| /* | |
| * Copyright (c) 2019, 2022, 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 "Resources.h" | |
| #include "FileUtils.h" | |
| #include "WinFileUtils.h" | |
| #include "WinErrorHandling.h" | |
| #include <fstream> | |
| Resource::Resource(LPCTSTR name, LPCTSTR type, HINSTANCE module) { | |
| init(name, type, module); | |
| } | |
| Resource::Resource(UINT id, LPCTSTR type, HINSTANCE module) { | |
| init(MAKEINTRESOURCE(id), type, module); | |
| } | |
| void Resource::init(LPCTSTR name, LPCTSTR type, HINSTANCE module) { | |
| if (IS_INTRESOURCE(name)) { | |
| std::wostringstream printer; | |
| printer << L"#" << reinterpret_cast<size_t>(name); | |
| nameStr = printer.str(); | |
| namePtr = name; | |
| } else { | |
| nameStr = name; | |
| namePtr = nameStr.c_str(); | |
| } | |
| if (IS_INTRESOURCE(type)) { | |
| std::wostringstream printer; | |
| printer << L"#" << reinterpret_cast<size_t>(name); | |
| typeStr = printer.str(); | |
| typePtr = type; | |
| } else { | |
| typeStr = type; | |
| typePtr = typeStr.c_str(); | |
| } | |
| instance = module; | |
| } | |
| std::string Resource::getErrMsg(const std::string &descr) const { | |
| return (tstrings::any() << descr << " (name='" << nameStr << | |
| "', type='" << typeStr << "')").str(); | |
| } | |
| HRSRC Resource::findResource() const { | |
| LPCTSTR id = namePtr; | |
| // string resources are stored in blocks (stringtables) | |
| // id of the resource is (stringId / 16 + 1) | |
| if (typePtr == RT_STRING) { | |
| id = MAKEINTRESOURCE(UINT(size_t(id) / 16 + 1)); | |
| } | |
| return FindResource(instance, id, typePtr); | |
| } | |
| LPVOID Resource::getPtr(DWORD &size) const | |
| { | |
| // LoadString returns the same result if value is zero-length or | |
| // if if the value does not exists, | |
| // so we need to ensure the stringtable exists | |
| HRSRC resInfo = findResource(); | |
| if (resInfo == NULL) { | |
| JP_THROW(SysError(getErrMsg("cannot find resource"), FindResource)); | |
| } | |
| HGLOBAL res = LoadResource(instance, resInfo); | |
| if (res == NULL) { | |
| JP_THROW(SysError(getErrMsg("cannot load resource"), LoadResource)); | |
| } | |
| LPVOID ptr = LockResource(res); | |
| if (res == NULL) { | |
| JP_THROW(SysError(getErrMsg("cannot lock resource"), LockResource)); | |
| } | |
| if (typePtr == RT_STRING) { | |
| // string resources are stored in stringtables and | |
| // need special handling | |
| // The simplest way (while we don't need handle resource locale) | |
| // is LoadString | |
| // But this adds dependency on user32.dll, | |
| // so implement custom string extraction | |
| // number in the block (namePtr is an integer) | |
| size_t num = size_t(namePtr) & 0xf; | |
| LPWSTR strPtr = (LPWSTR)ptr; | |
| for (size_t i = 0; i < num; i++) { | |
| // 1st symbol contains string length | |
| strPtr += DWORD(*strPtr) + 1; | |
| } | |
| // *strPtr contains string length, string value starts at strPtr+1 | |
| size = DWORD(*strPtr) * sizeof(wchar_t); | |
| ptr = strPtr+1; | |
| } else { | |
| size = SizeofResource(instance, resInfo); | |
| } | |
| return ptr; | |
| } | |
| bool Resource::available() const { | |
| return NULL != findResource(); | |
| } | |
| unsigned Resource::size() const { | |
| DWORD size = 0; | |
| getPtr(size); | |
| return size; | |
| } | |
| LPCVOID Resource::rawData() const { | |
| DWORD size = 0; | |
| return getPtr(size); | |
| } | |
| void Resource::saveToFile(const std::wstring &filePath) const { | |
| DWORD size = 0; | |
| const char *resPtr = (const char *)getPtr(size); | |
| FileUtils::FileWriter(filePath).write(resPtr, size).finalize(); | |
| } | |
| Resource::ByteArray Resource::binary() const { | |
| DWORD size = 0; | |
| LPBYTE resPtr = (LPBYTE)getPtr(size); | |
| return ByteArray(resPtr, resPtr+size); | |
| } | |
| tstring StringResource::string() const | |
| { | |
| DWORD size = 0; | |
| // string are stored as UNICODE | |
| LPWSTR resPtr = reinterpret_cast<LPWSTR>(impl.getPtr(size)); | |
| // size is in bytes; | |
| return tstrings::fromUtf16(std::wstring(resPtr, size / sizeof(wchar_t))); | |
| } | |
| tstring StringResource::string(const std::nothrow_t &, const tstring &defValue) const throw() | |
| { | |
| JP_TRY; | |
| return string(); | |
| JP_CATCH_ALL; | |
| return defValue; | |
| } |