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 |
15 | void 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 | |