1//
2// Copyright (c) Microsoft. All rights reserved.
3// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4//
5
6//----------------------------------------------------------
7// TOCFile.cpp - Abstraction for reading a TOC file
8//----------------------------------------------------------
9
10#include "standardpch.h"
11#include "tocfile.h"
12#include "logging.h"
13
14// Tries to load a Table of Contents
15void TOCFile::LoadToc(const char* inputFileName, bool validate)
16{
17 HANDLE hIndex = CreateFileA(inputFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
18 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
19 if (hIndex == INVALID_HANDLE_VALUE)
20 {
21 LogError("Failed to open file '%s'. GetLastError()=%u", inputFileName, GetLastError());
22 return;
23 }
24
25 // Now read the index file
26 LARGE_INTEGER val; // I'm abusing LARGE_INTEGER here...
27 DWORD read;
28 if (!ReadFile(hIndex, &val, sizeof(val), &read, nullptr) || (val.u.LowPart != *(DWORD*)("INDX")))
29 {
30 CloseHandle(hIndex);
31 LogWarning("The index file %s is invalid: it seems to be missing the starting sentinel/length", inputFileName);
32 return;
33 }
34
35 this->m_tocCount = val.u.HighPart;
36 this->m_tocArray = new TOCElement[this->m_tocCount];
37
38 // Read the whole array
39 if (!ReadFile(hIndex, &this->m_tocArray[0], (DWORD)(this->m_tocCount * sizeof(TOCElement)), &read, nullptr) ||
40 (read != (DWORD)(this->m_tocCount * sizeof(TOCElement))))
41 {
42 CloseHandle(hIndex);
43 this->Clear();
44 LogWarning("The index file %s is invalid: it appears to be truncated.", inputFileName);
45 return;
46 }
47
48 // Get the last 4 byte token (more abuse of LARGE_INTEGER)
49 if (!ReadFile(hIndex, &val.u.HighPart, sizeof(DWORD), &read, nullptr) || (read != sizeof(DWORD)) ||
50 (val.u.LowPart != val.u.HighPart))
51 {
52 CloseHandle(hIndex);
53 this->Clear();
54 LogWarning("The index file %s is invalid: it appears to be missing the ending sentinel.", inputFileName);
55 return;
56 }
57
58 CloseHandle(hIndex);
59
60 if (validate)
61 {
62 int lastNum = -1;
63
64 // Quickly validate that the index is sorted
65 for (size_t i = 0; i < this->m_tocCount; i++)
66 {
67 int nextNum = this->m_tocArray[i].Number;
68 if (nextNum <= lastNum)
69 {
70 // It wasn't sorted: abort
71 this->Clear();
72 LogWarning("The index file %s is invalid: it is not sorted.", inputFileName);
73 return;
74 }
75 lastNum = nextNum;
76 }
77 }
78}
79