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