summaryrefslogtreecommitdiff
path: root/utils/zenutils/libraries/pelib-0.9/pelib/BoundImportDirectory.cpp
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2008-07-11 15:50:46 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2008-07-11 15:50:46 +0000
commit14c7f45cdae826f88dc539c8c38dd95caf305731 (patch)
tree832da054b7cfb2dc6fd63339af736625f31d21aa /utils/zenutils/libraries/pelib-0.9/pelib/BoundImportDirectory.cpp
parent7c84ede3781c27db73403bd6302f320c76a58c8c (diff)
downloadrockbox-14c7f45cdae826f88dc539c8c38dd95caf305731.tar.gz
rockbox-14c7f45cdae826f88dc539c8c38dd95caf305731.zip
Add zook's ZenUtils to SVN
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18010 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/zenutils/libraries/pelib-0.9/pelib/BoundImportDirectory.cpp')
-rwxr-xr-xutils/zenutils/libraries/pelib-0.9/pelib/BoundImportDirectory.cpp511
1 files changed, 511 insertions, 0 deletions
diff --git a/utils/zenutils/libraries/pelib-0.9/pelib/BoundImportDirectory.cpp b/utils/zenutils/libraries/pelib-0.9/pelib/BoundImportDirectory.cpp
new file mode 100755
index 0000000000..5b84931838
--- /dev/null
+++ b/utils/zenutils/libraries/pelib-0.9/pelib/BoundImportDirectory.cpp
@@ -0,0 +1,511 @@
1/*
2* BoundImportDirectory.cpp - Part of the PeLib library.
3*
4* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
5* All rights reserved.
6*
7* This software is licensed under the zlib/libpng License.
8* For more details see http://www.opensource.org/licenses/zlib-license.php
9* or the license information file (license.htm) in the root directory
10* of PeLib.
11*/
12
13#include "PeLibInc.h"
14#include "BoundImportDirectory.h"
15#include <numeric>
16#include <set>
17#include <map>
18
19namespace PeLib
20{
21 /**
22 * Adds another bound import to the BoundImport directory.
23 * @param strModuleName Name of the PE file which will be imported.
24 * @param dwTds Value of the TimeDateStamp of the bound import field.
25 * @param wOmn Value of the OffsetModuleName of the bound import field.
26 * @param wWfr Value of the NumberOfModuleForwarderRefs of the bound import field.
27 **/
28 int BoundImportDirectory::addBoundImport(const std::string& strModuleName, dword dwTds, word wOmn, word wWfr)
29 {
30 for (unsigned int i=0;i<m_vIbd.size();i++)
31 {
32 if (isEqualNc(strModuleName, m_vIbd[i].strModuleName))
33 {
34 return ERROR_DUPLICATE_ENTRY;
35 }
36 }
37
38 PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR ibidCurrent;
39 ibidCurrent.TimeDateStamp = dwTds;
40 ibidCurrent.OffsetModuleName = wOmn;
41 ibidCurrent.NumberOfModuleForwarderRefs = wWfr;
42 PELIB_IMAGE_BOUND_DIRECTORY ibdCurrent;
43 ibdCurrent.ibdDescriptor = ibidCurrent;
44 ibdCurrent.strModuleName = strModuleName;
45 m_vIbd.push_back(ibdCurrent);
46
47 return NO_ERROR;
48 }
49
50 /**
51 * Searches for the first instance of a module with the given modulename.
52 * @param strModuleName The name of a module.
53 * @return The id of the module.
54 **/
55 int BoundImportDirectory::getModuleIndex(const std::string& strModuleName) const
56 {
57 std::vector<PELIB_IMAGE_BOUND_DIRECTORY>::const_iterator Iter = std::find_if(m_vIbd.begin(), m_vIbd.end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_BOUND_DIRECTORY::equal), strModuleName));
58
59 if (Iter == m_vIbd.end())
60 {
61 return ERROR_ENTRY_NOT_FOUND;
62 }
63
64 return static_cast<int>(std::distance(m_vIbd.begin(), Iter));
65 }
66
67 /**
68 * @return Number of files in the current BoundImport directory.
69 **/
70 unsigned int BoundImportDirectory::calcNumberOfModules() const
71 {
72 return static_cast<unsigned int>(m_vIbd.size());
73 }
74
75 int BoundImportDirectory::read(InputBuffer& inpBuffer, unsigned char* data, unsigned int dwSize)
76 {
77 std::vector<PELIB_IMAGE_BOUND_DIRECTORY> currentDirectory;
78
79 do
80 {
81 PELIB_IMAGE_BOUND_DIRECTORY ibdCurrent;
82
83 inpBuffer >> ibdCurrent.ibdDescriptor.TimeDateStamp;
84 inpBuffer >> ibdCurrent.ibdDescriptor.OffsetModuleName;
85 inpBuffer >> ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs;
86
87 if (ibdCurrent.ibdDescriptor.TimeDateStamp == 0 && ibdCurrent.ibdDescriptor.OffsetModuleName == 0 && ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs == 0) break;
88
89 for (int i=0;i<ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs;i++)
90 {
91 PELIB_IMAGE_BOUND_DIRECTORY currentForwarder;
92
93 inpBuffer >> currentForwarder.ibdDescriptor.TimeDateStamp;
94 inpBuffer >> currentForwarder.ibdDescriptor.OffsetModuleName;
95 inpBuffer >> currentForwarder.ibdDescriptor.NumberOfModuleForwarderRefs;
96
97 ibdCurrent.moduleForwarders.push_back(currentForwarder);
98 }
99
100 currentDirectory.push_back(ibdCurrent);
101 ibdCurrent.moduleForwarders.clear();
102 } while (true);
103
104 for (unsigned int i=0;i<currentDirectory.size();i++)
105 {
106 dword wOmn = currentDirectory[i].ibdDescriptor.OffsetModuleName;
107 if (wOmn > dwSize)
108 {
109 return ERROR_INVALID_FILE;
110 }
111
112 currentDirectory[i].strModuleName = "";
113 for (int k=0;data[wOmn + k] != 0 && k + wOmn < dwSize;k++)
114 {
115 currentDirectory[i].strModuleName += data[wOmn + k];
116 }
117
118 for (unsigned int j=0;j<currentDirectory[i].moduleForwarders.size();j++)
119 {
120 dword wOmn = currentDirectory[i].moduleForwarders[j].ibdDescriptor.OffsetModuleName;
121
122 if (wOmn > dwSize)
123 {
124 return ERROR_INVALID_FILE;
125 }
126
127// m_vIbd[i].moduleForwarders[j].strModuleName.assign((char*)(&vBimpDir[wOmn]));
128 currentDirectory[i].moduleForwarders[j].strModuleName = "";
129 for (int k=0;data[wOmn + k] != 0 && k + wOmn < dwSize;k++)
130 {
131 currentDirectory[i].moduleForwarders[j].strModuleName += data[wOmn + k];
132 }
133 }
134 }
135
136 std::swap(m_vIbd, currentDirectory);
137
138 return NO_ERROR;
139 }
140
141 /**
142 * Reads the BoundImport directory from a PE file.
143 * @param strModuleName The name of the PE file from which the BoundImport directory is read.
144 * @param dwOffset The file offset where the BoundImport directory can be found (see #PeFile::PeHeader::getIDBoundImportRVA).
145 * @param dwSize The size of the BoundImport directory (see #PeFile::PeHeader::getIDBoundImportSize).
146 **/
147 int BoundImportDirectory::read(const std::string& strModuleName, dword dwOffset, unsigned int uiSize)
148 {
149 std::ifstream ifFile(strModuleName.c_str(), std::ios::binary);
150
151 if (!ifFile)
152 {
153 return ERROR_OPENING_FILE;
154 }
155
156 if (fileSize(ifFile) < dwOffset + uiSize)
157 {
158 return ERROR_INVALID_FILE;
159 }
160
161 ifFile.seekg(dwOffset, std::ios::beg);
162
163 std::vector<unsigned char> vBimpDir(uiSize);
164 ifFile.read(reinterpret_cast<char*>(&vBimpDir[0]), uiSize);
165
166 InputBuffer inpBuffer(vBimpDir);
167
168 return read(inpBuffer, &vBimpDir[0], uiSize);
169 }
170
171 int BoundImportDirectory::read(unsigned char* pcBuffer, unsigned int uiSize)
172 {
173 std::vector<unsigned char> vBimpDir(pcBuffer, pcBuffer + uiSize);
174 InputBuffer inpBuffer(vBimpDir);
175
176 return read(inpBuffer, &vBimpDir[0], uiSize);
177 }
178
179 unsigned int BoundImportDirectory::totalModules() const
180 {
181 unsigned int modules = static_cast<unsigned int>(m_vIbd.size());
182
183 for (unsigned int i=0;i<m_vIbd.size();i++)
184 {
185 modules += static_cast<unsigned int>(m_vIbd[i].moduleForwarders.size());
186 }
187
188 return modules;
189 }
190
191 /**
192 * Rebuilds the BoundImport directory. The rebuilded BoundImport directory can then be
193 * written back to a PE file.
194 * @param vBuffer Buffer where the rebuilt BoundImport directory will be stored.
195 * @param fMakeValid If this flag is true a valid directory will be produced.
196 **/
197 void BoundImportDirectory::rebuild(std::vector<byte>& vBuffer, bool fMakeValid) const
198 {
199 std::map<std::string, word> filename_offsets;
200
201 OutputBuffer obBuffer(vBuffer);
202
203 word ulNameOffset = static_cast<word>((totalModules() + 1) * PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size());
204
205 for (unsigned int i=0;i<m_vIbd.size();i++)
206 {
207 obBuffer << m_vIbd[i].ibdDescriptor.TimeDateStamp;
208
209 // Recalculate the offsets if a valid directory is wanted.
210 if (fMakeValid)
211 {
212 if (filename_offsets.find(m_vIbd[i].strModuleName) == filename_offsets.end())
213 {
214 filename_offsets[m_vIbd[i].strModuleName] = ulNameOffset;
215 obBuffer << ulNameOffset;
216 ulNameOffset += static_cast<word>(m_vIbd[i].strModuleName.size() + 1);
217 }
218 else
219 {
220 obBuffer << filename_offsets[m_vIbd[i].strModuleName];
221 }
222 }
223 else // Otherwise just copy the old values into the buffer.
224 {
225 obBuffer << m_vIbd[i].ibdDescriptor.OffsetModuleName;
226 }
227
228 obBuffer << m_vIbd[i].ibdDescriptor.NumberOfModuleForwarderRefs;
229
230 for (int j=0;j<calcNumberOfModuleForwarderRefs(i);j++)
231 {
232 obBuffer << m_vIbd[i].moduleForwarders[j].ibdDescriptor.TimeDateStamp;
233
234 if (fMakeValid)
235 {
236 if (filename_offsets.find(m_vIbd[i].strModuleName) == filename_offsets.end())
237 {
238 filename_offsets[m_vIbd[i].moduleForwarders[j].strModuleName] = ulNameOffset;
239 obBuffer << ulNameOffset;
240 ulNameOffset += static_cast<word>(m_vIbd[i].moduleForwarders[j].strModuleName.size() + 1);
241 }
242 else
243 {
244 obBuffer << filename_offsets[m_vIbd[i].moduleForwarders[j].strModuleName];
245 }
246 }
247 else // Otherwise just copy the old values into the buffer.
248 {
249 obBuffer << m_vIbd[i].moduleForwarders[j].ibdDescriptor.OffsetModuleName;
250 }
251
252 obBuffer << m_vIbd[i].moduleForwarders[j].ibdDescriptor.NumberOfModuleForwarderRefs;
253 }
254 }
255
256 obBuffer << static_cast<dword>(0);
257 obBuffer << static_cast<word>(0);
258 obBuffer << static_cast<word>(0);
259
260 for (unsigned int i=0;i<m_vIbd.size();i++)
261 {
262 if (filename_offsets.find(m_vIbd[i].strModuleName) != filename_offsets.end())
263 {
264 obBuffer.add(getModuleName(i).c_str(), static_cast<unsigned long>(getModuleName(i).size() + 1));
265 filename_offsets.erase(m_vIbd[i].strModuleName);
266 }
267
268 for (int j=0;j<calcNumberOfModuleForwarderRefs(i);j++)
269 {
270 if (filename_offsets.find(getModuleName(i, j)) != filename_offsets.end())
271 {
272 obBuffer.add(getModuleName(i, j).c_str(), static_cast<unsigned long>(getModuleName(i, j).size() + 1));
273 filename_offsets.erase(getModuleName(i, j));
274 }
275 }
276 }
277 }
278
279 /**
280 * Removes all bound import files.
281 **/
282 void BoundImportDirectory::clear()
283 {
284 m_vIbd.clear();
285 }
286
287 /**
288 * Removes a field specified by the parameter filename from the BoundImport directory.
289 * @param strModuleName Name of the file whose field will be removed from the BoundImport directory.
290 **/
291 void BoundImportDirectory::removeBoundImport(const std::string& strModuleName)
292 {
293 m_vIbd.erase(std::remove_if(m_vIbd.begin(), m_vIbd.end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_BOUND_DIRECTORY::equal), strModuleName)), m_vIbd.end());
294 }
295
296 /**
297 * Returns the size of the rebuilt BoundImportDirectory.
298 * @return Size of the rebuilt BoundImportDirectory.
299 **/
300 unsigned int BoundImportDirectory::size() const
301 {
302 unsigned int size = PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size();
303
304 std::set<std::string> filenames;
305
306 for (unsigned int i = 0; i < m_vIbd.size(); i++)
307 {
308 filenames.insert(m_vIbd[i].strModuleName);
309
310 size += PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size();
311
312 for (unsigned int j = 0; j < m_vIbd[i].moduleForwarders.size(); j++)
313 {
314 filenames.insert(m_vIbd[i].moduleForwarders[j].strModuleName);
315
316 size += PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size();
317 }
318 }
319
320 for (std::set<std::string>::iterator iter = filenames.begin(); iter != filenames.end(); ++iter)
321 {
322 size += static_cast<unsigned int>(iter->size()) + 1;
323 }
324
325 return size;
326 }
327
328 /**
329 * @param strFilename Name of the file.
330 * @param dwOffset File offset the bound importdirectory will be written to.
331 * @param fMakeValid If this flag is true a valid directory will be produced.
332 **/
333 int BoundImportDirectory::write(const std::string& strFilename, dword dwOffset, bool fMakeValid) const
334 {
335 std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
336
337 if (!ofFile)
338 {
339 ofFile.clear();
340 ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
341 }
342 else
343 {
344 ofFile.close();
345 ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
346 }
347
348 if (!ofFile)
349 {
350 return ERROR_OPENING_FILE;
351 }
352
353 ofFile.seekp(dwOffset, std::ios::beg);
354
355 std::vector<unsigned char> vBuffer;
356 rebuild(vBuffer, fMakeValid);
357
358 ofFile.write(reinterpret_cast<const char*>(&vBuffer[0]), static_cast<std::streamsize>(vBuffer.size()));
359
360 ofFile.close();
361
362 return NO_ERROR;
363 }
364
365 /**
366 * Retrieves the value of the TimeDateStamp value of a bound import field.
367 * @param dwBidnr Number of the bound import field.
368 * @return Value of the TimeDateStamp of the bound import field.
369 **/
370 dword BoundImportDirectory::getTimeDateStamp(dword dwBidnr) const
371 {
372 return m_vIbd[dwBidnr].ibdDescriptor.TimeDateStamp;
373 }
374
375 /**
376 * Retrieves the value of the OffsetModuleName value of a bound import field.
377 * @param dwBidnr Number of the bound import field.
378 * @return Value of the OffsetModuleName of the bound import field.
379 **/
380 word BoundImportDirectory::getOffsetModuleName(dword dwBidnr) const
381 {
382 return m_vIbd[dwBidnr].ibdDescriptor.OffsetModuleName;
383 }
384
385 /**
386 * Retrieves the value of the NumberOfModuleForwarderRefs value of a bound import field.
387 * @param dwBidnr Number of the bound import field.
388 * @return Value of the NumberOfModuleForwarderRefs of the bound import field.
389 **/
390 word BoundImportDirectory::getNumberOfModuleForwarderRefs(dword dwBidnr) const
391 {
392 return m_vIbd[dwBidnr].ibdDescriptor.NumberOfModuleForwarderRefs;
393 }
394
395 /**
396 * Retrieves the value of the ModuleName value of a bound import field.
397 * @param dwBidnr Number of the bound import field.
398 * @return Value of the ModuleName of the bound import field.
399 **/
400 std::string BoundImportDirectory::getModuleName(dword dwBidnr) const
401 {
402 return m_vIbd[dwBidnr].strModuleName;
403 }
404
405 /**
406 * Changes the TimeDateStamp value of an existing bound import field.
407 * @param dwBidnr Number of the bound import field which will be changed.
408 * @param dwTds New value of the TimeDateStamp of the bound import field.
409 **/
410 void BoundImportDirectory::setTimeDateStamp(dword dwBidnr, dword dwTds)
411 {
412 m_vIbd[dwBidnr].ibdDescriptor.TimeDateStamp = dwTds;
413 }
414
415 /**
416 * Changes the OffsetModuleName value of an existing bound import field.
417 * @param dwBidnr Number of the bound import field which will be changed.
418 * @param wOmn New value of the OffsetModuleName of the bound import field.
419 **/
420 void BoundImportDirectory::setOffsetModuleName(dword dwBidnr, word wOmn)
421 {
422 m_vIbd[dwBidnr].ibdDescriptor.OffsetModuleName = wOmn;
423 }
424
425 /**
426 * Changes the NumberOfModuleForwarderRefs value of an existing bound import field.
427 * @param dwBidnr Number of the bound import field which will be changed.
428 * @param wMfr New value of the NumberOfModuleForwarderRefs of the bound import field.
429 **/
430 void BoundImportDirectory::setNumberOfModuleForwarderRefs(dword dwBidnr, word wMfr)
431 {
432 m_vIbd[dwBidnr].ibdDescriptor.NumberOfModuleForwarderRefs = wMfr;
433 }
434
435 /**
436 * Changes the ModuleName value of an existing bound import field.
437 * @param dwBidnr Number of the bound import field which will be changed.
438 * @param strModuleName New value of the ModuleName of the bound import field.
439 **/
440 void BoundImportDirectory::setModuleName(dword dwBidnr, const std::string& strModuleName)
441 {
442 m_vIbd[dwBidnr].strModuleName = strModuleName;
443 }
444
445 dword BoundImportDirectory::getTimeDateStamp(dword dwBidnr, dword forwardedModule) const
446 {
447 return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.TimeDateStamp;
448 }
449
450 word BoundImportDirectory::getOffsetModuleName(dword dwBidnr, dword forwardedModule) const
451 {
452 return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.OffsetModuleName;
453 }
454
455 word BoundImportDirectory::getNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule) const
456 {
457 return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.NumberOfModuleForwarderRefs;
458 }
459
460 std::string BoundImportDirectory::getModuleName(dword dwBidnr, dword forwardedModule) const
461 {
462 return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].strModuleName;
463 }
464
465 void BoundImportDirectory::setTimeDateStamp(dword dwBidnr, dword forwardedModule, dword dwTds)
466 {
467 m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.TimeDateStamp = dwTds;
468 }
469
470 void BoundImportDirectory::setOffsetModuleName(dword dwBidnr, dword forwardedModule, word wOmn)
471 {
472 m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.OffsetModuleName = wOmn;
473 }
474
475 void BoundImportDirectory::setNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule, word wMfr)
476 {
477 m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.NumberOfModuleForwarderRefs = wMfr;
478 }
479
480 void BoundImportDirectory::setModuleName(dword dwBidnr, dword forwardedModule, const std::string& strModuleName)
481 {
482 m_vIbd[dwBidnr].moduleForwarders[forwardedModule].strModuleName = strModuleName;
483 }
484
485 word BoundImportDirectory::calcNumberOfModuleForwarderRefs(dword dwBidnr) const
486 {
487 return static_cast<word>(m_vIbd[dwBidnr].moduleForwarders.size());
488 }
489
490 void BoundImportDirectory::addForwardedModule(dword dwBidnr, const std::string& name, dword timeStamp, word offsetModuleName, word forwardedModules)
491 {
492 // XXX: Maybe test if there are already 0xFFFF forwarded modules.
493 // XXX: Check for duplicate entries. Is it also necessary to check
494 // non-forwarded entries and forwarded entries in other non-forwarded
495 // entries?
496 // XXX: Can forwarders forward recursively?
497
498 PELIB_IMAGE_BOUND_DIRECTORY ibdCurrent;
499 ibdCurrent.strModuleName = name;
500 ibdCurrent.ibdDescriptor.TimeDateStamp = timeStamp;
501 ibdCurrent.ibdDescriptor.OffsetModuleName = offsetModuleName;
502 ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs = forwardedModules;
503
504 m_vIbd[dwBidnr].moduleForwarders.push_back(ibdCurrent);
505 }
506
507 void BoundImportDirectory::removeForwardedModule(dword dwBidnr, word forwardedModule)
508 {
509 m_vIbd[dwBidnr].moduleForwarders.erase(m_vIbd[dwBidnr].moduleForwarders.begin() + forwardedModule);
510 }
511}