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.
2226 lines
68 KiB
2226 lines
68 KiB
/*++
|
|
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ReadSchema.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of the helper functions that are used to read
|
|
schema information from the config stuctures into the metabase.
|
|
|
|
Author:
|
|
|
|
Varsha Jayasimha (varshaj) 30-Nov-1999
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
#include "precomp.hxx"
|
|
|
|
DWORD GetMetabaseFlags(DWORD i_CatalogFlag)
|
|
{
|
|
return i_CatalogFlag & 0x00000003; // First two bits represent metabase flag property.
|
|
}
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads the schema fromthe catalog into the schema tree.
|
|
|
|
Arguments:
|
|
|
|
[in] Storage pointer.
|
|
[in] Filetime pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadSchema(IIS_CRYPTO_STORAGE* i_pStorage,
|
|
FILETIME* i_pFileTime)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CMDBaseObject* pboReadSchema = NULL;
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
|
|
hr = ReadMetaObject(pboReadSchema,
|
|
(LPWSTR)g_wszSlashSchema,
|
|
i_pFileTime,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = ReadSchemaProperties(pboReadSchema,
|
|
i_pStorage);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
|
|
}
|
|
|
|
hr = ReadProperties(i_pStorage,
|
|
i_pFileTime);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = ReadClasses(i_pStorage,
|
|
i_pFileTime);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
|
|
} // ReadSchema
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads the properties in the root of the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object.
|
|
[in] Storage pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadSchemaProperties(CMDBaseObject* i_pboRead,
|
|
IIS_CRYPTO_STORAGE* i_pStorage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = ReadAdminACL(i_pboRead,
|
|
i_pStorage);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = ReadLargestMetaID(i_pboRead,
|
|
i_pStorage);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
|
|
} // ReadSchemaProperties
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Construct the Admin ACL property
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object.
|
|
[in] Storage pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadAdminACL(CMDBaseObject* i_pboRead,
|
|
IIS_CRYPTO_STORAGE* )
|
|
{
|
|
BOOL b = FALSE;
|
|
DWORD dwLength = 0;
|
|
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
PSECURITY_DESCRIPTOR outpSD = NULL;
|
|
DWORD cboutpSD = 0;
|
|
PACL pACLNew = NULL;
|
|
DWORD cbACL = 0;
|
|
PSID pAdminsSID = NULL;
|
|
PSID pEveryoneSID = NULL;
|
|
BOOL bWellKnownSID = FALSE;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwRes = 0;
|
|
DWORD dwMetaIDAdminACL = MD_ADMIN_ACL;
|
|
DWORD dwAttributesAdminACL = METADATA_INHERIT | METADATA_REFERENCE | METADATA_SECURE;
|
|
DWORD dwUserTypeAdminACL = IIS_MD_UT_SERVER;
|
|
DWORD dwDataTypeAdminACL = BINARY_METADATA;
|
|
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
|
|
//
|
|
// Initialize a new security descriptor
|
|
//
|
|
|
|
pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
|
|
SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
|
|
if (!pSD)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
InitializeSecurityDescriptor(pSD,
|
|
SECURITY_DESCRIPTOR_REVISION);
|
|
//
|
|
// Get Local Admins Sid
|
|
//
|
|
|
|
dwRes = GetPrincipalSID (L"Administrators",
|
|
&pAdminsSID,
|
|
&bWellKnownSID);
|
|
|
|
if(ERROR_SUCCESS != dwRes)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwRes);
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Get everyone Sid
|
|
//
|
|
|
|
GetPrincipalSID (L"Everyone", &pEveryoneSID, &bWellKnownSID);
|
|
|
|
//
|
|
// Initialize a new ACL, which only contains 2 aaace
|
|
//
|
|
|
|
cbACL = sizeof(ACL) +
|
|
(sizeof(ACCESS_ALLOWED_ACE) +
|
|
GetLengthSid(pAdminsSID) - sizeof(DWORD)) +
|
|
(sizeof(ACCESS_ALLOWED_ACE) +
|
|
GetLengthSid(pEveryoneSID) - sizeof(DWORD));
|
|
|
|
pACLNew = (PACL) LocalAlloc(LPTR,
|
|
cbACL);
|
|
|
|
if (!pACLNew)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
InitializeAcl(pACLNew,
|
|
cbACL,
|
|
ACL_REVISION);
|
|
|
|
AddAccessAllowedAce(pACLNew,
|
|
ACL_REVISION,
|
|
FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE,
|
|
pAdminsSID);
|
|
|
|
AddAccessAllowedAce(pACLNew,
|
|
ACL_REVISION,
|
|
FILE_GENERIC_READ,
|
|
pEveryoneSID);
|
|
|
|
//
|
|
// Add the ACL to the security descriptor
|
|
//
|
|
|
|
b = SetSecurityDescriptorDacl(pSD,
|
|
TRUE,
|
|
pACLNew,
|
|
FALSE);
|
|
|
|
if(!b)
|
|
{
|
|
hr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto exit;
|
|
}
|
|
|
|
b = SetSecurityDescriptorOwner(pSD,
|
|
pAdminsSID,
|
|
TRUE);
|
|
|
|
if(!b)
|
|
{
|
|
hr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto exit;
|
|
}
|
|
|
|
b = SetSecurityDescriptorGroup(pSD,
|
|
pAdminsSID,
|
|
TRUE);
|
|
|
|
if(!b)
|
|
{
|
|
hr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Security descriptor blob must be self relative
|
|
//
|
|
|
|
b = MakeSelfRelativeSD(pSD,
|
|
outpSD,
|
|
&cboutpSD);
|
|
|
|
outpSD = (PSECURITY_DESCRIPTOR)GlobalAlloc(GPTR,
|
|
cboutpSD);
|
|
|
|
if (!outpSD)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
b = MakeSelfRelativeSD(pSD,
|
|
outpSD,
|
|
&cboutpSD);
|
|
|
|
if(!b)
|
|
{
|
|
hr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// below this modify pSD to outpSD
|
|
//
|
|
|
|
//
|
|
// Apply the new security descriptor to the file
|
|
//
|
|
|
|
dwLength = GetSecurityDescriptorLength(outpSD);
|
|
|
|
//
|
|
// Apply the new security descriptor to the file
|
|
//
|
|
//
|
|
// Read all the property names. If the property is a flag, then read
|
|
// all the flag names as well.
|
|
//
|
|
|
|
a_pv[iMBProperty_Name] = NULL;
|
|
a_pv[iMBProperty_Location] = (LPWSTR)g_wszSlashSchema;
|
|
a_pv[iMBProperty_ID] = &dwMetaIDAdminACL;
|
|
a_pv[iMBProperty_Attributes] = &dwAttributesAdminACL;
|
|
a_pv[iMBProperty_UserType] = &dwUserTypeAdminACL;
|
|
a_pv[iMBProperty_Type] = &dwDataTypeAdminACL;
|
|
a_pv[iMBProperty_Value] = (LPBYTE)outpSD;
|
|
|
|
a_Size[iMBProperty_Value] = dwLength;
|
|
|
|
hr = ReadDataObject(i_pboRead,
|
|
a_pv,
|
|
a_Size,
|
|
NULL, // We should not be passing crypto object here, if we do it will attempt to decrypt it because the attribute is sucure.
|
|
TRUE);
|
|
|
|
|
|
exit :
|
|
|
|
//
|
|
//Cleanup:
|
|
// both of Administrators and Everyone are well-known SIDs, use FreeSid() to free them.
|
|
//
|
|
|
|
if (outpSD)
|
|
GlobalFree(outpSD);
|
|
|
|
if (pAdminsSID)
|
|
FreeSid(pAdminsSID);
|
|
if (pEveryoneSID)
|
|
FreeSid(pEveryoneSID);
|
|
if (pSD)
|
|
LocalFree((HLOCAL) pSD);
|
|
if (pACLNew)
|
|
LocalFree((HLOCAL) pACLNew);
|
|
|
|
return (hr);
|
|
}
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Helper function to read construct the Admin ACL.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
DWORD GetPrincipalSID (LPWSTR Principal,
|
|
PSID *Sid,
|
|
BOOL *pbWellKnownSID)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY SidIdentifierNTAuthority = SECURITY_NT_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY SidIdentifierWORLDAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
|
PSID_IDENTIFIER_AUTHORITY pSidIdentifierAuthority = NULL;
|
|
BYTE Count = 0;
|
|
DWORD dwRID[8];
|
|
|
|
*pbWellKnownSID = TRUE;
|
|
memset(&(dwRID[0]), 0, 8 * sizeof(DWORD));
|
|
if ( wcscmp(Principal,L"Administrators") == 0 )
|
|
{
|
|
//
|
|
// Administrators group
|
|
//
|
|
|
|
pSidIdentifierAuthority = &SidIdentifierNTAuthority;
|
|
Count = 2;
|
|
dwRID[0] = SECURITY_BUILTIN_DOMAIN_RID;
|
|
dwRID[1] = DOMAIN_ALIAS_RID_ADMINS;
|
|
|
|
}
|
|
else if ( wcscmp(Principal,L"System") == 0)
|
|
{
|
|
//
|
|
// SYSTEM
|
|
//
|
|
|
|
pSidIdentifierAuthority = &SidIdentifierNTAuthority;
|
|
Count = 1;
|
|
dwRID[0] = SECURITY_LOCAL_SYSTEM_RID;
|
|
|
|
}
|
|
else if ( wcscmp(Principal,L"Interactive") == 0)
|
|
{
|
|
//
|
|
// INTERACTIVE
|
|
//
|
|
|
|
pSidIdentifierAuthority = &SidIdentifierNTAuthority;
|
|
Count = 1;
|
|
dwRID[0] = SECURITY_INTERACTIVE_RID;
|
|
|
|
}
|
|
else if ( wcscmp(Principal,L"Everyone") == 0)
|
|
{
|
|
//
|
|
// Everyone
|
|
//
|
|
|
|
pSidIdentifierAuthority = &SidIdentifierWORLDAuthority;
|
|
Count = 1;
|
|
dwRID[0] = SECURITY_WORLD_RID;
|
|
|
|
}
|
|
else
|
|
{
|
|
*pbWellKnownSID = FALSE;
|
|
}
|
|
|
|
if (*pbWellKnownSID)
|
|
{
|
|
if ( !AllocateAndInitializeSid(pSidIdentifierAuthority,
|
|
(BYTE)Count,
|
|
dwRID[0],
|
|
dwRID[1],
|
|
dwRID[2],
|
|
dwRID[3],
|
|
dwRID[4],
|
|
dwRID[5],
|
|
dwRID[6],
|
|
dwRID[7],
|
|
Sid) )
|
|
return GetLastError();
|
|
} else {
|
|
// get regular account sid
|
|
DWORD sidSize;
|
|
WCHAR refDomain [256];
|
|
DWORD refDomainSize;
|
|
DWORD returnValue;
|
|
SID_NAME_USE snu;
|
|
|
|
sidSize = 0;
|
|
refDomainSize = 255;
|
|
|
|
LookupAccountNameW(NULL,
|
|
Principal,
|
|
*Sid,
|
|
&sidSize,
|
|
refDomain,
|
|
&refDomainSize,
|
|
&snu);
|
|
|
|
returnValue = GetLastError();
|
|
if (returnValue != ERROR_INSUFFICIENT_BUFFER)
|
|
return returnValue;
|
|
|
|
*Sid = (PSID) malloc (sidSize);
|
|
refDomainSize = 255;
|
|
|
|
if(NULL == *Sid)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else if (!LookupAccountNameW(NULL,
|
|
Principal,
|
|
*Sid,
|
|
&sidSize,
|
|
refDomain,
|
|
&refDomainSize,
|
|
&snu))
|
|
{
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads the largest metabase id available so far from the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object.
|
|
[in] Storage pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadLargestMetaID(CMDBaseObject* i_pboRead,
|
|
IIS_CRYPTO_STORAGE* i_pStorage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD* pdwLargestID = NULL;
|
|
DWORD dwLargestIDDefault = IIS_MD_ADSI_METAID_BEGIN;
|
|
|
|
DWORD dwMetaIDMetaID = MD_SCHEMA_METAID;
|
|
DWORD dwAttributesMetaID = METADATA_NO_ATTRIBUTES;
|
|
DWORD dwUserTypeMetaID = IIS_MD_UT_SERVER;
|
|
DWORD dwDataTypeMetaID = DWORD_METADATA;
|
|
ULONG iCol = iTABLEMETA_ExtendedVersion; // Largest ID is stored in this column
|
|
ULONG iRow = 0;
|
|
LPWSTR wszTable = wszTABLE_IIsConfigObject;
|
|
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTTableMetaForMetabaseTables->GetRowIndexByIdentity(NULL,
|
|
(LPVOID*)&wszTable,
|
|
&iRow);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = g_pGlobalISTHelper->m_pISTTableMetaForMetabaseTables->GetColumnValues(iRow,
|
|
1,
|
|
&iCol,
|
|
NULL,
|
|
(LPVOID*)&pdwLargestID);
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[SetLargestMetaID] Unable to read largest meta id from the meta tables. GetColumnValues failed with hr = 0x%x. Will default it to %d.\n",
|
|
hr,
|
|
dwLargestIDDefault));
|
|
|
|
hr = S_OK;
|
|
|
|
pdwLargestID = &dwLargestIDDefault;
|
|
}
|
|
|
|
a_pv[iMBProperty_Name] = NULL;
|
|
a_pv[iMBProperty_Location] = (LPWSTR)g_wszSlashSchema;
|
|
a_pv[iMBProperty_ID] = &dwMetaIDMetaID;
|
|
a_pv[iMBProperty_Attributes] = &dwAttributesMetaID;
|
|
a_pv[iMBProperty_UserType] = &dwUserTypeMetaID;
|
|
a_pv[iMBProperty_Type] = &dwDataTypeMetaID;
|
|
a_pv[iMBProperty_Value] = (LPBYTE)pdwLargestID;
|
|
|
|
a_Size[iMBProperty_Value] = sizeof(DWORD);
|
|
|
|
hr = ReadDataObject(i_pboRead,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads the properties into the schema tree.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object.
|
|
[in] Storage pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadProperties(IIS_CRYPTO_STORAGE* i_pStorage,
|
|
FILETIME* i_pFileTime)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CMDBaseObject* pboReadProperties = NULL;
|
|
CMDBaseObject* pboReadNames = NULL;
|
|
CMDBaseObject* pboReadTypes = NULL;
|
|
CMDBaseObject* pboReadDefaults = NULL;
|
|
ULONG i = 0;
|
|
ULONG iColIndex = 0;
|
|
LPVOID a_Identity[] = {(LPVOID)g_pGlobalISTHelper->m_wszTABLE_IIsConfigObject,
|
|
(LPVOID)&iColIndex
|
|
};
|
|
LPWSTR wszTable = NULL;
|
|
LPVOID a_pv[cCOLUMNMETA_NumberOfColumns];
|
|
ULONG a_Size[cCOLUMNMETA_NumberOfColumns];
|
|
ULONG a_iCol[] = {iCOLUMNMETA_Table,
|
|
iCOLUMNMETA_Index,
|
|
iCOLUMNMETA_InternalName,
|
|
iCOLUMNMETA_Type,
|
|
iCOLUMNMETA_MetaFlags,
|
|
iCOLUMNMETA_SchemaGeneratorFlags,
|
|
iCOLUMNMETA_DefaultValue,
|
|
iCOLUMNMETA_StartingNumber,
|
|
iCOLUMNMETA_EndingNumber,
|
|
iCOLUMNMETA_ID,
|
|
iCOLUMNMETA_UserType,
|
|
iCOLUMNMETA_Attributes
|
|
};
|
|
ULONG cCol = sizeof(a_iCol)/sizeof(ULONG);
|
|
|
|
//
|
|
// Initialize all the meta objects.
|
|
//
|
|
|
|
hr = ReadMetaObject(pboReadProperties,
|
|
(LPWSTR)g_wszSlashSchemaSlashProperties,
|
|
i_pFileTime,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = ReadMetaObject(pboReadNames,
|
|
(LPWSTR)g_wszSlashSchemaSlashPropertiesSlashNames,
|
|
i_pFileTime,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = ReadMetaObject(pboReadTypes,
|
|
(LPWSTR)g_wszSlashSchemaSlashPropertiesSlashTypes,
|
|
i_pFileTime,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = ReadMetaObject(pboReadDefaults,
|
|
(LPWSTR)g_wszSlashSchemaSlashPropertiesSlashDefaults,
|
|
i_pFileTime,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Get the row index of the first column and then iterate thru the table until
|
|
// e_st_nomorerows or the table difffers
|
|
//
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTColumnMeta->GetRowIndexByIdentity(NULL,
|
|
a_Identity,
|
|
&i);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// For each property in this table, construct the name, type and default
|
|
// in the metabase tree
|
|
//
|
|
|
|
for(;;i++)
|
|
{
|
|
hr = g_pGlobalISTHelper->m_pISTColumnMeta->GetColumnValues(i,
|
|
cCol,
|
|
a_iCol,
|
|
a_Size,
|
|
a_pv);
|
|
|
|
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if(NULL == wszTable)
|
|
{
|
|
wszTable = (LPWSTR)a_pv[iCOLUMNMETA_Table];
|
|
}
|
|
|
|
if(wszTable != (LPWSTR)a_pv[iCOLUMNMETA_Table])
|
|
{
|
|
//
|
|
// reached another table break
|
|
//
|
|
break;
|
|
}
|
|
|
|
MD_ASSERT(NULL != (DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags]);
|
|
|
|
if(fCOLUMNMETA_HIDDEN == (fCOLUMNMETA_HIDDEN & (*(DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags])))
|
|
{
|
|
//
|
|
// Do not read hidden properties. All these properties have the
|
|
// "HIDDEN" schemagenerator flag set on them.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
hr = ReadPropertyNames(pboReadNames,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = ReadPropertyTypes(pboReadTypes,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if((*(DWORD*)a_pv[iCOLUMNMETA_MetaFlags]) & fCOLUMNMETA_FLAG)
|
|
{
|
|
hr = ReadAllFlags(i_pStorage,
|
|
pboReadTypes,
|
|
pboReadNames,
|
|
pboReadDefaults,
|
|
*(DWORD*)a_pv[iCOLUMNMETA_Index],
|
|
*(DWORD*)a_pv[iCOLUMNMETA_ID],
|
|
GetMetabaseFlags(*(DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags]),
|
|
*(DWORD*)a_pv[iCOLUMNMETA_Attributes],
|
|
*(DWORD*)a_pv[iCOLUMNMETA_UserType],
|
|
(*(DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags]) & fCOLUMNMETA_MULTISTRING);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
hr = ReadPropertyDefaults(pboReadDefaults,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
|
|
} // ReadProperties
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads names of properties into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object.
|
|
[in] Array that hold catalog schema information about the property.
|
|
[in] Array that holds count of bytes for the above.
|
|
[in] Storage pointer.
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadPropertyNames(CMDBaseObject* i_pboRead,
|
|
LPVOID* i_apv,
|
|
ULONG* i_aSize,
|
|
IIS_CRYPTO_STORAGE* i_pStorage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
DWORD dwAttributes = METADATA_NO_ATTRIBUTES;
|
|
DWORD dwType = STRING_METADATA;
|
|
DWORD dwUserType = IIS_MD_UT_SERVER;
|
|
|
|
//
|
|
// Read all the property names. If the property is a flag, then read
|
|
// all the flag names as well.
|
|
//
|
|
|
|
a_pv[iMBProperty_Name] = i_apv[iCOLUMNMETA_InternalName];
|
|
a_pv[iMBProperty_Location] = (LPWSTR)g_wszSlashSchemaSlashPropertiesSlashNames;
|
|
a_pv[iMBProperty_ID] = i_apv[iCOLUMNMETA_ID];
|
|
a_pv[iMBProperty_Attributes] = &dwAttributes;
|
|
a_pv[iMBProperty_UserType] = &dwUserType;
|
|
a_pv[iMBProperty_Type] = &dwType;
|
|
a_pv[iMBProperty_Value] = i_apv[iCOLUMNMETA_InternalName];
|
|
|
|
a_Size[iMBProperty_Value] = i_aSize[iCOLUMNMETA_InternalName];
|
|
|
|
hr = ReadDataObject(i_pboRead,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
|
|
return hr;
|
|
|
|
} // ReadPropertyNames
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads names of flags into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object.
|
|
[in] Array that hold catalog schema information about the flags.
|
|
[in] Array that holds count of bytes for the above.
|
|
[in] Storage pointer.
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadFlagNames(CMDBaseObject* i_pboRead,
|
|
LPVOID* i_apv,
|
|
ULONG* i_aSize,
|
|
IIS_CRYPTO_STORAGE* i_pStorage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
DWORD dwAttributes = METADATA_NO_ATTRIBUTES;
|
|
DWORD dwType = STRING_METADATA;
|
|
DWORD dwUserType = IIS_MD_UT_SERVER;
|
|
|
|
//
|
|
// Read all the property names. If the property is a flag, then read
|
|
// all the flag names as well.
|
|
//
|
|
|
|
a_pv[iMBProperty_Name] = i_apv[iTAGMETA_InternalName];
|
|
a_pv[iMBProperty_Location] = (LPWSTR)g_wszSlashSchemaSlashPropertiesSlashNames;
|
|
a_pv[iMBProperty_ID] = i_apv[iTAGMETA_ID];
|
|
a_pv[iMBProperty_Attributes] = &dwAttributes;
|
|
a_pv[iMBProperty_UserType] = &dwUserType;
|
|
a_pv[iMBProperty_Type] = &dwType;
|
|
a_pv[iMBProperty_Value] = i_apv[iTAGMETA_InternalName];
|
|
|
|
a_Size[iMBProperty_Value] = i_aSize[iTAGMETA_InternalName];
|
|
|
|
hr = ReadDataObject(i_pboRead,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
return hr;
|
|
|
|
} // ReadFlagNames
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads type information about the properties into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object.
|
|
[in] Array that hold catalog schema information about the property.
|
|
[in] Array that holds count of bytes for the above.
|
|
[in] Storage pointer.
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadPropertyTypes(CMDBaseObject* i_pboRead,
|
|
LPVOID* i_apv,
|
|
ULONG* ,
|
|
IIS_CRYPTO_STORAGE* i_pStorage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
DWORD dwAttributes = METADATA_NO_ATTRIBUTES;
|
|
DWORD dwType = BINARY_METADATA;
|
|
DWORD dwUserType = IIS_MD_UT_SERVER;
|
|
PropValue propVal;
|
|
DWORD dwMetaFlagsEx = *(DWORD*)(i_apv[iCOLUMNMETA_SchemaGeneratorFlags]);
|
|
|
|
memset(&propVal, 0, sizeof(PropValue));
|
|
|
|
//
|
|
// Read all the property type. If the property is a flag, then read
|
|
// all the type for the flag names as well.
|
|
//
|
|
|
|
propVal.dwMetaID = *(DWORD*)(i_apv[iCOLUMNMETA_ID]);
|
|
propVal.dwPropID = *(DWORD*)(i_apv[iCOLUMNMETA_ID]); // Note: This is different from the meta id if it is a flag.
|
|
propVal.dwSynID = SynIDFromMetaFlagsEx(dwMetaFlagsEx);
|
|
propVal.dwMetaType = GetMetabaseType(*(DWORD*)(i_apv[iCOLUMNMETA_Type]),
|
|
*(DWORD*)(i_apv[iCOLUMNMETA_MetaFlags]));
|
|
|
|
if(DWORD_METADATA == propVal.dwMetaType)
|
|
{
|
|
propVal.dwMinRange = *(DWORD*)(i_apv[iCOLUMNMETA_StartingNumber]);
|
|
propVal.dwMaxRange = *(DWORD*)(i_apv[iCOLUMNMETA_EndingNumber]);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Ensure that non-DWORDs have no starting/ending numbers
|
|
//
|
|
|
|
propVal.dwMinRange = 0;
|
|
propVal.dwMaxRange = 0;
|
|
}
|
|
|
|
propVal.dwFlags = GetMetabaseFlags(*(DWORD*)i_apv[iCOLUMNMETA_SchemaGeneratorFlags]);
|
|
propVal.dwMask = 0; // This gets filled in for flag values only.
|
|
propVal.dwMetaFlags = *(DWORD*)(i_apv[iCOLUMNMETA_Attributes]);
|
|
propVal.dwUserGroup = *(DWORD*)(i_apv[iCOLUMNMETA_UserType]);
|
|
propVal.fMultiValued = ((*(DWORD*)i_apv[iCOLUMNMETA_MetaFlags])&fCOLUMNMETA_MULTISTRING)?1:0; // Ensure that this gets set in the schema as multivalued
|
|
propVal.dwDefault = 0;
|
|
propVal.szDefault = NULL;
|
|
|
|
a_pv[iMBProperty_Name] = i_apv[iCOLUMNMETA_InternalName];
|
|
a_pv[iMBProperty_Location] = (LPWSTR)g_wszSlashSchemaSlashPropertiesSlashTypes;
|
|
a_pv[iMBProperty_ID] = i_apv[iCOLUMNMETA_ID];
|
|
a_pv[iMBProperty_Attributes] = &dwAttributes;
|
|
a_pv[iMBProperty_UserType] = &dwUserType;
|
|
a_pv[iMBProperty_Type] = &dwType;
|
|
a_pv[iMBProperty_Value] = (LPVOID)&propVal;
|
|
|
|
a_Size[iMBProperty_Value] = sizeof(PropValue);
|
|
|
|
hr = ReadDataObject(i_pboRead,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
return hr;
|
|
|
|
} // ReadPropertyTypes
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads all flag properties into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Storage pointer.
|
|
[in] Pointer to the metabase object that holds the types tree.
|
|
[in] Pointer to the metabase object that holds the names tree.
|
|
[in] Pointer to the metabase object that holds the default value tree.
|
|
[in] Column index of the parent flag property.
|
|
[in] Meta Id of the parent flag property.
|
|
[in] Flags of the parent flag property.
|
|
[in] Attribute of the parent flag property.
|
|
[in] Usertype of the parent flag property.
|
|
[in] Multivalued attribute of the parent flag property.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadAllFlags(IIS_CRYPTO_STORAGE* i_pStorage,
|
|
CMDBaseObject* i_pboReadType,
|
|
CMDBaseObject* i_pboReadName,
|
|
CMDBaseObject* i_pboReadDefault,
|
|
DWORD i_dwColumnIndex,
|
|
DWORD i_dwMetaID,
|
|
DWORD i_dwFlags,
|
|
DWORD i_dwAttributes,
|
|
DWORD i_dwUserType,
|
|
DWORD i_dwMultivalued)
|
|
{
|
|
ULONG i = 0;
|
|
ULONG iStartRow = 0;
|
|
HRESULT hr = S_OK;
|
|
LPVOID a_pvSearch[cTAGMETA_NumberOfColumns];
|
|
ULONG aColSearch[] = {iTAGMETA_Table,
|
|
iTAGMETA_ColumnIndex
|
|
};
|
|
ULONG cColSearch = sizeof(aColSearch)/sizeof(ULONG);
|
|
LPWSTR wszTable = NULL;
|
|
|
|
|
|
a_pvSearch[iTAGMETA_Table] = g_pGlobalISTHelper->m_wszTABLE_IIsConfigObject;
|
|
a_pvSearch[iTAGMETA_ColumnIndex] = (LPVOID)&i_dwColumnIndex;
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTTagMetaByTableAndColumnIndex->GetRowIndexBySearch(iStartRow,
|
|
cColSearch,
|
|
aColSearch,
|
|
NULL,
|
|
a_pvSearch,
|
|
&iStartRow);
|
|
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
goto exit;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[ReadAllFlags] Unable to read flags. GetRowIndexBySearch failed with hr = 0x%x.\n",
|
|
hr));
|
|
goto exit;
|
|
}
|
|
|
|
|
|
for(i=iStartRow;;i++)
|
|
{
|
|
|
|
LPVOID a_pv[cTAGMETA_NumberOfColumns];
|
|
ULONG a_Size[cTAGMETA_NumberOfColumns];
|
|
ULONG a_iCol[] = {iTAGMETA_Table,
|
|
iTAGMETA_ColumnIndex,
|
|
iTAGMETA_InternalName,
|
|
iTAGMETA_Value,
|
|
iTAGMETA_ID
|
|
};
|
|
ULONG cCol = sizeof(a_iCol)/sizeof(ULONG);
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTTagMetaByTableAndColumnIndex->GetColumnValues(i,
|
|
cCol,
|
|
a_iCol,
|
|
a_Size,
|
|
a_pv);
|
|
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if(NULL == wszTable)
|
|
{
|
|
// Save the table name from the read cache so that you can do a pointer compare below.
|
|
wszTable = (LPWSTR)a_pv[iTAGMETA_Table];
|
|
}
|
|
|
|
if((wszTable != a_pv[iTAGMETA_Table]) ||
|
|
(i_dwColumnIndex != *(DWORD*)a_pv[iTAGMETA_ColumnIndex])
|
|
)
|
|
{
|
|
//
|
|
// Done with all tags of this column, in this table hence exit.
|
|
//
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
hr = ReadFlagTypes(i_pboReadType,
|
|
i_pStorage,
|
|
i_dwMetaID,
|
|
i_dwFlags,
|
|
i_dwAttributes,
|
|
i_dwUserType,
|
|
i_dwMultivalued,
|
|
a_pv,
|
|
a_Size);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = ReadFlagNames(i_pboReadName,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = ReadFlagDefaults(i_pboReadDefault,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
|
|
} // ReadAllFlagTypes
|
|
|
|
#define IIS_SYNTAX_ID_BOOL_BITMASK 7
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads all flag type information into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object that holds the types tree.
|
|
[in] Storage pointer.
|
|
[in] Meta Id of the parent flag property.
|
|
[in] Flags of the parent flag property.
|
|
[in] Attribute of the parent flag property.
|
|
[in] Usertype of the parent flag property.
|
|
[in] Multivalued attribute of the parent flag property.
|
|
[in] Array that hold catalog schema information about the flag.
|
|
[in] Array that holds count of bytes for the above.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadFlagTypes(CMDBaseObject* i_pboRead,
|
|
IIS_CRYPTO_STORAGE* i_pStorage,
|
|
DWORD i_dwMetaID,
|
|
DWORD i_dwFlags,
|
|
DWORD i_dwAttributes,
|
|
DWORD i_dwUserType,
|
|
DWORD i_dwMultivalued,
|
|
LPVOID* i_apv,
|
|
ULONG* )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
DWORD dwAttributes = METADATA_NO_ATTRIBUTES;
|
|
DWORD dwType = BINARY_METADATA;
|
|
DWORD dwUserType = IIS_MD_UT_SERVER;
|
|
PropValue propVal;
|
|
DWORD dwFlagSynID = IIS_SYNTAX_ID_BOOL_BITMASK;
|
|
DWORD dwFlagType = DWORD_METADATA;
|
|
|
|
memset(&propVal, 0, sizeof(PropValue));
|
|
|
|
//
|
|
// Read all the property type. If the property is a flag, then read
|
|
// all the type for the flag names as well.
|
|
//
|
|
|
|
propVal.dwMetaID = i_dwMetaID;
|
|
propVal.dwPropID = *(DWORD*)(i_apv[iTAGMETA_ID]); // This is different from the meta id if it is a flag.
|
|
propVal.dwSynID = dwFlagSynID;
|
|
propVal.dwMetaType = dwFlagType;
|
|
|
|
propVal.dwMaxRange = 0;
|
|
propVal.dwMinRange = 0;
|
|
|
|
propVal.dwFlags = i_dwFlags; // Set to parent prop flags
|
|
propVal.dwMask = *(DWORD*)(i_apv[iTAGMETA_Value]); // Set to parent prop flags
|
|
propVal.dwMetaFlags = i_dwAttributes; // Set to parent prop flags
|
|
propVal.dwUserGroup = i_dwUserType; // Set to parent prop flags
|
|
propVal.fMultiValued = i_dwMultivalued; // Set to parent prop flags
|
|
propVal.dwDefault = 0;
|
|
propVal.szDefault = NULL;
|
|
|
|
a_pv[iMBProperty_Name] = NULL;
|
|
a_pv[iMBProperty_Location] = (LPWSTR)g_wszSlashSchemaSlashPropertiesSlashTypes;
|
|
a_pv[iMBProperty_ID] = i_apv[iTAGMETA_ID];
|
|
a_pv[iMBProperty_Attributes] = &dwAttributes;
|
|
a_pv[iMBProperty_UserType] = &dwUserType;
|
|
a_pv[iMBProperty_Type] = &dwType;
|
|
a_pv[iMBProperty_Value] = (LPVOID)&propVal;
|
|
|
|
a_Size[iMBProperty_Value] = sizeof(PropValue);
|
|
|
|
hr = ReadDataObject(i_pboRead,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
return hr;
|
|
|
|
} // ReadFlagTypes
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads property defaults into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object that holds property defaults.
|
|
[in] Array that hold catalog schema information about the property.
|
|
[in] Array that holds count of bytes for the above.
|
|
[in] Storage pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadPropertyDefaults(CMDBaseObject* i_pboRead,
|
|
LPVOID* i_apv,
|
|
ULONG* i_aSize,
|
|
IIS_CRYPTO_STORAGE* i_pStorage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
DWORD dwType = GetMetabaseType(*(DWORD*)i_apv[iCOLUMNMETA_Type],
|
|
*(DWORD*)i_apv[iCOLUMNMETA_MetaFlags]);
|
|
LPVOID pvValue = NULL;
|
|
ULONG cbSize = NULL;
|
|
DWORD dwZero = 0;
|
|
DWORD dwAttributes = METADATA_NO_ATTRIBUTES;
|
|
|
|
//
|
|
// Read all the property names. If the property is a flag, then read
|
|
// all the flag names as well.
|
|
//
|
|
|
|
a_pv[iMBProperty_Name] = i_apv[iCOLUMNMETA_InternalName];
|
|
a_pv[iMBProperty_Location] = (LPWSTR)g_wszSlashSchemaSlashPropertiesSlashDefaults;
|
|
a_pv[iMBProperty_ID] = i_apv[iCOLUMNMETA_ID];
|
|
a_pv[iMBProperty_Attributes] = &dwAttributes; // NO_ATTRIBUTES since it will attempt to decrypt.
|
|
a_pv[iMBProperty_UserType] = i_apv[iCOLUMNMETA_UserType];
|
|
a_pv[iMBProperty_Type] = &dwType;
|
|
|
|
if((dwType == DWORD_METADATA) && (NULL == i_apv[iCOLUMNMETA_DefaultValue]))
|
|
{
|
|
pvValue = &dwZero;
|
|
cbSize = sizeof(DWORD);
|
|
}
|
|
else if(((dwType == MULTISZ_METADATA) || (dwType == STRING_METADATA) || (dwType == EXPANDSZ_METADATA)) &&
|
|
((NULL == i_apv[iCOLUMNMETA_DefaultValue]) || (0 == *(BYTE*)(i_apv[iCOLUMNMETA_DefaultValue])))
|
|
)
|
|
{
|
|
if(dwType == MULTISZ_METADATA)
|
|
{
|
|
pvValue = g_wszEmptyMultisz; // Two nulls.
|
|
cbSize = g_cchEmptyMultisz * sizeof(WCHAR);
|
|
}
|
|
else if((dwType == STRING_METADATA) || (dwType == EXPANDSZ_METADATA))
|
|
{
|
|
pvValue = g_wszEmptyWsz;
|
|
cbSize = g_cchEmptyWsz * sizeof(WCHAR); // One null.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pvValue = i_apv[iCOLUMNMETA_DefaultValue];
|
|
cbSize = i_aSize[iCOLUMNMETA_DefaultValue];
|
|
}
|
|
|
|
a_pv[iMBProperty_Value] = pvValue;
|
|
a_Size[iMBProperty_Value] = cbSize;
|
|
|
|
hr = ReadDataObject(i_pboRead,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[ReadPropertyDefaults] Could not read property %s:%d.\npv=%d.\ncb=%d.\n",
|
|
i_apv[iCOLUMNMETA_InternalName],
|
|
*(DWORD*)i_apv[iCOLUMNMETA_ID],
|
|
pvValue,
|
|
cbSize));
|
|
|
|
if(NULL != pvValue)
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[ReadPropertyDefaults]*pv=%d.\n",
|
|
*(WORD*)pvValue));
|
|
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
} // ReadPropertyDefaults
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads all flag defaults into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Pointer to the metabase object that holds the defaults.
|
|
[in] Array that hold catalog schema information about the flag.
|
|
[in] Array that holds count of bytes for the above.
|
|
[in] Storage pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadFlagDefaults(CMDBaseObject* i_pboRead,
|
|
LPVOID* i_apv,
|
|
ULONG* ,
|
|
IIS_CRYPTO_STORAGE* i_pStorage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
DWORD dwAttributes = METADATA_NO_ATTRIBUTES;
|
|
DWORD dwType = DWORD_METADATA;
|
|
DWORD dwUserType = IIS_MD_UT_SERVER;
|
|
|
|
//
|
|
// TODO: Is this a correct assumption? I noticed that default values for
|
|
// flags was being set to 0 or -1. This doesnt make any sense. How can a
|
|
// flag have a default value other than its own value? This is not
|
|
//captured in our new schema, so just putting it as 0.
|
|
//
|
|
|
|
DWORD dwFlagDefaults = 0;
|
|
|
|
//
|
|
// Read all the property names. If the property is a flag, then read
|
|
// all the flag names as well.
|
|
//
|
|
|
|
a_pv[iMBProperty_Name] = i_apv[iTAGMETA_InternalName];
|
|
a_pv[iMBProperty_Location] = (LPWSTR)g_wszSlashSchemaSlashPropertiesSlashDefaults;
|
|
a_pv[iMBProperty_ID] = i_apv[iTAGMETA_ID];
|
|
a_pv[iMBProperty_Attributes] = &dwAttributes;
|
|
a_pv[iMBProperty_UserType] = &dwUserType;
|
|
a_pv[iMBProperty_Type] = &dwType;
|
|
a_pv[iMBProperty_Value] = &dwFlagDefaults;
|
|
|
|
a_Size[iMBProperty_Value] = sizeof(DWORD);
|
|
|
|
hr = ReadDataObject(i_pboRead,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
return hr;
|
|
|
|
} // ReadFlagDefaults
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads all classes into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Storage pointer.
|
|
[in] Filetime pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadClasses(IIS_CRYPTO_STORAGE* i_pStorage,
|
|
FILETIME* i_pFileTime)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CMDBaseObject* pboReadClasses = NULL;
|
|
ULONG i = 0;
|
|
LPVOID a_pv[cTABLEMETA_NumberOfColumns];
|
|
ULONG a_Size[cTABLEMETA_NumberOfColumns];
|
|
ULONG a_iCol[] = {iTABLEMETA_InternalName,
|
|
iTABLEMETA_MetaFlags,
|
|
iTABLEMETA_SchemaGeneratorFlags,
|
|
iTABLEMETA_ContainerClassList
|
|
};
|
|
ULONG cCol = sizeof(a_iCol)/sizeof(ULONG);
|
|
|
|
hr = ReadMetaObject(pboReadClasses,
|
|
(LPWSTR)g_wszSlashSchemaSlashClasses,
|
|
i_pFileTime,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
for(i=0;;i++)
|
|
{
|
|
hr = g_pGlobalISTHelper->m_pISTTableMetaForMetabaseTables->GetColumnValues(i,
|
|
cCol,
|
|
a_iCol,
|
|
a_Size,
|
|
a_pv);
|
|
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
MD_ASSERT(NULL != (DWORD*)a_pv[iTABLEMETA_MetaFlags]);
|
|
|
|
if(fTABLEMETA_HIDDEN == (fTABLEMETA_HIDDEN & (*(DWORD*)a_pv[iTABLEMETA_MetaFlags])))
|
|
{
|
|
//
|
|
// Do not read hidden classes. All these classes have the "HIDDEN" MetaFlag set on them.
|
|
// Eg: IIsConfigObject,MetabaseBaseClass, MBProperty, MBPropertyDiff, IIsInheritedProperties
|
|
//
|
|
continue;
|
|
}
|
|
|
|
hr = ReadClass(a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
i_pFileTime);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[ReadClasses] Could not read information for class: %s.\nReadClass failed with hr=0x%x.\n",
|
|
a_pv[iTABLEMETA_InternalName],
|
|
hr));
|
|
}
|
|
|
|
}
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
|
|
} // ReadClasses
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Reads a class into the schema.
|
|
|
|
Arguments:
|
|
|
|
[in] Array that hold catalog schema information about the class.
|
|
[in] Array that holds count of bytes for the above.
|
|
[in] Storage pointer.
|
|
[in] Filetime pointer.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT ReadClass(LPVOID* i_apv,
|
|
ULONG* ,
|
|
IIS_CRYPTO_STORAGE* i_pStorage,
|
|
FILETIME* i_pFileTime)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CMDBaseObject* pboReadClass = NULL;
|
|
WCHAR wszClassPathFixed[MAX_PATH];
|
|
ULONG cchClassPath = 0;
|
|
WCHAR* wszClassPath = wszClassPathFixed;
|
|
WCHAR* wszEnd = NULL;
|
|
ULONG cchClassName = (ULONG)wcslen((LPWSTR)i_apv[iTABLEMETA_InternalName]);
|
|
DWORD dwID = 0;
|
|
DWORD dwType = DWORD_METADATA;
|
|
DWORD dwUserType = IIS_MD_UT_SERVER;
|
|
DWORD dwAttributes = METADATA_NO_ATTRIBUTES;
|
|
DWORD dwValue = 0;
|
|
LPVOID a_pv[cMBProperty_NumberOfColumns];
|
|
ULONG a_Size[cMBProperty_NumberOfColumns];
|
|
LPWSTR wszManditory = NULL;
|
|
LPWSTR wszOptional = NULL;
|
|
|
|
//
|
|
// Construct the ClassPath and read the meta object.
|
|
//
|
|
|
|
cchClassPath = g_cchSlashSchemaSlashClasses +
|
|
g_cchSlash +
|
|
cchClassName;
|
|
|
|
if((cchClassPath + 1) > MAX_PATH)
|
|
{
|
|
wszClassPath = new WCHAR[cchClassPath + 1];
|
|
if(NULL == wszClassPath)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
wszEnd = wszClassPath;
|
|
memcpy(wszEnd, g_wszSlashSchemaSlashClasses, g_cchSlashSchemaSlashClasses*sizeof(WCHAR));
|
|
wszEnd = wszEnd + g_cchSlashSchemaSlashClasses;
|
|
memcpy(wszEnd, g_wszSlash, g_cchSlash*sizeof(WCHAR));
|
|
wszEnd = wszEnd + g_cchSlash;
|
|
memcpy(wszEnd, i_apv[iTABLEMETA_InternalName], cchClassName*sizeof(WCHAR));
|
|
wszEnd = wszEnd + cchClassName;
|
|
*wszEnd = L'\0';
|
|
|
|
hr = ReadMetaObject(pboReadClass,
|
|
wszClassPath,
|
|
i_pFileTime,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[ReadClasses] ReadMetaObject for class: %s failed with hr=0x%x.\n",
|
|
wszClassPath,
|
|
hr));
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Initialize a_pv to write data objects
|
|
//
|
|
|
|
a_pv[iMBProperty_Name] = NULL;
|
|
a_pv[iMBProperty_ID] = &dwID;
|
|
a_pv[iMBProperty_Location] = wszClassPath;
|
|
a_pv[iMBProperty_Attributes] = &dwAttributes;
|
|
a_pv[iMBProperty_UserType] = &dwUserType;
|
|
a_pv[iMBProperty_Type] = &dwType;
|
|
|
|
//
|
|
// Read the data object that corresponds to container class property
|
|
//
|
|
|
|
dwID = MD_SCHEMA_CLASS_CONTAINER;
|
|
dwType = DWORD_METADATA;
|
|
dwValue = ((*(DWORD*)(i_apv[iTABLEMETA_SchemaGeneratorFlags])) & fTABLEMETA_CONTAINERCLASS)?1:0; // Need to set true or false.
|
|
a_pv[iMBProperty_Value] = &dwValue;
|
|
a_Size[iMBProperty_Value] = sizeof(DWORD);
|
|
|
|
hr = ReadDataObject(pboReadClass,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[ReadClasses] ReadDataObject for class: %s, property: Container failed with hr=0x%x.\n",
|
|
wszClassPath,
|
|
hr));
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Read the data object that corresponds to container class list property
|
|
//
|
|
|
|
dwID = MD_SCHEMA_CLASS_CONTAINMENT;
|
|
dwType = STRING_METADATA;
|
|
|
|
if(NULL == i_apv[iTABLEMETA_ContainerClassList])
|
|
{
|
|
a_pv[iMBProperty_Value] = g_wszEmptyWsz;
|
|
a_Size[iMBProperty_Value] = (g_cchEmptyWsz)*sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
a_pv[iMBProperty_Value] = i_apv[iTABLEMETA_ContainerClassList];
|
|
a_Size[iMBProperty_Value] = (ULONG)(wcslen((LPWSTR)i_apv[iTABLEMETA_ContainerClassList])+1)*sizeof(WCHAR);
|
|
}
|
|
|
|
hr = ReadDataObject(pboReadClass,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Read properties for this class.
|
|
//
|
|
|
|
hr = GetProperties((LPCWSTR)i_apv[iTABLEMETA_InternalName],
|
|
&wszOptional,
|
|
&wszManditory);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Read data object that corresponds to optional property list
|
|
//
|
|
|
|
dwID = MD_SCHEMA_CLASS_OPT_PROPERTIES;
|
|
dwType = STRING_METADATA;
|
|
|
|
if(NULL == wszOptional)
|
|
{
|
|
a_pv[iMBProperty_Value] = g_wszEmptyWsz;
|
|
a_Size[iMBProperty_Value] = (g_cchEmptyWsz)*sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
a_pv[iMBProperty_Value] = wszOptional;
|
|
a_Size[iMBProperty_Value] = (ULONG)(wcslen(wszOptional)+1)*sizeof(WCHAR);
|
|
}
|
|
|
|
// DBGINFOW((DBG_CONTEXT,
|
|
// L"[ReadClasses] Class: %s has Optional Properties: %s.\n",
|
|
// wszClassPath,
|
|
// a_pv[iMBProperty_Value]));
|
|
|
|
hr = ReadDataObject(pboReadClass,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Read data object that corresponds to maditory property list
|
|
//
|
|
|
|
dwID = MD_SCHEMA_CLASS_MAND_PROPERTIES;
|
|
dwType = STRING_METADATA;
|
|
|
|
if(NULL == wszManditory)
|
|
{
|
|
a_pv[iMBProperty_Value] = g_wszEmptyWsz;
|
|
a_Size[iMBProperty_Value] = (g_cchEmptyWsz)*sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
a_pv[iMBProperty_Value] = wszManditory;
|
|
a_Size[iMBProperty_Value] = (ULONG)(wcslen(wszManditory)+1)*sizeof(WCHAR);
|
|
}
|
|
|
|
|
|
// DBGINFOW((DBG_CONTEXT,
|
|
// L"[ReadClasses] Class: %s has Manditory Properties: %s.\n",
|
|
// wszClassPath,
|
|
// a_pv[iMBProperty_Value]));
|
|
|
|
hr = ReadDataObject(pboReadClass,
|
|
a_pv,
|
|
a_Size,
|
|
i_pStorage,
|
|
TRUE);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
if(wszClassPathFixed != wszClassPath)
|
|
{
|
|
delete [] wszClassPath;
|
|
wszClassPath = NULL;
|
|
}
|
|
|
|
if(NULL != wszManditory)
|
|
{
|
|
delete [] wszManditory;
|
|
wszManditory = NULL;
|
|
}
|
|
|
|
if(NULL != wszOptional)
|
|
{
|
|
delete [] wszOptional;
|
|
wszOptional = NULL;
|
|
}
|
|
|
|
return hr;
|
|
|
|
} // ReadClasses
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Given a class it constructs the optional and manditory property lists
|
|
|
|
Arguments:
|
|
|
|
[in] Class name.
|
|
[out] Optional properties.
|
|
[out] Manditory properties.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT GetProperties(LPCWSTR i_wszTable,
|
|
LPWSTR* o_pwszOptional,
|
|
LPWSTR* o_pwszManditory)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
LPVOID a_pv[cCOLUMNMETA_NumberOfColumns];
|
|
ULONG a_iCol[] = { iCOLUMNMETA_Table,
|
|
iCOLUMNMETA_InternalName,
|
|
iCOLUMNMETA_Index,
|
|
iCOLUMNMETA_MetaFlags,
|
|
iCOLUMNMETA_SchemaGeneratorFlags,
|
|
iCOLUMNMETA_ID
|
|
};
|
|
ULONG cCol = sizeof(a_iCol)/sizeof(ULONG);
|
|
WCHAR* wszEndOpt = NULL;
|
|
WCHAR* wszEndMand = NULL;
|
|
ULONG cchOptional = 0;
|
|
ULONG cchManditory = 0;
|
|
ULONG iColIndex = 0;
|
|
LPVOID a_Identity[] = {(LPVOID)i_wszTable,
|
|
(LPVOID)&iColIndex
|
|
};
|
|
LPWSTR wszTable = NULL;
|
|
ULONG iStartRow = 0;
|
|
ULONG i = 0;
|
|
|
|
MD_ASSERT(NULL != o_pwszOptional);
|
|
MD_ASSERT(NULL != o_pwszManditory);
|
|
|
|
*o_pwszOptional = NULL;
|
|
*o_pwszManditory = NULL;
|
|
|
|
//
|
|
// Get the row index of the first column and then iterate thru the table until
|
|
// e_st_nomorerows or the table difffers
|
|
//
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTColumnMeta->GetRowIndexByIdentity(NULL,
|
|
a_Identity,
|
|
&iStartRow);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Count the optional and maditory property lengths.
|
|
//
|
|
|
|
for(i=iStartRow;;i++)
|
|
{
|
|
ULONG* pcCh = NULL;
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTColumnMeta->GetColumnValues(i,
|
|
cCol,
|
|
a_iCol,
|
|
NULL,
|
|
a_pv);
|
|
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[GetProperties] GetColumnValues (count) failed with hr = 0x%x. Index: %d\n",
|
|
hr, i));
|
|
goto exit;
|
|
}
|
|
|
|
if(NULL == wszTable)
|
|
{
|
|
// Save the table name from the read cache so that you can do a pointer compare below.
|
|
wszTable = (LPWSTR)a_pv[iCOLUMNMETA_Table];
|
|
}
|
|
|
|
if(wszTable != a_pv[iCOLUMNMETA_Table])
|
|
{
|
|
//
|
|
// reached another table break
|
|
//
|
|
break;
|
|
}
|
|
|
|
if(MD_LOCATION == *(DWORD*)a_pv[iCOLUMNMETA_ID])
|
|
{
|
|
//
|
|
// Do NOT read in the location property.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
MD_ASSERT(NULL != (DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags]);
|
|
|
|
if(fCOLUMNMETA_HIDDEN == (fCOLUMNMETA_HIDDEN & (*(DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags])))
|
|
{
|
|
//
|
|
// Do not read hidden properties. All these properties have the
|
|
// "HIDDEN" schemagenerator flag set on them.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
if((*(DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags]) & fCOLUMNMETA_MANDATORY)
|
|
{
|
|
cchManditory = cchManditory + (ULONG)wcslen((LPWSTR)a_pv[iCOLUMNMETA_InternalName]) + 1 ; // For comma
|
|
pcCh = &cchManditory;
|
|
}
|
|
else
|
|
{
|
|
cchOptional = cchOptional + (ULONG)wcslen((LPWSTR)a_pv[iCOLUMNMETA_InternalName]) + 1; // For comma
|
|
pcCh = &cchOptional;
|
|
}
|
|
|
|
if((*(DWORD*)a_pv[iCOLUMNMETA_MetaFlags]) & fCOLUMNMETA_FLAG)
|
|
{
|
|
hr = AddFlagValuesToPropertyList((LPWSTR)i_wszTable,
|
|
*(DWORD*)a_pv[iCOLUMNMETA_Index],
|
|
pcCh,
|
|
NULL);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[GetProperties] AddFlagValuesToPropertyList for %s:%s failed with hr = 0x%x.\n",
|
|
i_wszTable,
|
|
a_pv[iCOLUMNMETA_InternalName],
|
|
hr
|
|
));
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(cchManditory > 0)
|
|
{
|
|
*o_pwszManditory = new WCHAR[cchManditory+1];
|
|
if(NULL == *o_pwszManditory)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
**o_pwszManditory = 0;
|
|
wszEndMand = *o_pwszManditory;
|
|
}
|
|
|
|
if(cchOptional > 0)
|
|
{
|
|
*o_pwszOptional = new WCHAR[cchOptional+1];
|
|
if(NULL == *o_pwszOptional)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
**o_pwszOptional= 0;
|
|
wszEndOpt = *o_pwszOptional;
|
|
}
|
|
|
|
//
|
|
// Count the optional and maditory property lengths.
|
|
//
|
|
|
|
wszTable = NULL;
|
|
|
|
for(i=iStartRow; ;i++)
|
|
{
|
|
ULONG cchName = 0;
|
|
LPWSTR* pwszPropertyList = NULL;
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTColumnMeta->GetColumnValues(i,
|
|
cCol,
|
|
a_iCol,
|
|
NULL,
|
|
a_pv);
|
|
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[GetProperties] GetColumnValues (copy) failed with hr = 0x%x. Index: %d\n",
|
|
hr, i));
|
|
goto exit;
|
|
}
|
|
|
|
if(NULL == wszTable)
|
|
{
|
|
// Save the table name from the read cache so that you can do a pointer compare below.
|
|
wszTable = (LPWSTR)a_pv[iCOLUMNMETA_Table];
|
|
}
|
|
|
|
if(wszTable != a_pv[iCOLUMNMETA_Table])
|
|
{
|
|
//
|
|
// reached another table break
|
|
//
|
|
break;
|
|
}
|
|
|
|
if(MD_LOCATION == *(DWORD*)a_pv[iCOLUMNMETA_ID])
|
|
{
|
|
//
|
|
// Do NOT read in the location property.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
MD_ASSERT(NULL != (DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags]);
|
|
|
|
if(fCOLUMNMETA_HIDDEN == (fCOLUMNMETA_HIDDEN & (*(DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags])))
|
|
{
|
|
//
|
|
// Do not read hidden properties. All these properties have the
|
|
// "HIDDEN" schemagenerator flag set on them.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
cchName = (ULONG)wcslen((LPWSTR)a_pv[iCOLUMNMETA_InternalName]);
|
|
|
|
|
|
if((*(DWORD*)a_pv[iCOLUMNMETA_SchemaGeneratorFlags]) & fCOLUMNMETA_MANDATORY)
|
|
{
|
|
MD_ASSERT(wszEndMand != NULL);
|
|
memcpy(wszEndMand, a_pv[iCOLUMNMETA_InternalName], cchName*sizeof(WCHAR));
|
|
wszEndMand = wszEndMand + cchName;
|
|
memcpy(wszEndMand, g_wszComma, g_cchComma*sizeof(WCHAR));
|
|
wszEndMand = wszEndMand + g_cchComma;
|
|
pwszPropertyList = &wszEndMand;
|
|
}
|
|
else
|
|
{
|
|
MD_ASSERT(wszEndOpt != NULL);
|
|
memcpy(wszEndOpt, a_pv[iCOLUMNMETA_InternalName], cchName*sizeof(WCHAR));
|
|
wszEndOpt = wszEndOpt + cchName;
|
|
memcpy(wszEndOpt, g_wszComma, g_cchComma*sizeof(WCHAR));
|
|
wszEndOpt = wszEndOpt + g_cchComma;
|
|
pwszPropertyList = &wszEndOpt;
|
|
}
|
|
|
|
if((*(DWORD*)a_pv[iCOLUMNMETA_MetaFlags]) & fCOLUMNMETA_FLAG)
|
|
{
|
|
hr = AddFlagValuesToPropertyList((LPWSTR)i_wszTable,
|
|
*(DWORD*)a_pv[iCOLUMNMETA_Index],
|
|
NULL,
|
|
pwszPropertyList);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[GetProperties] AddFlagValuesToPropertyList for %s:%s failed with hr = 0x%x.\n",
|
|
i_wszTable,
|
|
a_pv[iCOLUMNMETA_InternalName],
|
|
hr
|
|
));
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if(cchManditory > 0)
|
|
{
|
|
wszEndMand--;
|
|
*wszEndMand = L'\0';
|
|
}
|
|
|
|
if(cchOptional > 0)
|
|
{
|
|
wszEndOpt--;
|
|
*wszEndOpt = L'\0';
|
|
}
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
|
|
} // GetProperties
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Adds the flag values to the (optional or manditory) property lists
|
|
|
|
Arguments:
|
|
|
|
[in] Class name.
|
|
[in] index
|
|
[out] Count of chars.
|
|
[in out] Property list with all flag values added to it.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT AddFlagValuesToPropertyList(LPWSTR i_wszTable,
|
|
ULONG i_dwIndex,
|
|
ULONG* io_pcCh,
|
|
LPWSTR* io_pwszPropertyList)
|
|
{
|
|
|
|
ULONG a_iCol[] = { iTAGMETA_InternalName,
|
|
iTAGMETA_ColumnIndex,
|
|
iTAGMETA_Table
|
|
};
|
|
ULONG cCol = sizeof(a_iCol)/sizeof(ULONG);
|
|
LPVOID a_pv[cTAGMETA_NumberOfColumns];
|
|
|
|
ULONG aColSearchTag[] = {iTAGMETA_Table,
|
|
iTAGMETA_ColumnIndex
|
|
};
|
|
ULONG cColSearchTag = sizeof(aColSearchTag)/sizeof(ULONG);
|
|
ULONG iStartRow = 0;
|
|
LPWSTR wszEnd = NULL;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR wszTable = NULL;
|
|
|
|
if(NULL != io_pwszPropertyList && NULL != *io_pwszPropertyList)
|
|
{
|
|
wszEnd = *io_pwszPropertyList;
|
|
}
|
|
|
|
a_pv[iTAGMETA_Table] = i_wszTable;
|
|
a_pv[iTAGMETA_ColumnIndex] = (LPVOID)&i_dwIndex;
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTTagMetaByTableAndColumnIndex->GetRowIndexBySearch(iStartRow,
|
|
cColSearchTag,
|
|
aColSearchTag,
|
|
NULL,
|
|
a_pv,
|
|
(ULONG*)&iStartRow);
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[AddFlagValuesToPropertyList] No flags found for %s:%d.\n",
|
|
i_wszTable,
|
|
i_dwIndex));
|
|
hr = S_OK;
|
|
goto exit;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[AddFlagValuesToPropertyList] GetRowIndexBySearch for %s failed with hr = 0x%x.\n",
|
|
wszTABLE_TAGMETA,
|
|
hr));
|
|
|
|
goto exit;
|
|
}
|
|
|
|
for(ULONG iRow=iStartRow;;iRow++)
|
|
{
|
|
ULONG cchName = 0;
|
|
|
|
hr = g_pGlobalISTHelper->m_pISTTagMetaByTableAndColumnIndex->GetColumnValues(iRow,
|
|
cCol,
|
|
a_iCol,
|
|
NULL,
|
|
a_pv);
|
|
if(E_ST_NOMOREROWS == hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
DBGINFOW((DBG_CONTEXT,
|
|
L"[AddFlagValuesToPropertyList] GetColumnValues for %s index %i failed with hr = 0x%x.\n",
|
|
wszTABLE_TAGMETA,
|
|
iRow,
|
|
hr));
|
|
goto exit;
|
|
}
|
|
|
|
if(NULL == wszTable)
|
|
{
|
|
wszTable = (LPWSTR)a_pv[iTAGMETA_Table];
|
|
}
|
|
|
|
if((wszTable != (LPWSTR)a_pv[iTAGMETA_Table]) ||
|
|
(i_dwIndex != *(DWORD*)a_pv[iTAGMETA_ColumnIndex])
|
|
)
|
|
{
|
|
//
|
|
// Reached another table, done with the tags of this table
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
cchName = (ULONG)wcslen((LPWSTR)a_pv[iTAGMETA_InternalName]);
|
|
|
|
if(NULL != io_pcCh)
|
|
{
|
|
*io_pcCh = *io_pcCh + cchName + 1; // for comma
|
|
}
|
|
|
|
if(NULL != wszEnd)
|
|
{
|
|
memcpy(wszEnd, a_pv[iTAGMETA_InternalName], cchName*sizeof(WCHAR));
|
|
wszEnd = wszEnd + cchName;
|
|
memcpy(wszEnd, g_wszComma, g_cchComma*sizeof(WCHAR));
|
|
wszEnd = wszEnd + g_cchComma;
|
|
}
|
|
}
|
|
|
|
|
|
if(NULL != io_pwszPropertyList)
|
|
{
|
|
*io_pwszPropertyList = wszEnd;
|
|
}
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
|
|
} // AddFlagValuesToPropertyList
|