| /* |
| * 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; |
| } |