1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <algorithm> 27 #include <fstream> 28 #include "ResourceEditor.h" 29 #include "WinErrorHandling.h" 30 #include "Log.h" 31 32 33 ResourceEditor::FileLock::FileLock(const std::wstring& binaryPath) { 34 h = BeginUpdateResource(binaryPath.c_str(), FALSE); 35 if (NULL == h) { 36 JP_THROW(SysError(tstrings::any() << "BeginUpdateResource(" 37 << binaryPath << ") failed", BeginUpdateResource)); 38 } 39 40 discard(false); 41 } 42 43 44 ResourceEditor::FileLock::~FileLock() { 45 if (!EndUpdateResource(h, theDiscard)) { 46 JP_NO_THROW(JP_THROW(SysError(tstrings::any() 47 << "EndUpdateResource(" << h << ") failed.", EndUpdateResource))); 48 } 49 } 50 51 52 ResourceEditor::ResourceEditor() { 53 language(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)).type(unsigned(0)).id(unsigned(0)); 54 } 55 56 57 ResourceEditor& ResourceEditor::type(unsigned v) { 58 return type(MAKEINTRESOURCE(v)); 59 } 60 61 62 ResourceEditor& ResourceEditor::type(LPCWSTR v) { 63 if (IS_INTRESOURCE(v)) { 64 std::wostringstream printer; 65 printer << L"#" << reinterpret_cast<size_t>(v); 66 theType = printer.str(); 67 theTypePtr = MAKEINTRESOURCE(static_cast<DWORD>(reinterpret_cast<DWORD_PTR>(v))); 68 } else { 69 theType = v; 70 theTypePtr = theType.c_str(); 71 } 72 return *this; 73 } 74 75 76 ResourceEditor& ResourceEditor::id(unsigned v) { 77 return id(MAKEINTRESOURCE(v)); 78 } 79 80 81 ResourceEditor& ResourceEditor::id(LPCWSTR v) { 82 if (IS_INTRESOURCE(v)) { 83 std::wostringstream printer; 84 printer << L"#" << reinterpret_cast<size_t>(v); 85 theId = printer.str(); 86 } else { 87 theId = v; 88 theIdPtr = theId.c_str(); 89 } 90 return *this; 91 } 92 93 94 ResourceEditor& ResourceEditor::apply(const FileLock& dstBinary, 95 std::istream& srcStream, std::streamsize size) { 96 97 typedef std::vector<BYTE> ByteArray; 98 ByteArray buf; 99 if (size <= 0) { 100 // Read the entire stream. 101 buf = ByteArray((std::istreambuf_iterator<char>(srcStream)), 102 std::istreambuf_iterator<char>()); 103 } else { 104 buf.resize(size_t(size)); 105 srcStream.read(reinterpret_cast<char*>(buf.data()), size); 106 } 107 108 auto reply = UpdateResource(dstBinary.get(), theTypePtr, theIdPtr, lang, 109 buf.data(), static_cast<DWORD>(buf.size())); 110 if (reply == FALSE) { 111 JP_THROW(SysError("UpdateResource() failed", UpdateResource)); 112 } 113 114 return *this; 115 } 116 117 118 ResourceEditor& ResourceEditor::apply(const FileLock& dstBinary, 119 const std::wstring& srcFile) { 120 std::ifstream input(srcFile, std::ios_base::binary); 121 input.exceptions(std::ios::failbit | std::ios::badbit); 122 return apply(dstBinary, input); 123 }