--- old/src/jdk.jpackage/windows/native/libapplauncher/WindowsPlatform.cpp 2019-11-18 21:15:42.557250000 -0500 +++ /dev/null 2019-11-18 21:15:43.000000000 -0500 @@ -1,761 +0,0 @@ -/* - * Copyright (c) 2014, 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 "Platform.h" - -#include "JavaVirtualMachine.h" -#include "WindowsPlatform.h" -#include "Package.h" -#include "Helpers.h" -#include "PlatformString.h" -#include "Macros.h" - -#include -#include -#include -#include -#include -#include - -using namespace std; - -#define WINDOWS_JPACKAGE_TMP_DIR \ - L"\\AppData\\Local\\Java\\JPackage\\tmp" - -class Registry { -private: - HKEY FKey; - HKEY FOpenKey; - bool FOpen; - -public: - - Registry(HKEY Key) { - FOpen = false; - FKey = Key; - } - - ~Registry() { - Close(); - } - - void Close() { - if (FOpen == true) { - RegCloseKey(FOpenKey); - } - } - - bool Open(TString SubKey) { - bool result = false; - Close(); - - if (RegOpenKeyEx(FKey, SubKey.data(), 0, KEY_READ, &FOpenKey) == - ERROR_SUCCESS) { - result = true; - } - - return result; - } - - std::list GetKeys() { - std::list result; - DWORD count; - - if (RegQueryInfoKey(FOpenKey, NULL, NULL, NULL, NULL, NULL, NULL, - &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { - - DWORD length = 255; - DynamicBuffer buffer(length); - if (buffer.GetData() == NULL) { - return result; - } - - for (unsigned int index = 0; index < count; index++) { - buffer.Zero(); - DWORD status = RegEnumValue(FOpenKey, index, buffer.GetData(), - &length, NULL, NULL, NULL, NULL); - - while (status == ERROR_MORE_DATA) { - length = length * 2; - if (!buffer.Resize(length)) { - return result; - } - status = RegEnumValue(FOpenKey, index, buffer.GetData(), - &length, NULL, NULL, NULL, NULL); - } - - if (status == ERROR_SUCCESS) { - TString value = buffer.GetData(); - result.push_back(value); - } - } - } - - return result; - } - - TString ReadString(TString Name) { - TString result; - DWORD length; - DWORD dwRet; - DynamicBuffer buffer(0); - length = 0; - - dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, NULL, - &length); - if (dwRet == ERROR_MORE_DATA || dwRet == 0) { - if (!buffer.Resize(length + 1)) { - return result; - } - dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, - (LPBYTE) buffer.GetData(), &length); - result = buffer.GetData(); - } - - return result; - } -}; - -WindowsPlatform::WindowsPlatform(void) : Platform() { - FMainThread = ::GetCurrentThreadId(); -} - -WindowsPlatform::~WindowsPlatform(void) { -} - -TString WindowsPlatform::GetPackageAppDirectory() { - return FilePath::IncludeTrailingSeparator( - GetPackageRootDirectory()) + _T("app"); -} - -TString WindowsPlatform::GetPackageLauncherDirectory() { - return GetPackageRootDirectory(); -} - -TString WindowsPlatform::GetPackageRuntimeBinDirectory() { - return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) + _T("runtime\\bin"); -} - -TCHAR* WindowsPlatform::ConvertStringToFileSystemString(TCHAR* Source, - bool &release) { - // Not Implemented. - return NULL; -} - -TCHAR* WindowsPlatform::ConvertFileSystemStringToString(TCHAR* Source, - bool &release) { - // Not Implemented. - return NULL; -} - -void WindowsPlatform::SetCurrentDirectory(TString Value) { - _wchdir(Value.data()); -} - -TString WindowsPlatform::GetPackageRootDirectory() { - TString filename = GetModuleFileName(); - return FilePath::ExtractFilePath(filename); -} - -TString WindowsPlatform::GetAppDataDirectory() { - TString result; - TCHAR path[MAX_PATH]; - - if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path) == S_OK) { - result = path; - } - - return result; -} - -TString WindowsPlatform::GetAppName() { - TString result = GetModuleFileName(); - result = FilePath::ExtractFileName(result); - result = FilePath::ChangeFileExt(result, _T("")); - return result; -} - -void WindowsPlatform::ShowMessage(TString title, TString description) { - MessageBox(NULL, description.data(), - !title.empty() ? title.data() : description.data(), - MB_ICONERROR | MB_OK); -} - -void WindowsPlatform::ShowMessage(TString description) { - TString appname = GetModuleFileName(); - appname = FilePath::ExtractFileName(appname); - MessageBox(NULL, description.data(), appname.data(), MB_ICONERROR | MB_OK); -} - -MessageResponse WindowsPlatform::ShowResponseMessage(TString title, - TString description) { - MessageResponse result = mrCancel; - - if (::MessageBox(NULL, description.data(), title.data(), MB_OKCANCEL) == - IDOK) { - result = mrOK; - } - - return result; -} - -TString WindowsPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) { - TString result = FilePath::IncludeTrailingSeparator(RuntimePath) + - _T("jre\\bin\\jli.dll"); - - if (FilePath::FileExists(result) == false) { - result = FilePath::IncludeTrailingSeparator(RuntimePath) + - _T("bin\\jli.dll"); - } - - return result; -} - -ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) { - IniFile *result = new IniFile(); - if (result == NULL) { - return NULL; - } - - result->LoadFromFile(FileName); - - return result; -} - -TString WindowsPlatform::GetModuleFileName() { - TString result; - DynamicBuffer buffer(MAX_PATH); - if (buffer.GetData() == NULL) { - return result; - } - - ::GetModuleFileName(NULL, buffer.GetData(), - static_cast (buffer.GetSize())); - - while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { - if (!buffer.Resize(buffer.GetSize() * 2)) { - return result; - } - ::GetModuleFileName(NULL, buffer.GetData(), - static_cast (buffer.GetSize())); - } - - result = buffer.GetData(); - return result; -} - -Module WindowsPlatform::LoadLibrary(TString FileName) { - return ::LoadLibrary(FileName.data()); -} - -void WindowsPlatform::FreeLibrary(Module AModule) { - ::FreeLibrary((HMODULE) AModule); -} - -Procedure WindowsPlatform::GetProcAddress(Module AModule, - std::string MethodName) { - return ::GetProcAddress((HMODULE) AModule, MethodName.c_str()); -} - -bool WindowsPlatform::IsMainThread() { - bool result = (FMainThread == ::GetCurrentThreadId()); - return result; -} - -TString WindowsPlatform::GetTempDirectory() { - TString result; - PWSTR userDir = 0; - - if (SUCCEEDED(SHGetKnownFolderPath( - FOLDERID_Profile, - 0, - NULL, - &userDir))) { - result = userDir; - result += WINDOWS_JPACKAGE_TMP_DIR; - CoTaskMemFree(userDir); - } - - return result; -} - -static BOOL CALLBACK enumWindows(HWND winHandle, LPARAM lParam) { - DWORD pid = (DWORD) lParam, wPid = 0; - GetWindowThreadProcessId(winHandle, &wPid); - if (pid == wPid) { - SetForegroundWindow(winHandle); - return FALSE; - } - return TRUE; -} - -TPlatformNumber WindowsPlatform::GetMemorySize() { - SYSTEM_INFO si; - GetSystemInfo(&si); - size_t result = (size_t) si.lpMaximumApplicationAddress; - result = result / 1048576; // Convert from bytes to megabytes. - return result; -} - -std::vector FilterList(std::vector &Items, - std::wregex Pattern) { - std::vector result; - - for (std::vector::iterator it = Items.begin(); - it != Items.end(); ++it) { - TString item = *it; - std::wsmatch match; - - if (std::regex_search(item, match, Pattern)) { - result.push_back(item); - } - } - return result; -} - -Process* WindowsPlatform::CreateProcess() { - return new WindowsProcess(); -} - -void WindowsPlatform::InitStreamLocale(wios *stream) { - const std::locale empty_locale = std::locale::empty(); - const std::locale utf8_locale = - std::locale(empty_locale, new std::codecvt_utf8()); - stream->imbue(utf8_locale); -} - -void WindowsPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) { - if (pJavaLibrary == NULL) { - return; - } - - if (FilePath::FileExists(_T("msvcr100.dll")) == true) { - pJavaLibrary->AddDependency(_T("msvcr100.dll")); - } - - TString runtimeBin = GetPackageRuntimeBinDirectory(); - SetDllDirectory(runtimeBin.c_str()); -} - -void Platform::CopyString(char *Destination, - size_t NumberOfElements, const char *Source) { - strcpy_s(Destination, NumberOfElements, Source); - - if (NumberOfElements > 0) { - Destination[NumberOfElements - 1] = '\0'; - } -} - -void Platform::CopyString(wchar_t *Destination, - size_t NumberOfElements, const wchar_t *Source) { - wcscpy_s(Destination, NumberOfElements, Source); - - if (NumberOfElements > 0) { - Destination[NumberOfElements - 1] = '\0'; - } -} - -// Owner must free the return value. -MultibyteString Platform::WideStringToMultibyteString( - const wchar_t* value) { - MultibyteString result; - size_t count = 0; - - if (value == NULL) { - return result; - } - - count = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL); - - if (count > 0) { - result.data = new char[count + 1]; - result.length = WideCharToMultiByte(CP_UTF8, 0, value, -1, - result.data, (int)count, NULL, NULL); - } - - return result; -} - -// Owner must free the return value. -WideString Platform::MultibyteStringToWideString(const char* value) { - WideString result; - size_t count = 0; - - if (value == NULL) { - return result; - } - - mbstowcs_s(&count, NULL, 0, value, _TRUNCATE); - - if (count > 0) { - result.data = new wchar_t[count + 1]; - mbstowcs_s(&result.length, result.data, count, value, count); - } - - return result; -} - -FileHandle::FileHandle(std::wstring FileName) { - FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); -} - -FileHandle::~FileHandle() { - if (IsValid() == true) { - ::CloseHandle(FHandle); - } -} - -bool FileHandle::IsValid() { - return FHandle != INVALID_HANDLE_VALUE; -} - -HANDLE FileHandle::GetHandle() { - return FHandle; -} - -FileMappingHandle::FileMappingHandle(HANDLE FileHandle) { - FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL); -} - -bool FileMappingHandle::IsValid() { - return FHandle != NULL; -} - -FileMappingHandle::~FileMappingHandle() { - if (IsValid() == true) { - ::CloseHandle(FHandle); - } -} - -HANDLE FileMappingHandle::GetHandle() { - return FHandle; -} - -FileData::FileData(HANDLE Handle) { - FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0); -} - -FileData::~FileData() { - if (IsValid() == true) { - ::UnmapViewOfFile(FBaseAddress); - } -} - -bool FileData::IsValid() { - return FBaseAddress != NULL; -} - -LPVOID FileData::GetBaseAddress() { - return FBaseAddress; -} - -WindowsLibrary::WindowsLibrary(std::wstring FileName) { - FFileName = FileName; -} - -std::vector WindowsLibrary::GetImports() { - std::vector result; - FileHandle library(FFileName); - - if (library.IsValid() == true) { - FileMappingHandle mapping(library.GetHandle()); - - if (mapping.IsValid() == true) { - FileData fileData(mapping.GetHandle()); - - if (fileData.IsValid() == true) { - PIMAGE_DOS_HEADER dosHeader = - (PIMAGE_DOS_HEADER) fileData.GetBaseAddress(); - PIMAGE_FILE_HEADER pImgFileHdr = - (PIMAGE_FILE_HEADER) fileData.GetBaseAddress(); - if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { - result = DumpPEFile(dosHeader); - } - } - } - } - - return result; -} - -// Given an RVA, look up the section header that encloses it and return a -// pointer to its IMAGE_SECTION_HEADER - -PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva, - PIMAGE_NT_HEADERS pNTHeader) { - PIMAGE_SECTION_HEADER result = 0; - PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader); - - for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections; - index++, section++) { - // Is the RVA is within this section? - if ((rva >= section->VirtualAddress) && - (rva < (section->VirtualAddress + section->Misc.VirtualSize))) { - result = section; - } - } - - return result; -} - -LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader, - DWORD imageBase) { - LPVOID result = 0; - PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva, - pNTHeader); - - if (pSectionHdr != NULL) { - INT delta = (INT) ( - pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData); - DWORD_PTR dwp = (DWORD_PTR) (imageBase + rva - delta); - result = reinterpret_cast (dwp); // VS2017 - FIXME - } - - return result; -} - -std::vector WindowsLibrary::GetImportsSection(DWORD base, - PIMAGE_NT_HEADERS pNTHeader) { - std::vector result; - - // Look up where the imports section is located. Normally in - // the .idata section, - // but not necessarily so. Therefore, grab the RVA from the data dir. - DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[ - IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; - - if (importsStartRVA != NULL) { - // Get the IMAGE_SECTION_HEADER that contains the imports. This is - // usually the .idata section, but doesn't have to be. - PIMAGE_SECTION_HEADER pSection = - GetEnclosingSectionHeader(importsStartRVA, pNTHeader); - - if (pSection != NULL) { - PIMAGE_IMPORT_DESCRIPTOR importDesc = - (PIMAGE_IMPORT_DESCRIPTOR) GetPtrFromRVA( - importsStartRVA, pNTHeader, base); - - if (importDesc != NULL) { - while (true) { - // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR - if ((importDesc->TimeDateStamp == 0) && - (importDesc->Name == 0)) { - break; - } - - std::string filename = (char*) GetPtrFromRVA( - importDesc->Name, pNTHeader, base); - result.push_back(PlatformString(filename)); - importDesc++; // advance to next IMAGE_IMPORT_DESCRIPTOR - } - } - } - } - - return result; -} - -std::vector WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) { - std::vector result; - // all of this is VS2017 - FIXME - DWORD_PTR dwDosHeaders = reinterpret_cast (dosHeader); - DWORD_PTR dwPIHeaders = dwDosHeaders + (DWORD) (dosHeader->e_lfanew); - - PIMAGE_NT_HEADERS pNTHeader = - reinterpret_cast (dwPIHeaders); - - // Verify that the e_lfanew field gave us a reasonable - // pointer and the PE signature. - // TODO: To really fix JDK-8131321 this condition needs to be changed. - // There is a matching change - // in JavaVirtualMachine.cpp that also needs to be changed. - if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) { - DWORD base = (DWORD) (dwDosHeaders); - result = GetImportsSection(base, pNTHeader); - } - - return result; -} - -#include - -WindowsJob::WindowsJob() { - FHandle = NULL; -} - -WindowsJob::~WindowsJob() { - if (FHandle != NULL) { - CloseHandle(FHandle); - } -} - -HANDLE WindowsJob::GetHandle() { - if (FHandle == NULL) { - FHandle = CreateJobObject(NULL, NULL); // GLOBAL - - if (FHandle == NULL) { - ::MessageBox(0, _T("Could not create job object"), - _T("TEST"), MB_OK); - } else { - JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0}; - - // Configure all child processes associated with - // the job to terminate when the - jeli.BasicLimitInformation.LimitFlags = - JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - if (0 == SetInformationJobObject(FHandle, - JobObjectExtendedLimitInformation, &jeli, sizeof (jeli))) { - ::MessageBox(0, _T("Could not SetInformationJobObject"), - _T("TEST"), MB_OK); - } - } - } - - return FHandle; -} - -// Initialize static member of WindowsProcess -WindowsJob WindowsProcess::FJob; - -WindowsProcess::WindowsProcess() : Process() { - FRunning = false; -} - -WindowsProcess::~WindowsProcess() { - Terminate(); -} - -void WindowsProcess::Cleanup() { - CloseHandle(FProcessInfo.hProcess); - CloseHandle(FProcessInfo.hThread); -} - -bool WindowsProcess::IsRunning() { - bool result = false; - - HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); - if (handle == INVALID_HANDLE_VALUE) { - return false; - } - - PROCESSENTRY32 process = {0}; - process.dwSize = sizeof (process); - - if (::Process32First(handle, &process)) { - do { - if (process.th32ProcessID == FProcessInfo.dwProcessId) { - result = true; - break; - } - } while (::Process32Next(handle, &process)); - } - - CloseHandle(handle); - - return result; -} - -bool WindowsProcess::Terminate() { - bool result = false; - - if (IsRunning() == true && FRunning == true) { - FRunning = false; - } - - return result; -} - -bool WindowsProcess::Execute(const TString Application, - const std::vector Arguments, bool AWait) { - bool result = false; - - if (FRunning == false) { - FRunning = true; - - STARTUPINFO startupInfo; - ZeroMemory(&startupInfo, sizeof (startupInfo)); - startupInfo.cb = sizeof (startupInfo); - ZeroMemory(&FProcessInfo, sizeof (FProcessInfo)); - - TString command = Application; - - for (std::vector::const_iterator iterator = Arguments.begin(); - iterator != Arguments.end(); iterator++) { - command += TString(_T(" ")) + *iterator; - } - - if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL, - NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo) == FALSE) { - TString message = PlatformString::Format( - _T("Error: Unable to create process %s"), - Application.data()); - throw Exception(message); - } else { - if (FJob.GetHandle() != NULL) { - if (::AssignProcessToJobObject(FJob.GetHandle(), - FProcessInfo.hProcess) == 0) { - // Failed to assign process to job. It doesn't prevent - // anything from continuing so continue. - } - } - - // Wait until child process exits. - if (AWait == true) { - Wait(); - // Close process and thread handles. - Cleanup(); - } - } - } - - return result; -} - -bool WindowsProcess::Wait() { - bool result = false; - - WaitForSingleObject(FProcessInfo.hProcess, INFINITE); - return result; -} - -TProcessID WindowsProcess::GetProcessID() { - return FProcessInfo.dwProcessId; -} - -bool WindowsProcess::ReadOutput() { - bool result = false; - // TODO implement - return result; -} - -void WindowsProcess::SetInput(TString Value) { - // TODO implement -} - -std::list WindowsProcess::GetOutput() { - ReadOutput(); - return Process::GetOutput(); -} --- /dev/null 2019-11-18 21:15:44.000000000 -0500 +++ new/src/jdk.incubator.jpackage/windows/native/libapplauncher/WindowsPlatform.cpp 2019-11-18 21:15:39.203493800 -0500 @@ -0,0 +1,759 @@ +/* + * Copyright (c) 2014, 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 "Platform.h" + +#include "JavaVirtualMachine.h" +#include "WindowsPlatform.h" +#include "Package.h" +#include "Helpers.h" +#include "PlatformString.h" +#include "Macros.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define WINDOWS_JPACKAGE_TMP_DIR \ + L"\\AppData\\Local\\Java\\JPackage\\tmp" + +class Registry { +private: + HKEY FKey; + HKEY FOpenKey; + bool FOpen; + +public: + + Registry(HKEY Key) { + FOpen = false; + FKey = Key; + } + + ~Registry() { + Close(); + } + + void Close() { + if (FOpen == true) { + RegCloseKey(FOpenKey); + } + } + + bool Open(TString SubKey) { + bool result = false; + Close(); + + if (RegOpenKeyEx(FKey, SubKey.data(), 0, KEY_READ, &FOpenKey) == + ERROR_SUCCESS) { + result = true; + } + + return result; + } + + std::list GetKeys() { + std::list result; + DWORD count; + + if (RegQueryInfoKey(FOpenKey, NULL, NULL, NULL, NULL, NULL, NULL, + &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + + DWORD length = 255; + DynamicBuffer buffer(length); + if (buffer.GetData() == NULL) { + return result; + } + + for (unsigned int index = 0; index < count; index++) { + buffer.Zero(); + DWORD status = RegEnumValue(FOpenKey, index, buffer.GetData(), + &length, NULL, NULL, NULL, NULL); + + while (status == ERROR_MORE_DATA) { + length = length * 2; + if (!buffer.Resize(length)) { + return result; + } + status = RegEnumValue(FOpenKey, index, buffer.GetData(), + &length, NULL, NULL, NULL, NULL); + } + + if (status == ERROR_SUCCESS) { + TString value = buffer.GetData(); + result.push_back(value); + } + } + } + + return result; + } + + TString ReadString(TString Name) { + TString result; + DWORD length; + DWORD dwRet; + DynamicBuffer buffer(0); + length = 0; + + dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, NULL, + &length); + if (dwRet == ERROR_MORE_DATA || dwRet == 0) { + if (!buffer.Resize(length + 1)) { + return result; + } + dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, + (LPBYTE) buffer.GetData(), &length); + result = buffer.GetData(); + } + + return result; + } +}; + +WindowsPlatform::WindowsPlatform(void) : Platform() { + FMainThread = ::GetCurrentThreadId(); +} + +WindowsPlatform::~WindowsPlatform(void) { +} + +TString WindowsPlatform::GetPackageAppDirectory() { + return FilePath::IncludeTrailingSeparator( + GetPackageRootDirectory()) + _T("app"); +} + +TString WindowsPlatform::GetPackageLauncherDirectory() { + return GetPackageRootDirectory(); +} + +TString WindowsPlatform::GetPackageRuntimeBinDirectory() { + return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) + _T("runtime\\bin"); +} + +TCHAR* WindowsPlatform::ConvertStringToFileSystemString(TCHAR* Source, + bool &release) { + // Not Implemented. + return NULL; +} + +TCHAR* WindowsPlatform::ConvertFileSystemStringToString(TCHAR* Source, + bool &release) { + // Not Implemented. + return NULL; +} + +TString WindowsPlatform::GetPackageRootDirectory() { + TString result; + TString filename = GetModuleFileName(); + return FilePath::ExtractFilePath(filename); +} + +TString WindowsPlatform::GetAppDataDirectory() { + TString result; + TCHAR path[MAX_PATH]; + + if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path) == S_OK) { + result = path; + } + + return result; +} + +TString WindowsPlatform::GetAppName() { + TString result = GetModuleFileName(); + result = FilePath::ExtractFileName(result); + result = FilePath::ChangeFileExt(result, _T("")); + return result; +} + +void WindowsPlatform::ShowMessage(TString title, TString description) { + MessageBox(NULL, description.data(), + !title.empty() ? title.data() : description.data(), + MB_ICONERROR | MB_OK); +} + +void WindowsPlatform::ShowMessage(TString description) { + TString appname = GetModuleFileName(); + appname = FilePath::ExtractFileName(appname); + MessageBox(NULL, description.data(), appname.data(), MB_ICONERROR | MB_OK); +} + +MessageResponse WindowsPlatform::ShowResponseMessage(TString title, + TString description) { + MessageResponse result = mrCancel; + + if (::MessageBox(NULL, description.data(), title.data(), MB_OKCANCEL) == + IDOK) { + result = mrOK; + } + + return result; +} + +TString WindowsPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) { + TString result = FilePath::IncludeTrailingSeparator(RuntimePath) + + _T("jre\\bin\\jli.dll"); + + if (FilePath::FileExists(result) == false) { + result = FilePath::IncludeTrailingSeparator(RuntimePath) + + _T("bin\\jli.dll"); + } + + return result; +} + +ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) { + IniFile *result = new IniFile(); + if (result == NULL) { + return NULL; + } + + result->LoadFromFile(FileName); + + return result; +} + +TString WindowsPlatform::GetModuleFileName() { + TString result; + DynamicBuffer buffer(MAX_PATH); + if (buffer.GetData() == NULL) { + return result; + } + + ::GetModuleFileName(NULL, buffer.GetData(), + static_cast (buffer.GetSize())); + + while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { + if (!buffer.Resize(buffer.GetSize() * 2)) { + return result; + } + ::GetModuleFileName(NULL, buffer.GetData(), + static_cast (buffer.GetSize())); + } + + result = buffer.GetData(); + return result; +} + +Module WindowsPlatform::LoadLibrary(TString FileName) { + return ::LoadLibrary(FileName.data()); +} + +void WindowsPlatform::FreeLibrary(Module AModule) { + ::FreeLibrary((HMODULE) AModule); +} + +Procedure WindowsPlatform::GetProcAddress(Module AModule, + std::string MethodName) { + return ::GetProcAddress((HMODULE) AModule, MethodName.c_str()); +} + +bool WindowsPlatform::IsMainThread() { + bool result = (FMainThread == ::GetCurrentThreadId()); + return result; +} + +TString WindowsPlatform::GetTempDirectory() { + TString result; + PWSTR userDir = 0; + + if (SUCCEEDED(SHGetKnownFolderPath( + FOLDERID_Profile, + 0, + NULL, + &userDir))) { + result = userDir; + result += WINDOWS_JPACKAGE_TMP_DIR; + CoTaskMemFree(userDir); + } + + return result; +} + +static BOOL CALLBACK enumWindows(HWND winHandle, LPARAM lParam) { + DWORD pid = (DWORD) lParam, wPid = 0; + GetWindowThreadProcessId(winHandle, &wPid); + if (pid == wPid) { + SetForegroundWindow(winHandle); + return FALSE; + } + return TRUE; +} + +TPlatformNumber WindowsPlatform::GetMemorySize() { + SYSTEM_INFO si; + GetSystemInfo(&si); + size_t result = (size_t) si.lpMaximumApplicationAddress; + result = result / 1048576; // Convert from bytes to megabytes. + return result; +} + +std::vector FilterList(std::vector &Items, + std::wregex Pattern) { + std::vector result; + + for (std::vector::iterator it = Items.begin(); + it != Items.end(); ++it) { + TString item = *it; + std::wsmatch match; + + if (std::regex_search(item, match, Pattern)) { + result.push_back(item); + } + } + return result; +} + +Process* WindowsPlatform::CreateProcess() { + return new WindowsProcess(); +} + +void WindowsPlatform::InitStreamLocale(wios *stream) { + const std::locale empty_locale = std::locale::empty(); + const std::locale utf8_locale = + std::locale(empty_locale, new std::codecvt_utf8()); + stream->imbue(utf8_locale); +} + +void WindowsPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) { + if (pJavaLibrary == NULL) { + return; + } + + if (FilePath::FileExists(_T("msvcr100.dll")) == true) { + pJavaLibrary->AddDependency(_T("msvcr100.dll")); + } + + TString runtimeBin = GetPackageRuntimeBinDirectory(); + SetDllDirectory(runtimeBin.c_str()); +} + +void Platform::CopyString(char *Destination, + size_t NumberOfElements, const char *Source) { + strcpy_s(Destination, NumberOfElements, Source); + + if (NumberOfElements > 0) { + Destination[NumberOfElements - 1] = '\0'; + } +} + +void Platform::CopyString(wchar_t *Destination, + size_t NumberOfElements, const wchar_t *Source) { + wcscpy_s(Destination, NumberOfElements, Source); + + if (NumberOfElements > 0) { + Destination[NumberOfElements - 1] = '\0'; + } +} + +// Owner must free the return value. +MultibyteString Platform::WideStringToMultibyteString( + const wchar_t* value) { + MultibyteString result; + size_t count = 0; + + if (value == NULL) { + return result; + } + + count = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL); + + if (count > 0) { + result.data = new char[count + 1]; + result.length = WideCharToMultiByte(CP_UTF8, 0, value, -1, + result.data, (int)count, NULL, NULL); + } + + return result; +} + +// Owner must free the return value. +WideString Platform::MultibyteStringToWideString(const char* value) { + WideString result; + size_t count = 0; + + if (value == NULL) { + return result; + } + + mbstowcs_s(&count, NULL, 0, value, _TRUNCATE); + + if (count > 0) { + result.data = new wchar_t[count + 1]; + mbstowcs_s(&result.length, result.data, count, value, count); + } + + return result; +} + +FileHandle::FileHandle(std::wstring FileName) { + FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); +} + +FileHandle::~FileHandle() { + if (IsValid() == true) { + ::CloseHandle(FHandle); + } +} + +bool FileHandle::IsValid() { + return FHandle != INVALID_HANDLE_VALUE; +} + +HANDLE FileHandle::GetHandle() { + return FHandle; +} + +FileMappingHandle::FileMappingHandle(HANDLE FileHandle) { + FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL); +} + +bool FileMappingHandle::IsValid() { + return FHandle != NULL; +} + +FileMappingHandle::~FileMappingHandle() { + if (IsValid() == true) { + ::CloseHandle(FHandle); + } +} + +HANDLE FileMappingHandle::GetHandle() { + return FHandle; +} + +FileData::FileData(HANDLE Handle) { + FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0); +} + +FileData::~FileData() { + if (IsValid() == true) { + ::UnmapViewOfFile(FBaseAddress); + } +} + +bool FileData::IsValid() { + return FBaseAddress != NULL; +} + +LPVOID FileData::GetBaseAddress() { + return FBaseAddress; +} + +WindowsLibrary::WindowsLibrary(std::wstring FileName) { + FFileName = FileName; +} + +std::vector WindowsLibrary::GetImports() { + std::vector result; + FileHandle library(FFileName); + + if (library.IsValid() == true) { + FileMappingHandle mapping(library.GetHandle()); + + if (mapping.IsValid() == true) { + FileData fileData(mapping.GetHandle()); + + if (fileData.IsValid() == true) { + PIMAGE_DOS_HEADER dosHeader = + (PIMAGE_DOS_HEADER) fileData.GetBaseAddress(); + PIMAGE_FILE_HEADER pImgFileHdr = + (PIMAGE_FILE_HEADER) fileData.GetBaseAddress(); + if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { + result = DumpPEFile(dosHeader); + } + } + } + } + + return result; +} + +// Given an RVA, look up the section header that encloses it and return a +// pointer to its IMAGE_SECTION_HEADER + +PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva, + PIMAGE_NT_HEADERS pNTHeader) { + PIMAGE_SECTION_HEADER result = 0; + PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader); + + for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections; + index++, section++) { + // Is the RVA is within this section? + if ((rva >= section->VirtualAddress) && + (rva < (section->VirtualAddress + section->Misc.VirtualSize))) { + result = section; + } + } + + return result; +} + +LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader, + DWORD imageBase) { + LPVOID result = 0; + PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva, + pNTHeader); + + if (pSectionHdr != NULL) { + INT delta = (INT) ( + pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData); + DWORD_PTR dwp = (DWORD_PTR) (imageBase + rva - delta); + result = reinterpret_cast (dwp); // VS2017 - FIXME + } + + return result; +} + +std::vector WindowsLibrary::GetImportsSection(DWORD base, + PIMAGE_NT_HEADERS pNTHeader) { + std::vector result; + + // Look up where the imports section is located. Normally in + // the .idata section, + // but not necessarily so. Therefore, grab the RVA from the data dir. + DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[ + IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; + + if (importsStartRVA != NULL) { + // Get the IMAGE_SECTION_HEADER that contains the imports. This is + // usually the .idata section, but doesn't have to be. + PIMAGE_SECTION_HEADER pSection = + GetEnclosingSectionHeader(importsStartRVA, pNTHeader); + + if (pSection != NULL) { + PIMAGE_IMPORT_DESCRIPTOR importDesc = + (PIMAGE_IMPORT_DESCRIPTOR) GetPtrFromRVA( + importsStartRVA, pNTHeader, base); + + if (importDesc != NULL) { + while (true) { + // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR + if ((importDesc->TimeDateStamp == 0) && + (importDesc->Name == 0)) { + break; + } + + std::string filename = (char*) GetPtrFromRVA( + importDesc->Name, pNTHeader, base); + result.push_back(PlatformString(filename)); + importDesc++; // advance to next IMAGE_IMPORT_DESCRIPTOR + } + } + } + } + + return result; +} + +std::vector WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) { + std::vector result; + // all of this is VS2017 - FIXME + DWORD_PTR dwDosHeaders = reinterpret_cast (dosHeader); + DWORD_PTR dwPIHeaders = dwDosHeaders + (DWORD) (dosHeader->e_lfanew); + + PIMAGE_NT_HEADERS pNTHeader = + reinterpret_cast (dwPIHeaders); + + // Verify that the e_lfanew field gave us a reasonable + // pointer and the PE signature. + // TODO: To really fix JDK-8131321 this condition needs to be changed. + // There is a matching change + // in JavaVirtualMachine.cpp that also needs to be changed. + if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) { + DWORD base = (DWORD) (dwDosHeaders); + result = GetImportsSection(base, pNTHeader); + } + + return result; +} + +#include + +WindowsJob::WindowsJob() { + FHandle = NULL; +} + +WindowsJob::~WindowsJob() { + if (FHandle != NULL) { + CloseHandle(FHandle); + } +} + +HANDLE WindowsJob::GetHandle() { + if (FHandle == NULL) { + FHandle = CreateJobObject(NULL, NULL); // GLOBAL + + if (FHandle == NULL) { + ::MessageBox(0, _T("Could not create job object"), + _T("TEST"), MB_OK); + } else { + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0}; + + // Configure all child processes associated with + // the job to terminate when the + jeli.BasicLimitInformation.LimitFlags = + JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + if (0 == SetInformationJobObject(FHandle, + JobObjectExtendedLimitInformation, &jeli, sizeof (jeli))) { + ::MessageBox(0, _T("Could not SetInformationJobObject"), + _T("TEST"), MB_OK); + } + } + } + + return FHandle; +} + +// Initialize static member of WindowsProcess +WindowsJob WindowsProcess::FJob; + +WindowsProcess::WindowsProcess() : Process() { + FRunning = false; +} + +WindowsProcess::~WindowsProcess() { + Terminate(); +} + +void WindowsProcess::Cleanup() { + CloseHandle(FProcessInfo.hProcess); + CloseHandle(FProcessInfo.hThread); +} + +bool WindowsProcess::IsRunning() { + bool result = false; + + HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); + if (handle == INVALID_HANDLE_VALUE) { + return false; + } + + PROCESSENTRY32 process = {0}; + process.dwSize = sizeof (process); + + if (::Process32First(handle, &process)) { + do { + if (process.th32ProcessID == FProcessInfo.dwProcessId) { + result = true; + break; + } + } while (::Process32Next(handle, &process)); + } + + CloseHandle(handle); + + return result; +} + +bool WindowsProcess::Terminate() { + bool result = false; + + if (IsRunning() == true && FRunning == true) { + FRunning = false; + } + + return result; +} + +bool WindowsProcess::Execute(const TString Application, + const std::vector Arguments, bool AWait) { + bool result = false; + + if (FRunning == false) { + FRunning = true; + + STARTUPINFO startupInfo; + ZeroMemory(&startupInfo, sizeof (startupInfo)); + startupInfo.cb = sizeof (startupInfo); + ZeroMemory(&FProcessInfo, sizeof (FProcessInfo)); + + TString command = Application; + + for (std::vector::const_iterator iterator = Arguments.begin(); + iterator != Arguments.end(); iterator++) { + command += TString(_T(" ")) + *iterator; + } + + if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL, + NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo) + == FALSE) { + TString message = PlatformString::Format( + _T("Error: Unable to create process %s"), + Application.data()); + throw Exception(message); + } else { + if (FJob.GetHandle() != NULL) { + if (::AssignProcessToJobObject(FJob.GetHandle(), + FProcessInfo.hProcess) == 0) { + // Failed to assign process to job. It doesn't prevent + // anything from continuing so continue. + } + } + + // Wait until child process exits. + if (AWait == true) { + Wait(); + // Close process and thread handles. + Cleanup(); + } + } + } + + return result; +} + +bool WindowsProcess::Wait() { + bool result = false; + + WaitForSingleObject(FProcessInfo.hProcess, INFINITE); + return result; +} + +TProcessID WindowsProcess::GetProcessID() { + return FProcessInfo.dwProcessId; +} + +bool WindowsProcess::ReadOutput() { + bool result = false; + // TODO implement + return result; +} + +void WindowsProcess::SetInput(TString Value) { + // TODO implement +} + +std::list WindowsProcess::GetOutput() { + ReadOutput(); + return Process::GetOutput(); +}