src/jdk.incubator.jpackage/windows/native/msiwrapper/Resources.cpp
branchJDK-8200758-branch
changeset 58994 b09ba68c6a19
parent 57909 c7de06ed4b54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/msiwrapper/Resources.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2019, 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 "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 wee 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);
+}