1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#include "standardpch.h"
#include "verbtoc.h"
#include "methodcontext.h"
#include "methodcontextreader.h"
#include "methodcontextiterator.h"
#include "simpletimer.h"
class TOCElementNode
{
public:
TOCElementNode* Next;
TOCElement tocElement;
TOCElementNode(int number, __int64 offset) : Next(nullptr), tocElement(number, offset)
{
}
};
int verbTOC::DoWork(const char* nameOfInput)
{
LogVerbose("Indexing from '%s' into '%s.mct'", nameOfInput, nameOfInput);
MethodContextIterator mci;
if (!mci.Initialize(nameOfInput))
return -1;
int savedCount = 0;
TOCElementNode* head = nullptr;
TOCElementNode* curElem = nullptr;
while (mci.MoveNext())
{
MethodContext* mc = mci.Current();
TOCElementNode* nxt = new TOCElementNode(mci.MethodContextNumber(), mci.CurrentPos());
mc->dumpMethodMD5HashToBuffer(nxt->tocElement.Hash, MD5_HASH_BUFFER_SIZE);
if (curElem != nullptr)
{
curElem->Next = nxt;
}
else
{
head = nxt;
}
curElem = nxt;
savedCount++;
}
size_t maxLen = strlen(nameOfInput) + 5;
char* nameOfOutput = (char*)_alloca(maxLen);
strcpy_s(nameOfOutput, maxLen, nameOfInput);
strcat_s(nameOfOutput, maxLen, ".mct");
HANDLE hFileOut =
CreateFileA(nameOfOutput, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFileOut == INVALID_HANDLE_VALUE)
{
LogError("Failed to open input 1 '%s'. GetLastError()=%u", nameOfOutput, GetLastError());
return -1;
}
DWORD written;
// Write out the signature "INDX" and then the element count
LARGE_INTEGER token;
token.u.LowPart = *(const int*)"INDX"; // cuz Type Safety is for languages that have good IO facilities
token.u.HighPart = savedCount;
if (!WriteFile(hFileOut, &token, sizeof(token), &written, nullptr) || written != sizeof(token))
{
LogError("Failed to write index header. GetLastError()=%u", GetLastError());
}
// Now just dump sizeof(TOCElement) byte chunks into the file.
// I could probably do this more efficiently, but I don't think it matters
DWORD chunkSize = sizeof(TOCElement);
for (curElem = head; curElem != nullptr; curElem = curElem->Next)
{
if (!WriteFile(hFileOut, &curElem->tocElement, chunkSize, &written, nullptr) || written != chunkSize)
{
LogError("Failed to write index element '%d'. GetLastError()=%u", curElem->tocElement.Number,
GetLastError());
return -1;
}
}
// Now write out a final "INDX" to flag the end of the file...
if (!WriteFile(hFileOut, &token.u.LowPart, sizeof(token.u.LowPart), &written, nullptr) ||
(written != sizeof(token.u.LowPart)))
{
LogError("Failed to write index terminal. GetLastError()=%u", GetLastError());
}
LogInfo("Loaded %d, added %d to Table of Contents", mci.MethodContextNumber(), savedCount);
if (CloseHandle(hFileOut) == 0)
{
LogError("CloseHandle failed. GetLastError()=%u", GetLastError());
return -1;
}
if (!mci.Destroy())
return -1;
return 0;
}
|