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