|
|
/*++
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
|