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#include "standardpch.h"
7#include "verbstrip.h"
8#include "simpletimer.h"
9#include "methodcontext.h"
10#include "errorhandling.h"
11#include "methodcontextreader.h"
12#include "methodcontextiterator.h"
13
14// verbStrip::DoWork handles both "-copy" and "-strip". These both copy from input file to output file,
15// but treat the passed-in indexes in opposite ways.
16int verbStrip::DoWork(
17 const char* nameOfInput, const char* nameOfOutput, int indexCount, const int* indexes, bool strip, bool stripCR)
18{
19 if (strip)
20 return DoWorkTheOldWay(nameOfInput, nameOfOutput, indexCount, indexes, stripCR);
21 SimpleTimer* st1 = new SimpleTimer();
22
23 LogVerbose("Reading from '%s' removing Mc Indexes and writing into '%s'", nameOfInput, nameOfOutput);
24
25 int loadedCount = 0;
26 MethodContext* mc = nullptr;
27 int savedCount = 0;
28 int index = 0;
29
30 // The method context reader handles skipping any unrequested method contexts
31 // Used in conjunction with an MCI file, it does a lot less work...
32 MethodContextReader* reader = new MethodContextReader(nameOfInput, indexes, indexCount);
33 if (!reader->isValid())
34 {
35 return -1;
36 }
37
38 HANDLE hFileOut = CreateFileA(nameOfOutput, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
39 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
40 if (hFileOut == INVALID_HANDLE_VALUE)
41 {
42 LogError("Failed to open input 1 '%s'. GetLastError()=%u", nameOfOutput, GetLastError());
43 return -1;
44 }
45
46 if (indexCount == -1)
47 strip = true; // Copy command with no indexes listed should copy all the inputs...
48 while (true)
49 {
50 MethodContextBuffer mcb = reader->GetNextMethodContext();
51 if (mcb.Error())
52 {
53 return -1;
54 }
55 else if (mcb.allDone())
56 {
57 break;
58 }
59
60 loadedCount++;
61 if ((loadedCount % 500 == 0) && (loadedCount > 0))
62 {
63 st1->Stop();
64 LogVerbose("%2.1f%% - Loaded %d at %d per second", reader->PercentComplete(), loadedCount,
65 (int)((double)500 / st1->GetSeconds()));
66 st1->Start();
67 }
68
69 if (!MethodContext::Initialize(loadedCount, mcb.buff, mcb.size, &mc))
70 return -1;
71
72 if (stripCR)
73 {
74 delete mc->cr;
75 mc->cr = new CompileResult();
76 }
77 mc->saveToFile(hFileOut);
78 savedCount++;
79 delete mc;
80 }
81 if (CloseHandle(hFileOut) == 0)
82 {
83 LogError("2nd CloseHandle failed. GetLastError()=%u", GetLastError());
84 return -1;
85 }
86 LogInfo("Loaded %d, Saved %d", loadedCount, savedCount);
87
88 return 0;
89}
90
91// This is only used for "-strip".
92int verbStrip::DoWorkTheOldWay(
93 const char* nameOfInput, const char* nameOfOutput, int indexCount, const int* indexes, bool stripCR)
94{
95 LogVerbose("Reading from '%s' removing MC Indexes and writing into '%s'", nameOfInput, nameOfOutput);
96
97 MethodContextIterator mci(true);
98 if (!mci.Initialize(nameOfInput))
99 return -1;
100
101 int savedCount = 0;
102 bool write;
103 int index = 0; // Can't use MethodContextIterator indexing, since we want the opposite of that.
104
105 HANDLE hFileOut = CreateFileA(nameOfOutput, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
106 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
107 if (hFileOut == INVALID_HANDLE_VALUE)
108 {
109 LogError("Failed to open input 1 '%s'. GetLastError()=%u", nameOfOutput, GetLastError());
110 return -1;
111 }
112
113 while (mci.MoveNext())
114 {
115 MethodContext* mc = mci.Current();
116
117 write = true; // assume we'll write it
118 if (index < indexCount)
119 {
120 if (indexes[index] == mci.MethodContextNumber())
121 {
122 index++;
123 write = false;
124 }
125 }
126
127 if (write)
128 {
129 if (stripCR)
130 {
131 delete mc->cr;
132 mc->cr = new CompileResult();
133 }
134 mc->saveToFile(hFileOut);
135 savedCount++;
136 }
137 }
138
139 if (CloseHandle(hFileOut) == 0)
140 {
141 LogError("2nd CloseHandle failed. GetLastError()=%u", GetLastError());
142 return -1;
143 }
144
145 if (index < indexCount)
146 LogWarning("Didn't use all of index count input %d < %d (i.e. didn't see MC #%d)", index, indexCount,
147 indexes[index]);
148
149 LogInfo("Loaded %d, Saved %d", mci.MethodContextNumber(), savedCount);
150
151 if (!mci.Destroy())
152 return -1;
153
154 return 0;
155}
156