1 //===-- 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 18 namespace llvm { 19 namespace object { 20 21 static const size_t ResourceMagicSize = 16; 22 23 static const size_t NullEntrySize = 16; 24 25 #define RETURN_IF_ERROR(X) \ 26 if (auto EC = X) \ 27 return EC; 28 29 WindowsResource::WindowsResource(MemoryBufferRef Source) 30 : Binary(Binary::ID_WinRes, Source) { 31 size_t LeadingSize = ResourceMagicSize + NullEntrySize; 32 BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize), 33 support::little); 34 } 35 36 WindowsResource::~WindowsResource() = default; 37 38 Expected<std::unique_ptr<WindowsResource>> 39 WindowsResource::createWindowsResource(MemoryBufferRef Source) { 40 if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize) 41 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 48 Expected<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 56 ResourceEntryRef::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 64 Error 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 75 Error 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 91