COFFI
1.2
               
coffi_directory.hpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2014-2014 by Serge Lamikhov-Center
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 
23 /*! @file coffi_directory.hpp
24  * @brief COFFI library classes for the PE data directories.
25  *
26  * Do not include this file directly. This file is included by coffi.hpp.
27  */
28 
29 #ifndef COFFI_DIRECTORY_HPP
30 #define COFFI_DIRECTORY_HPP
31 
32 #include <iostream>
33 #include <memory>
34 #include <vector>
35 
36 #include <coffi/coffi_utils.hpp>
37 #include <coffi/coffi_headers.hpp>
38 #include <coffi/coffi_section.hpp>
39 
40 #if defined(__has_include) && __has_include(<gsl/narrow>)
41 #include <gsl/narrow>
42 using gsl::narrow_cast;
43 #else
44 #ifndef narrow_cast
45 #define narrow_cast static_cast
46 #endif
47 #endif
48 
49 namespace COFFI {
50 
51 //! Class for accessing an image data directory
52 class directory
53 {
54  public:
55  //------------------------------------------------------------------------------
56  directory(uint32_t index) : data_{nullptr}, index_{index} {}
57 
58  //------------------------------------------------------------------------------
59  //! Discards the copy constructor
60  directory(const directory&) = delete;
61 
62  virtual ~directory() { clean(); }
63  //------------------------------------------------------------------------------
64  //! @accessors{directory}
65  COFFI_GET_SET_ACCESS(uint32_t, virtual_address);
66  COFFI_GET_SET_ACCESS(uint32_t, size);
67 
68  COFFI_GET_SIZEOF();
69  //! @endaccessors
70 
71  uint32_t get_index() const { return index_; }
72 
73  //------------------------------------------------------------------------------
74  const char* get_data() const { return data_; }
75 
76  //------------------------------------------------------------------------------
77  void set_data(const char* data, uint32_t size)
78  {
79  if ((index_ != DIRECTORY_CERTIFICATE_TABLE) &&
80  (index_ != DIRECTORY_BOUND_IMPORT)) {
81  return;
82  }
83 
84  clean();
85  if (!data) {
86  set_size(0);
87  return;
88  }
89 
90  char* temp_buffer = new char[size];
91  if (!temp_buffer) {
92  set_size(0);
93  return;
94  }
95  std::copy(data, data + size, temp_buffer);
96  data_ = temp_buffer;
97  set_size(size);
98  }
99 
100  //------------------------------------------------------------------------------
101  uint32_t get_data_filesize() const
102  {
103  if ((index_ == DIRECTORY_CERTIFICATE_TABLE) ||
104  (index_ == DIRECTORY_BOUND_IMPORT)) {
105  return get_size();
106  }
107  return 0;
108  }
109 
110  //------------------------------------------------------------------------------
111  bool load(std::istream& stream)
112  {
113  clean();
114  stream.read(reinterpret_cast<char*>(&header), sizeof(header));
115  if (stream.gcount() != sizeof(header)) {
116  return false;
117  }
118  return true;
119  }
120 
121  //------------------------------------------------------------------------------
122  bool load_data(std::istream& stream)
123  {
124  if ((index_ != DIRECTORY_CERTIFICATE_TABLE) &&
125  (index_ != DIRECTORY_BOUND_IMPORT)) {
126  return true;
127  }
128  if ((get_size() > 0) && (get_virtual_address() != 0)) {
129  char* temp_buffer = new char[get_size()];
130  stream.seekg(get_virtual_address());
131  stream.read(temp_buffer, get_size());
132  if (stream.gcount() != static_cast<int>(get_size())) {
133  return false;
134  }
135  data_ = temp_buffer;
136  }
137  return true;
138  }
139 
140  //---------------------------------------------------------------------
141  void save(std::ostream& stream) const
142  {
143  stream.write(reinterpret_cast<const char*>(&header), sizeof(header));
144  }
145 
146  void save_data(std::ostream& stream) const
147  {
148  if ((index_ != DIRECTORY_CERTIFICATE_TABLE) &&
149  (index_ != DIRECTORY_BOUND_IMPORT)) {
150  return;
151  }
152  if (data_ && get_size() > 0) {
153  stream.write(data_, get_size());
154  }
155  }
156 
157  //------------------------------------------------------------------------------
158  void clean()
159  {
160  if (data_) {
161  delete[] data_;
162  data_ = nullptr;
163  }
164  }
165 
166  private:
167  image_data_directory header{};
168  const char* data_;
169  uint32_t index_;
170 };
171 
172 /*! @brief List of image data directories
173  *
174  * It is implemented as a vector of @ref directory pointers.
175  */
176 class directories : public std::vector<directory*>
177 {
178  public:
179  //------------------------------------------------------------------------------
180  directories(sections_provider* scn) : scn_{scn} {}
181 
182  //! Discards the copy constructor
183  directories(const directories&) = delete;
184 
185  virtual ~directories() { clean(); }
186 
187  void clean()
188  {
189  for (auto d : *this) {
190  delete d;
191  }
192  clear();
193  }
194 
195  //------------------------------------------------------------------------------
196  bool load(std::istream& stream)
197  {
198  for (uint32_t i = 0;
199  i < scn_->get_win_header()->get_number_of_rva_and_sizes(); ++i) {
200  std::unique_ptr<directory> d = std::make_unique<directory>(i);
201  if (!d->load(stream)) {
202  return false;
203  }
204  push_back(d.release());
205  }
206  return true;
207  }
208 
209  //------------------------------------------------------------------------------
210  bool load_data(std::istream& stream)
211  {
212  for (auto d : *this) {
213  if (!d->load_data(stream)) {
214  return false;
215  }
216  }
217  return true;
218  }
219 
220  //---------------------------------------------------------------------
221  void save(std::ostream& stream) const
222  {
223  for (auto d : *this) {
224  d->save(stream);
225  }
226  }
227 
228  //------------------------------------------------------------------------------
229  uint32_t get_sizeof() const
230  {
231  if (size() > 0) {
232  return narrow_cast<uint32_t>(size() * (*begin())->get_sizeof());
233  }
234  return 0;
235  }
236 
237  //------------------------------------------------------------------------------
238  protected:
239  //------------------------------------------------------------------------------
240  sections_provider* scn_;
241 };
242 
243 } // namespace COFFI
244 
245 #endif //COFFI_DIRECTORY_HPP
List of image data directories.
directories(const directories &)=delete
Discards the copy constructor.
Class for accessing an image data directory.
directory(const directory &)=delete
Discards the copy constructor.
Interface that gives the headers and sections.
virtual const win_header * get_win_header() const =0
Returns the Windows NT header.
COFFI library classes for the COFF file headers.
COFFI library classes for the COFF sections.
COFFI library utilities.
COFFI library namespace.
Definition: coffi.hpp:66