//---------------------------------------------------------------------------- // // Copyright (C) 2006 Intel Corporation // // File: SetupFileReaderWriter.cpp // // Contents: Demonstrates how to read and write a configuration setup file. // // Notes: This file contains a number of functions that demonstrate how // to read and write a configuration setup file. // //---------------------------------------------------------------------------- #include #include "SetupFileReaderWriter.h" #include "ConfigFile.h" static const char* G_S_DEFAULT_MEBX_PWD = "admin"; static const unsigned short G_S_DEFAULT_MEBX_PWD_LENGTH = 5; //////////////////////////// // DataRecordEntry functions //////////////////////////// DataRecordEntry::DataRecordEntry() { _moduleId = 0; _variableId = 0; _variableLength = 0; _variableValue = NULL; } DataRecordEntry::DataRecordEntry(const unsigned short moduleId, const unsigned short variableId, const unsigned short variableLength, const unsigned char* variableValue) { _variableValue = NULL; SetModuleId(moduleId); SetVariableId(variableId); SetVariableValue(variableLength, variableValue); } DataRecordEntry::DataRecordEntry(const DataRecordEntry& entry) { _variableValue = NULL; SetModuleId(entry._moduleId); SetVariableId(entry._variableId); SetVariableValue(entry._variableLength, entry._variableValue); } DataRecordEntry& DataRecordEntry::operator=(const DataRecordEntry& entry) { if (this == &entry) return *this; _variableValue = NULL; SetModuleId(entry._moduleId); SetVariableId(entry._variableId); SetVariableValue(entry._variableLength, entry._variableValue); return *this; } DataRecordEntry::~DataRecordEntry() { if(_variableValue) { delete _variableValue; _variableValue = NULL; } } unsigned short DataRecordEntry::GetModuleId() const { return _moduleId; } unsigned short DataRecordEntry::GetVariableId() const { return _variableId; } unsigned short DataRecordEntry::GetVariableLength() const { return _variableLength; } unsigned short DataRecordEntry::GetVariableValue(const unsigned short bufferLen, unsigned char* buffer) const { if(_variableValue == NULL || buffer == NULL) { return 0; } if (memcpy_s(buffer, min(_variableLength, bufferLen), _variableValue, min(_variableLength, bufferLen))) { printf("Error: Can't Copy Memory"); return 0; } return min(_variableLength, bufferLen); } void DataRecordEntry::SetModuleId(const unsigned short moduleId) { _moduleId = moduleId; } void DataRecordEntry::SetVariableId(const unsigned short variableId) { _variableId = variableId; } void DataRecordEntry::SetVariableValue(const unsigned short bufferLen, const unsigned char* buffer) { if(_variableValue) { delete _variableValue; _variableValue = NULL; } _variableLength = bufferLen; _variableValue = new unsigned char[bufferLen]; if(buffer) { if (memcpy_s(_variableValue, _variableLength, buffer, bufferLen)) { printf("Error: Can't Copy Memory"); } } } /////////////////////// // DataRecord functions /////////////////////// DataRecord::DataRecord(const bool isValid, const bool isScrambled) :_recordEntries(), _isValid(isValid), _isScrambled(isScrambled) { _recordEntries = new vector(); } DataRecord::DataRecord(const DataRecord& record) { _recordEntries = NULL; CopyRecord(record); } DataRecord& DataRecord::operator=(const DataRecord& record) { if (this == &record) return *this; _recordEntries = NULL; CopyRecord(record); return *this; } DataRecord::~DataRecord() { if(_recordEntries) { delete _recordEntries; _recordEntries = NULL; } } void DataRecord::AddRecordEntry(const unsigned short moduleId, const unsigned short variableId, const unsigned short variableLength, const unsigned char* variableValue) { DataRecordEntry entry(moduleId, variableId, variableLength, variableValue); _recordEntries->push_back(entry); } bool DataRecord::GetIsValid() const { return _isValid; } bool DataRecord::GetIsScrambled() const { return _isScrambled; } vector DataRecord::GetRecordEntries() const { return *_recordEntries; } void DataRecord::SetValid(const bool isValid) { _isValid = isValid; } void DataRecord::SetScrambled(const bool isScrambled) { _isScrambled = isScrambled; } void DataRecord::CopyRecord(const DataRecord& record) { if(_recordEntries) { delete _recordEntries; _recordEntries = NULL; } SetValid(record._isValid); SetScrambled(record._isScrambled); if(record._recordEntries) { _recordEntries = new vector(*(record._recordEntries)); } else { _recordEntries = new vector(); } } bool DataRecord::FindEntry(const unsigned short moduleId, const unsigned short variableId, unsigned short* variableLength, const unsigned short bufferLength, unsigned char* buffer) const { vector::iterator it; for(it = _recordEntries->begin(); it != _recordEntries->end(); it++) { if(it->GetModuleId() == moduleId && it->GetVariableId() == variableId) { if(variableLength) { *variableLength = it->GetVariableLength(); } if(buffer) { it->GetVariableValue(bufferLength, buffer); } return true; } } return false; } /////////////////// // Global Functions /////////////////// // Validate a UUID bool ValidateUuid(const unsigned char* uuid1, const unsigned char* uuid2) { if(memcmp(uuid1, uuid2, GUID_SIZE) != 0) { return false; } return true; } // set a DATA_RECORD_ENTRY_T from a DataRecord void SetEntry(DATA_RECORD_ENTRY_T* entry, const DataRecordEntry& recordEntry) { entry->ModuleIdentifier = recordEntry.GetModuleId(); entry->VariableIdentifier = recordEntry.GetVariableId(); entry->VariableLength = recordEntry.GetVariableLength(); recordEntry.GetVariableValue(recordEntry.GetVariableLength(), &entry->VariableValue); } // Parse the SetupFile header int ParseFileHeader(const unsigned int bufferLength, const unsigned char* buffer, SetupFileInfo* fileInfo, unsigned int* moduleListSize, set* moduleList) { if(buffer == NULL) { return CONFIG_INVALID_BUFFER; } SETUP_HEADER_T* fileHeader; fileHeader = (SETUP_HEADER_T*)buffer; unsigned char setupFileGuid[GUID_SIZE] = SETUP_GUID; unsigned char setupFileGuid2[GUID_SIZE] = SETUP_GUID_2; unsigned char setupFileGuid3[GUID_SIZE] = SETUP_GUID_3; unsigned char setupFileGuid4[GUID_SIZE] = SETUP_GUID_4; const unsigned char* strSetupFileGuid = NULL; switch (fileHeader->MajorVersion) { case SETUP_FILE_VERSION_1: strSetupFileGuid = setupFileGuid; break; case SETUP_FILE_VERSION_2: strSetupFileGuid = setupFileGuid2; break; case SETUP_FILE_VERSION_3: strSetupFileGuid = setupFileGuid3; break; case SETUP_FILE_VERSION_4: strSetupFileGuid = setupFileGuid4; break; default: return CONFIG_VERSION_UNSUPPORTED; } if(!ValidateUuid( strSetupFileGuid, (unsigned char*)&(fileHeader->FileTypeUuid))) { return CONFIG_INVALID_UUID; } if(fileHeader->MajorVersion > MAX_MAJOR_VERSION) { return CONFIG_VERSION_UNSUPPORTED; } if(fileHeader->RecordNumber != 0) { return CONFIG_INVALID_RECORD_NUMBER; } unsigned int length = CHUNK_SIZE * (fileHeader->RecordChunkCount + (fileHeader->DataRecordCount * fileHeader->RecordChunkCount)); if(length > bufferLength) { return CONFIG_INVALID_BUFFER_LENGTH; } if(fileHeader->RecordHeaderByteCount < sizeof(SETUP_HEADER_T) || fileHeader->RecordHeaderByteCount > CHUNK_SIZE * fileHeader->RecordChunkCount) { return CONFIG_INVALID_RECORD_HEADER_BYTE_COUNT; } const unsigned short* TMP = (const unsigned short*)&(fileHeader->ModuleList); unsigned int counter = 0; unsigned int bytesInHeader = sizeof(SETUP_HEADER_T) - 1; while(TMP[counter] != 0) { counter ++; bytesInHeader += 2; if(bytesInHeader > fileHeader->RecordHeaderByteCount) { return CONFIG_INVALID_MODULE_LIST; } } // fill values if(fileInfo) { fileInfo->headerChunkCount = fileHeader->RecordChunkCount; fileInfo->recordCount = fileHeader->DataRecordCount; fileInfo->recordsConsumed = fileHeader->DataRecordsConsumed; fileInfo->dataRecordChunkCount = fileHeader->DataRecordChunkCount; fileInfo->majorVersion = fileHeader->MajorVersion; fileInfo->minorVersion = fileHeader->MinorVersion; fileInfo->consumeRecords = (fileHeader->FileFlags.DontConsumeRecords == 0); } if(moduleList) { for(unsigned int i = 0; i < counter; i++) { moduleList->insert(TMP[i]); } } if(moduleListSize) { *moduleListSize = counter; } return CONFIG_SUCCESS; } int WriteFileHeader(unsigned char* buffer, const SetupFileInfo fileInfo, const set& moduleList) { if(buffer == NULL) { return CONFIG_INVALID_BUFFER; } unsigned short numLegalModules; set::const_iterator it = moduleList.find(0); if(it == moduleList.end()) { numLegalModules = (unsigned short)moduleList.size(); } else { numLegalModules = (unsigned short)moduleList.size() - 1; } unsigned short byteCount = sizeof(SETUP_HEADER_T) + numLegalModules*2; if(byteCount > fileInfo.headerChunkCount*CHUNK_SIZE) { return CONFIG_INVALID_HEADER_CHUNK_COUNT; } memset(buffer, 0, fileInfo.headerChunkCount*CHUNK_SIZE); SETUP_HEADER_T* header = (SETUP_HEADER_T*)buffer; unsigned char setupFileGuid[GUID_SIZE] = SETUP_GUID; unsigned char setupFileGuid2[GUID_SIZE] = SETUP_GUID_2; unsigned char setupFileGuid3[GUID_SIZE] = SETUP_GUID_3; unsigned char setupFileGuid4[GUID_SIZE] = SETUP_GUID_4; switch (fileInfo.majorVersion) { case SETUP_FILE_VERSION_1: if (memcpy_s(&(header->FileTypeUuid), ARRAYSIZE(header->FileTypeUuid), setupFileGuid, ARRAYSIZE(setupFileGuid))) { return CONFIG_INVALID_BUFFER; } break; case SETUP_FILE_VERSION_2: if (memcpy_s(&(header->FileTypeUuid), ARRAYSIZE(header->FileTypeUuid), setupFileGuid2, ARRAYSIZE(setupFileGuid2))) { return CONFIG_INVALID_BUFFER; } break; case SETUP_FILE_VERSION_3: if (memcpy_s(&(header->FileTypeUuid), ARRAYSIZE(header->FileTypeUuid), setupFileGuid3, ARRAYSIZE(setupFileGuid3))) { return CONFIG_INVALID_BUFFER; } break; case SETUP_FILE_VERSION_4: if (memcpy_s(&(header->FileTypeUuid), ARRAYSIZE(header->FileTypeUuid), setupFileGuid4, ARRAYSIZE(setupFileGuid4))) { return CONFIG_INVALID_BUFFER; } break; default: return CONFIG_VERSION_UNSUPPORTED; } bool singleRecord = ((fileInfo.majorVersion >= SETUP_FILE_VERSION_2) && fileInfo.consumeRecords == false); header->RecordChunkCount = fileInfo.headerChunkCount; header->RecordHeaderByteCount = byteCount; header->MajorVersion = fileInfo.majorVersion; header->MinorVersion = fileInfo.minorVersion; header->RecordNumber = 0; header->DataRecordCount = singleRecord ? 1 : fileInfo.recordCount; header->DataRecordsConsumed = singleRecord ? 0 : fileInfo.recordsConsumed; header->DataRecordChunkCount = fileInfo.dataRecordChunkCount; header->FileFlags.DontConsumeRecords = singleRecord ? 1 : 0; unsigned short* tmp = &header->ModuleList; it = moduleList.begin(); while(it != moduleList.end()) { if((*it) != 0) { *tmp = *it; tmp++; } it++; } *tmp = 0; return CONFIG_SUCCESS; } // retrieve a Data Record int GetDataRecord(const unsigned short numChunks, const unsigned char* buffer, const unsigned char majorVersion, const unsigned char minorVersion, set* legalModules, DataRecord* record) { if(buffer == NULL) { return CONFIG_INVALID_BUFFER; } DATA_RECORD_HEADER_T* recordHeader; DATA_RECORD_ENTRY_T* recordEntry; recordHeader = (DATA_RECORD_HEADER_T*)buffer; if(recordHeader->RecordChunkCount != numChunks) { return CONFIG_INVALID_RECORD_CHUNK_COUNT; } unsigned int base = recordHeader->RecordHeaderByteCount; if(base > (unsigned int)(numChunks * CHUNK_SIZE)) { return CONFIG_INVALID_RECORD_HEADER_BYTE_COUNT; } bool valid = recordHeader->RecordFlags.Valid; static bool scrambled = recordHeader->RecordFlags.Scrambled; if(!valid) { return CONFIG_INVALID_RECORD; } if(recordHeader->RecordTypeIdentifier != RECORD_IDENTIFIER_DATA_RECORD) { return CONFIG_RECORD_TYPE_INVALID; } if (scrambled != recordHeader->RecordFlags.Scrambled) { return CONFIG_INVALID_SCRAMBLED_STATE; } DataRecord dr(valid, scrambled); unsigned int entryDwordLength; bool first = true; // in SETUP_FILE_VERSION_2 default "admin" must be followed by // a new MEBx password bool findNewMebxPwd = false; // in SETUP_FILE_VERSION_2 // ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION // may not appear after any CM settings bool cmVarFound = false; // in SETUP_FILE_VERSION_2 // CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERT_ADD must be preceded // by setting CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG to // if (scrambled) { DescrambleRecordData((unsigned char *)buffer + base, recordHeader->RecordChunkCount * CHUNK_SIZE - base); } while(valid) // if valid is false - do not search for entries { recordEntry = (DATA_RECORD_ENTRY_T*)(buffer + base); if(first) { // make sure first entry is current MEBx password if(recordEntry->ModuleIdentifier != MODULE_IDENTIFIER_ME_KERNEL || recordEntry->VariableIdentifier != ME_VARIABLE_IDENTIFIER_CURRENT_MEBX_PWD) { return CONFIG_MISSING_CURRENT_MEBX_PWD_ENTRY; } first = false; if(recordEntry->VariableLength == G_S_DEFAULT_MEBX_PWD_LENGTH && memcmp(&(recordEntry->VariableValue), G_S_DEFAULT_MEBX_PWD, min(G_S_DEFAULT_MEBX_PWD_LENGTH, sizeof(recordEntry->VariableValue))) == 0) {// default password found findNewMebxPwd = true; } } if(recordEntry->ModuleIdentifier == 0 && recordEntry->VariableIdentifier == 0 && recordEntry->VariableLength == 0 && recordEntry->Reserved == 0) { // NULL Entry Terminator break; } if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_ME_KERNEL && recordEntry->VariableIdentifier == ME_VARIABLE_IDENTIFIER_NEW_MEBX_PWD) {// new MEBx pwd found findNewMebxPwd = false; } if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_ME_KERNEL && recordEntry->VariableIdentifier == ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION && majorVersion >= SETUP_FILE_VERSION_2) { if(cmVarFound) { return CONFIG_INVALID_MANAGEABILITY_FEATURE_SELECTION; } } if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_AMT_CM) { cmVarFound = true; } //if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_AMT_CM // && recordEntry->VariableIdentifier == // CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG // && recordEntry->VariableValue == CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG_DELETE) // { // userDefinedCertsDeleted = true; //} //if(recordEntry->ModuleIdentifier == MODULE_IDENTIFIER_AMT_CM // && recordEntry->VariableIdentifier == // CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERT_ADD // && majorVersion >= SETUP_FILE_VERSION_2) // { // if(!userDefinedCertsDeleted) // { // return CONFIG_INVALID_CERT_SETTINGS; // } //} if(legalModules) {// validate moduleId if(recordEntry->ModuleIdentifier != 0) { set::iterator it = legalModules->find(recordEntry->ModuleIdentifier); if(it == legalModules->end()) { return CONFIG_INVALID_MODULE_ID; } } // else - filler value } dr.AddRecordEntry(recordEntry->ModuleIdentifier, recordEntry->VariableIdentifier, recordEntry->VariableLength, &(recordEntry->VariableValue)); entryDwordLength = 2 + (recordEntry->VariableLength + 3)/4; base += 4*entryDwordLength; if(base > (unsigned int)CHUNK_SIZE * numChunks) { return CONFIG_INVALID_ENTRY_LIST; } } if(majorVersion >= SETUP_FILE_VERSION_2 && findNewMebxPwd) { return CONFIG_MISSING_NEW_MEBX_PWD_ENTRY; } if(record) { record->CopyRecord(dr); } return CONFIG_SUCCESS; } int WriteDataRecord(const unsigned short numChunks, unsigned char* buffer, const unsigned char majorVersion, const unsigned char minorVersion, const unsigned int recordNumber, const DataRecord& record, set* modulesUsed) { if(buffer == NULL) { return CONFIG_INVALID_BUFFER; } unsigned int requiredDwords = (sizeof(DATA_RECORD_HEADER_T) + 3)/4; bool currentMEBxPwdFound = false; bool isDefaultMEBxPwd = false; bool newMEBxPwdFound = false; bool manFeatureFound = false; bool pkiDnsSuffixFound = false; bool configServerFqdnFound = false; bool provisioningServerAddressFound = false; bool meProvisioningHaltActivateFound = false; int currPwdIndex = -1; int newPwdIndex = -1; int manSelectionIndex = -1; int meProvisioningHaltActivateIndex = -1; vector entries = record.GetRecordEntries(); unsigned int numEntries = (unsigned int)entries.size(); for(unsigned int i = 0; i < numEntries; i++) { if(entries[i].GetModuleId() == MODULE_IDENTIFIER_ME_KERNEL && entries[i].GetVariableId() == ME_VARIABLE_IDENTIFIER_CURRENT_MEBX_PWD) { currPwdIndex = i; currentMEBxPwdFound = true; if(entries[i].GetVariableLength() == G_S_DEFAULT_MEBX_PWD_LENGTH) { unsigned char tmp[G_S_DEFAULT_MEBX_PWD_LENGTH + 1]; entries[i].GetVariableValue(G_S_DEFAULT_MEBX_PWD_LENGTH + 1, &(tmp[0])); if(memcmp(tmp, G_S_DEFAULT_MEBX_PWD, G_S_DEFAULT_MEBX_PWD_LENGTH) == 0) { isDefaultMEBxPwd = true; } } } if(entries[i].GetModuleId() == MODULE_IDENTIFIER_ME_KERNEL && entries[i].GetVariableId() == ME_VARIABLE_IDENTIFIER_NEW_MEBX_PWD) { newPwdIndex = i; newMEBxPwdFound = true; } if(entries[i].GetModuleId() == MODULE_IDENTIFIER_ME_KERNEL && entries[i].GetVariableId() == ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION) { manSelectionIndex = i; manFeatureFound = true; } if(entries[i].GetModuleId() == MODULE_IDENTIFIER_AMT_CM && entries[i].GetVariableId() == CM_VARIABLE_IDENTIFIER_PKI_DNS_SUFFIX) { pkiDnsSuffixFound = true; } if(entries[i].GetModuleId() == MODULE_IDENTIFIER_AMT_CM && entries[i].GetVariableId() == CM_VARIABLE_IDENTIFIER_CONFIG_SERVER_FQDN) { configServerFqdnFound = true; } if(entries[i].GetModuleId() == MODULE_IDENTIFIER_AMT_CM && entries[i].GetVariableId() == CM_VARIABLE_IDENTIFIER_PSADDR) { provisioningServerAddressFound = true; } if(entries[i].GetModuleId() == MODULE_IDENTIFIER_AMT_CM && entries[i].GetVariableId() == CM_VARIABLE_IDENTIFIER_ME_PROVISION_HALT_ACTIVE) { meProvisioningHaltActivateIndex = i; meProvisioningHaltActivateFound = true; } requiredDwords += (2 + (entries[i].GetVariableLength() + 3)/4); } requiredDwords += 2; // for NULL terminating entry if(!currentMEBxPwdFound) { return CONFIG_MISSING_CURRENT_MEBX_PWD_ENTRY; } if(majorVersion >= SETUP_FILE_VERSION_2 && isDefaultMEBxPwd && !newMEBxPwdFound) { return CONFIG_MISSING_NEW_MEBX_PWD_ENTRY; } if(4*requiredDwords > (unsigned int)numChunks*CHUNK_SIZE) { return CONFIG_INVALID_RECORD_CHUNK_COUNT; } memset(buffer, 0, numChunks*CHUNK_SIZE); DATA_RECORD_HEADER_T* header; DATA_RECORD_ENTRY_T* entry; bool scrambled = record.GetIsScrambled(); header = (DATA_RECORD_HEADER_T*)buffer; header->RecordTypeIdentifier = RECORD_IDENTIFIER_DATA_RECORD; header->RecordFlags.Valid = (record.GetIsValid()) ? 1 : 0; header->RecordFlags.Scrambled = scrambled ? 1 : 0; header->RecordChunkCount = numChunks; unsigned short headerDwords = ((sizeof(DATA_RECORD_HEADER_T) + 3)/4) * 4; header->RecordHeaderByteCount = headerDwords; header->RecordNumber = recordNumber; unsigned int base = header->RecordHeaderByteCount; unsigned int entryDwordLength; // first insert CurrentMEBx Pwd entry = (DATA_RECORD_ENTRY_T*)(buffer + base); SetEntry(entry, entries[currPwdIndex]); if(modulesUsed) { modulesUsed->insert(entries[currPwdIndex].GetModuleId()); } entryDwordLength = 2 + (entry->VariableLength + 3)/4; base += 4*entryDwordLength; // next insert newMebx, if found if(newMEBxPwdFound) { entry = (DATA_RECORD_ENTRY_T*)(buffer + base); SetEntry(entry, entries[newPwdIndex]); entryDwordLength = 2 + (entry->VariableLength + 3)/4; base += 4*entryDwordLength; } // next insert manageability selection, if found if(manFeatureFound) { entry = (DATA_RECORD_ENTRY_T*)(buffer + base); SetEntry(entry, entries[manSelectionIndex]); entryDwordLength = 2 + (entry->VariableLength + 3)/4; base += 4*entryDwordLength; } bool waitForHaltActiveAfterConfigServerSettings = false; // The "ME provisioning Halt/Activate" command must appear in the file only after "PKIDNSSuffix", // "ConfigServerFQDN" and "Provisioning Server Address" if ((pkiDnsSuffixFound || configServerFqdnFound || provisioningServerAddressFound) && meProvisioningHaltActivateFound) { waitForHaltActiveAfterConfigServerSettings = true; } for(unsigned int i = 0; i < numEntries; i++) { if(i == currPwdIndex || i == newPwdIndex || i == manSelectionIndex) { continue; } if (i == meProvisioningHaltActivateIndex) { if (waitForHaltActiveAfterConfigServerSettings) { continue; } } entry = (DATA_RECORD_ENTRY_T*)(buffer + base); SetEntry(entry, entries[i]); if(modulesUsed) { modulesUsed->insert(entries[i].GetModuleId()); } entryDwordLength = 2 + (entry->VariableLength + 3)/4; base += 4*entryDwordLength; } // The "ME provisioning Halt/Activate" command must appear in the file only after "PKIDNSSuffix", // "ConfigServerFQDN" and "Provisioning Server Address" if (waitForHaltActiveAfterConfigServerSettings) { entry = (DATA_RECORD_ENTRY_T*)(buffer + base); SetEntry(entry, entries[meProvisioningHaltActivateIndex]); if(modulesUsed) { modulesUsed->insert(entries[meProvisioningHaltActivateIndex].GetModuleId()); } entryDwordLength = 2 + (entry->VariableLength + 3)/4; base += 4*entryDwordLength; } entry = (DATA_RECORD_ENTRY_T*)(buffer + base); entry->ModuleIdentifier = 0; entry->VariableIdentifier = 0; entry->VariableLength = 0; entry->Reserved = 0; if (scrambled) { ScrambleRecordData(buffer + headerDwords, header->RecordChunkCount * CHUNK_SIZE - headerDwords); } return CONFIG_SUCCESS; } int BufferToRecords(const unsigned int bufferLength, const unsigned char* buffer, SetupFileInfo* fileData, vector* records) { if(buffer == NULL) { return CONFIG_INVALID_BUFFER; } SetupFileInfo tmp; SetupFileInfo* fileInfo = (fileData ? fileData : &tmp); unsigned int moduleListSize; try { auto moduleList = std::unique_ptr>(new set()); int retVal = ParseFileHeader(bufferLength, buffer, fileInfo, &moduleListSize, moduleList.get()); if (retVal != CONFIG_SUCCESS) { return retVal; } DataRecord record; // verfiy the number of records consumed for (unsigned int i = 0; i < fileInfo->recordsConsumed; i++) { retVal = GetDataRecord(fileInfo->dataRecordChunkCount, (buffer + CHUNK_SIZE * (fileInfo->headerChunkCount + i*fileInfo->dataRecordChunkCount)), fileInfo->majorVersion, fileInfo->minorVersion, moduleList.get(), &record); if (retVal != CONFIG_INVALID_RECORD) { return CONFIG_INVALID_FILE; } } for (unsigned int i = fileInfo->recordsConsumed; i < fileInfo->recordCount; i++) { retVal = GetDataRecord(fileInfo->dataRecordChunkCount, (buffer + CHUNK_SIZE * (fileInfo->headerChunkCount + i*fileInfo->dataRecordChunkCount)), fileInfo->majorVersion, fileInfo->minorVersion, moduleList.get(), &record); if (retVal == CONFIG_SUCCESS) { if (records) { records->push_back(record); } } else { return retVal; } } return CONFIG_SUCCESS; } catch (std::bad_alloc&) { printf("ERROR: can't allocate memory"); return MEMORY_ALLOC_ERROR; } } int GetRecordByIndex(const unsigned int bufferLength, const unsigned char* buffer, const unsigned int index, DataRecord* record) { if(buffer == NULL) { return CONFIG_INVALID_BUFFER; } SetupFileInfo fileInfo; unsigned int moduleListSize; try { auto moduleList = std::unique_ptr>(new set()); int retVal = ParseFileHeader(bufferLength, buffer, &fileInfo, &moduleListSize, moduleList.get()); if (retVal != CONFIG_SUCCESS) { return retVal; } if (index == 0 || index > fileInfo.recordCount) { return CONFIG_INVALID_INDEX; } retVal = GetDataRecord(fileInfo.dataRecordChunkCount, (buffer + CHUNK_SIZE * (fileInfo.headerChunkCount + (index - 1)*fileInfo.dataRecordChunkCount)), fileInfo.majorVersion, fileInfo.minorVersion, moduleList.get(), record); return retVal; } catch (std::bad_alloc&) { printf("ERROR: can't allocate memory"); return MEMORY_ALLOC_ERROR; } } int GetNextValidRecord(const unsigned int bufferLength, const unsigned char* buffer, DataRecord* record) { if(buffer == NULL) { return CONFIG_INVALID_BUFFER; } SetupFileInfo fileInfo; unsigned int moduleListSize; try { auto moduleList = std::unique_ptr>(new set()); int retVal = ParseFileHeader(bufferLength, buffer, &fileInfo, &moduleListSize, moduleList.get()); if (retVal != CONFIG_SUCCESS) { return retVal; } if (fileInfo.recordsConsumed >= fileInfo.recordCount) { return CONFIG_NO_VALID_RECORDS; } unsigned int index = fileInfo.recordCount - fileInfo.recordsConsumed; retVal = GetDataRecord(fileInfo.dataRecordChunkCount, (buffer + CHUNK_SIZE * (fileInfo.headerChunkCount + (index - 1)*fileInfo.dataRecordChunkCount)), fileInfo.majorVersion, fileInfo.minorVersion, moduleList.get(), record); if (retVal == CONFIG_INVALID_RECORD) { retVal = CONFIG_INVALID_FILE; } return retVal; } catch (std::bad_alloc&) { printf("ERROR: can't allocate memory"); return MEMORY_ALLOC_ERROR; } } int RecordsToBuffer(const vector& records, const SetupFileInfo& setupInfo, const unsigned int bufferLength, unsigned char* buffer) { if(buffer == NULL) { return CONFIG_INVALID_BUFFER; } unsigned int numRecords = (unsigned int)records.size(); if((numRecords != setupInfo.recordCount) || (0 != setupInfo.recordsConsumed)) { return CONFIG_INVALID_INPUT; } unsigned int requiredLength = (setupInfo.headerChunkCount + numRecords*setupInfo.dataRecordChunkCount)*CHUNK_SIZE; if(bufferLength < requiredLength) { return CONFIG_INVALID_BUFFER_LENGTH; } set modulesUsed; int retVal = CONFIG_SUCCESS; unsigned int index = 1; unsigned int offset = CHUNK_SIZE * setupInfo.headerChunkCount; try { auto tempBuffer = std::unique_ptr(new unsigned char[requiredLength]); memset(tempBuffer.get(), 0, requiredLength); while (index <= numRecords) { retVal = WriteDataRecord(setupInfo.dataRecordChunkCount, tempBuffer.get() + offset, setupInfo.majorVersion, setupInfo.minorVersion, index, records[index - 1], &modulesUsed); if (retVal != CONFIG_SUCCESS) { break; } offset += (CHUNK_SIZE * setupInfo.dataRecordChunkCount); index++; } if (retVal == CONFIG_SUCCESS) { retVal = WriteFileHeader(tempBuffer.get(), setupInfo, modulesUsed); } if (retVal == CONFIG_SUCCESS) { if (memcpy_s(buffer, bufferLength, tempBuffer.get(), requiredLength)) { return CONFIG_INVALID_BUFFER_LENGTH; } } return retVal; } catch (std::bad_alloc&) { printf("ERROR: can't allocate memory"); return MEMORY_ALLOC_ERROR; } } int GetChunkCount(const DataRecord& record) { unsigned int requiredDwords = (sizeof(DATA_RECORD_HEADER_T) + 3)/4; vector entries = record.GetRecordEntries(); unsigned int numEntries = (unsigned int)entries.size(); for(int i = 0; i < (int)numEntries; i++) { requiredDwords += (2 + (entries[i].GetVariableLength() + 3)/4); } requiredDwords += 2; // for NULL terminating entry return (4*requiredDwords + (CHUNK_SIZE - 1))/CHUNK_SIZE; }