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
|
//===-- WindowsResource.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the .res file class.
//
//===----------------------------------------------------------------------===//
#include "llvm/Object/WindowsResource.h"
#include "llvm/Object/Error.h"
#include <system_error>
namespace llvm {
namespace object {
static const char ResourceMagic[] = {
'\0', '\0', '\0', '\0', '\x20', '\0', '\0', '\0',
'\xff', '\xff', '\0', '\0', '\xff', '\xff', '\0', '\0'};
static const char NullEntry[16] = {'\0'};
#define RETURN_IF_ERROR(X) \
if (auto EC = X) \
return EC;
WindowsResource::WindowsResource(MemoryBufferRef Source)
: Binary(Binary::ID_WinRes, Source) {
size_t LeadingSize = sizeof(ResourceMagic) + sizeof(NullEntry);
BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize),
support::little);
}
WindowsResource::~WindowsResource() = default;
Expected<std::unique_ptr<WindowsResource>>
WindowsResource::createWindowsResource(MemoryBufferRef Source) {
if (Source.getBufferSize() < sizeof(ResourceMagic) + sizeof(NullEntry))
return make_error<GenericBinaryError>(
"File too small to be a resource file",
object_error::invalid_file_type);
std::unique_ptr<WindowsResource> Ret(new WindowsResource(Source));
return std::move(Ret);
}
Expected<ResourceEntryRef> WindowsResource::getHeadEntry() {
Error Err = Error::success();
auto Ref = ResourceEntryRef(BinaryStreamRef(BBS), this, Err);
if (Err)
return std::move(Err);
return Ref;
}
ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref,
const WindowsResource *Owner, Error &Err)
: Reader(Ref), OwningRes(Owner) {
if (loadNext())
Err = make_error<GenericBinaryError>("Could not read first entry.",
object_error::unexpected_eof);
}
Error ResourceEntryRef::moveNext(bool &End) {
// Reached end of all the entries.
if (Reader.bytesRemaining() == 0) {
End = true;
return Error::success();
}
RETURN_IF_ERROR(loadNext());
return Error::success();
}
Error ResourceEntryRef::loadNext() {
uint32_t DataSize;
RETURN_IF_ERROR(Reader.readInteger(DataSize));
uint32_t HeaderSize;
RETURN_IF_ERROR(Reader.readInteger(HeaderSize));
// The data and header size ints are themselves part of the header, so we must
// subtract them from the size.
RETURN_IF_ERROR(
Reader.readStreamRef(HeaderBytes, HeaderSize - 2 * sizeof(uint32_t)));
RETURN_IF_ERROR(Reader.readStreamRef(DataBytes, DataSize));
RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
return Error::success();
}
} // namespace object
} // namespace llvm
|