| /* | |
| * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| #include <algorithm> | |
| #include <fstream> | |
| #include "ResourceEditor.h" | |
| #include "WinErrorHandling.h" | |
| #include "Log.h" | |
| ResourceEditor::FileLock::FileLock(const std::wstring& binaryPath) { | |
| h = BeginUpdateResource(binaryPath.c_str(), FALSE); | |
| if (NULL == h) { | |
| JP_THROW(SysError(tstrings::any() << "BeginUpdateResource(" | |
| << binaryPath << ") failed", BeginUpdateResource)); | |
| } | |
| ownHandle(true); | |
| discard(false); | |
| notifyUnlockFailed(); | |
| } | |
| ResourceEditor::FileLock::FileLock(HANDLE h): h(h) { | |
| ownHandle(false); | |
| discard(false); | |
| notifyUnlockFailed(); | |
| } | |
| ResourceEditor::FileLock::~FileLock() { | |
| if (theOwnHandle && !EndUpdateResource(h, theDiscard)) { | |
| if (unlockFailed) { | |
| *unlockFailed = true; | |
| } | |
| JP_NO_THROW(JP_THROW(SysError(tstrings::any() | |
| << "EndUpdateResource(" << h << ") failed.", EndUpdateResource))); | |
| } else if (unlockFailed) { | |
| *unlockFailed = false; | |
| } | |
| } | |
| ResourceEditor::ResourceEditor() { | |
| language(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)).type(unsigned(0)).id(unsigned(0)); | |
| } | |
| ResourceEditor& ResourceEditor::type(unsigned v) { | |
| return type(MAKEINTRESOURCE(v)); | |
| } | |
| ResourceEditor& ResourceEditor::type(LPCWSTR v) { | |
| if (IS_INTRESOURCE(v)) { | |
| std::wostringstream printer; | |
| printer << L"#" << reinterpret_cast<size_t>(v); | |
| theType = printer.str(); | |
| theTypePtr = MAKEINTRESOURCE(static_cast<DWORD>(reinterpret_cast<DWORD_PTR>(v))); | |
| } else { | |
| theType = v; | |
| theTypePtr = theType.c_str(); | |
| } | |
| return *this; | |
| } | |
| ResourceEditor& ResourceEditor::id(unsigned v) { | |
| return id(MAKEINTRESOURCE(v)); | |
| } | |
| ResourceEditor& ResourceEditor::id(LPCWSTR v) { | |
| if (IS_INTRESOURCE(v)) { | |
| std::wostringstream printer; | |
| printer << L"#" << reinterpret_cast<size_t>(v); | |
| theId = printer.str(); | |
| } else { | |
| theId = v; | |
| } | |
| theIdPtr = v; | |
| return *this; | |
| } | |
| ResourceEditor& ResourceEditor::apply(const FileLock& dstBinary, | |
| std::istream& srcStream, std::streamsize size) { | |
| typedef std::vector<BYTE> ByteArray; | |
| ByteArray buf; | |
| if (size <= 0) { | |
| // Read the entire stream. | |
| buf = ByteArray((std::istreambuf_iterator<char>(srcStream)), | |
| std::istreambuf_iterator<char>()); | |
| } else { | |
| buf.resize(size_t(size)); | |
| srcStream.read(reinterpret_cast<char*>(buf.data()), size); | |
| } | |
| auto reply = UpdateResource(dstBinary.get(), theTypePtr, theIdPtr, lang, | |
| buf.data(), static_cast<DWORD>(buf.size())); | |
| if (reply == FALSE) { | |
| JP_THROW(SysError("UpdateResource() failed", UpdateResource)); | |
| } | |
| return *this; | |
| } | |
| ResourceEditor& ResourceEditor::apply(const FileLock& dstBinary, | |
| const std::wstring& srcFile) { | |
| std::ifstream input(srcFile, std::ios_base::binary); | |
| input.exceptions(std::ios::failbit | std::ios::badbit); | |
| return apply(dstBinary, input); | |
| } |