blob: b525634690943134fc1468e345d804a57c8e89ce [file] [log] [blame]
Eric Beckmanna6bdf752017-05-20 01:49:19 +00001//===-- WindowsResource.cpp -------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the .res file class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Object/WindowsResource.h"
15#include "llvm/Object/Error.h"
16#include <system_error>
17
18namespace llvm {
19namespace object {
20
David Blaikief1c3bee2017-05-20 03:32:51 +000021static const size_t ResourceMagicSize = 16;
Eric Beckmanna6bdf752017-05-20 01:49:19 +000022
David Blaikief1c3bee2017-05-20 03:32:51 +000023static const size_t NullEntrySize = 16;
Eric Beckmanna6bdf752017-05-20 01:49:19 +000024
25#define RETURN_IF_ERROR(X) \
26 if (auto EC = X) \
27 return EC;
28
29WindowsResource::WindowsResource(MemoryBufferRef Source)
30 : Binary(Binary::ID_WinRes, Source) {
David Blaikief1c3bee2017-05-20 03:32:51 +000031 size_t LeadingSize = ResourceMagicSize + NullEntrySize;
Eric Beckmanna6bdf752017-05-20 01:49:19 +000032 BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize),
33 support::little);
34}
35
36WindowsResource::~WindowsResource() = default;
37
38Expected<std::unique_ptr<WindowsResource>>
39WindowsResource::createWindowsResource(MemoryBufferRef Source) {
David Blaikief1c3bee2017-05-20 03:32:51 +000040 if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize)
Eric Beckmanna6bdf752017-05-20 01:49:19 +000041 return make_error<GenericBinaryError>(
42 "File too small to be a resource file",
43 object_error::invalid_file_type);
44 std::unique_ptr<WindowsResource> Ret(new WindowsResource(Source));
45 return std::move(Ret);
46}
47
48Expected<ResourceEntryRef> WindowsResource::getHeadEntry() {
49 Error Err = Error::success();
50 auto Ref = ResourceEntryRef(BinaryStreamRef(BBS), this, Err);
51 if (Err)
52 return std::move(Err);
53 return Ref;
54}
55
56ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref,
57 const WindowsResource *Owner, Error &Err)
58 : Reader(Ref), OwningRes(Owner) {
59 if (loadNext())
60 Err = make_error<GenericBinaryError>("Could not read first entry.",
61 object_error::unexpected_eof);
62}
63
64Error ResourceEntryRef::moveNext(bool &End) {
65 // Reached end of all the entries.
66 if (Reader.bytesRemaining() == 0) {
67 End = true;
68 return Error::success();
69 }
70 RETURN_IF_ERROR(loadNext());
71
72 return Error::success();
73}
74
75Error ResourceEntryRef::loadNext() {
76 uint32_t DataSize;
77 RETURN_IF_ERROR(Reader.readInteger(DataSize));
78 uint32_t HeaderSize;
79 RETURN_IF_ERROR(Reader.readInteger(HeaderSize));
80 // The data and header size ints are themselves part of the header, so we must
81 // subtract them from the size.
82 RETURN_IF_ERROR(
83 Reader.readStreamRef(HeaderBytes, HeaderSize - 2 * sizeof(uint32_t)));
84 RETURN_IF_ERROR(Reader.readStreamRef(DataBytes, DataSize));
85 RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
86 return Error::success();
87}
88
89} // namespace object
90} // namespace llvm