diff options
Diffstat (limited to 'src/ToolBox/superpmi/superpmi-shared/tocfile.cpp')
-rw-r--r-- | src/ToolBox/superpmi/superpmi-shared/tocfile.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/ToolBox/superpmi/superpmi-shared/tocfile.cpp b/src/ToolBox/superpmi/superpmi-shared/tocfile.cpp new file mode 100644 index 0000000000..c91ca89c93 --- /dev/null +++ b/src/ToolBox/superpmi/superpmi-shared/tocfile.cpp @@ -0,0 +1,79 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +//---------------------------------------------------------- +// TOCFile.cpp - Abstraction for reading a TOC file +//---------------------------------------------------------- + +#include "standardpch.h" +#include "tocfile.h" +#include "logging.h" + +// Tries to load a Table of Contents +void TOCFile::LoadToc(const char *inputFileName, bool validate) +{ + HANDLE hIndex = CreateFileA(inputFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hIndex == INVALID_HANDLE_VALUE) + { + LogError("Failed to open file '%s'. GetLastError()=%u", inputFileName, GetLastError()); + return; + } + + // Now read the index file + LARGE_INTEGER val; // I'm abusing LARGE_INTEGER here... + DWORD read; + if (!ReadFile(hIndex, &val, sizeof(val), &read, nullptr) || + (val.u.LowPart != *(DWORD *)("INDX"))) + { + CloseHandle(hIndex); + LogWarning("The index file %s is invalid: it seems to be missing the starting sentinel/length", inputFileName); + return; + } + + this->m_tocCount = val.u.HighPart; + this->m_tocArray = new TOCElement[this->m_tocCount]; + + // Read the whole array + if (!ReadFile(hIndex, &this->m_tocArray[0], (DWORD)(this->m_tocCount * sizeof(TOCElement)), &read, nullptr) || + (read != (DWORD)(this->m_tocCount * sizeof(TOCElement)))) + { + CloseHandle(hIndex); + this->Clear(); + LogWarning("The index file %s is invalid: it appears to be truncated.", inputFileName); + return; + } + + // Get the last 4 byte token (more abuse of LARGE_INTEGER) + if (!ReadFile(hIndex, &val.u.HighPart, sizeof(DWORD), &read, nullptr) || + (read != sizeof(DWORD)) || + (val.u.LowPart != val.u.HighPart)) + { + CloseHandle(hIndex); + this->Clear(); + LogWarning("The index file %s is invalid: it appears to be missing the ending sentinel.", inputFileName); + return; + } + + CloseHandle(hIndex); + + if (validate) + { + int lastNum = -1; + + // Quickly validate that the index is sorted + for (size_t i = 0; i < this->m_tocCount; i++) + { + int nextNum = this->m_tocArray[i].Number; + if (nextNum <= lastNum) + { + // It wasn't sorted: abort + this->Clear(); + LogWarning("The index file %s is invalid: it is not sorted.", inputFileName); + return; + } + lastNum = nextNum; + } + } +} |