src/jdk.jpackage/share/native/libjpackage/WindowsPlatform.cpp
branchJDK-8200758-branch
changeset 57064 a7fdadf67a92
parent 57063 1fa5c73d3c5a
child 57065 2446962c555c
equal deleted inserted replaced
57063:1fa5c73d3c5a 57064:a7fdadf67a92
     1 /*
       
     2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #include "Platform.h"
       
    27 
       
    28 #ifdef WINDOWS
       
    29 
       
    30 #include "JavaVirtualMachine.h"
       
    31 #include "WindowsPlatform.h"
       
    32 #include "Package.h"
       
    33 #include "Helpers.h"
       
    34 #include "PlatformString.h"
       
    35 #include "Macros.h"
       
    36 
       
    37 #include <map>
       
    38 #include <vector>
       
    39 #include <regex>
       
    40 
       
    41 #define WINDOWS_JPACKAGE_TMP_DIR \
       
    42         L"\\AppData\\Local\\Java\\JPackage\\tmp"
       
    43 
       
    44 
       
    45 class Registry {
       
    46 private:
       
    47     HKEY FKey;
       
    48     HKEY FOpenKey;
       
    49     bool FOpen;
       
    50 
       
    51 public:
       
    52     Registry(HKEY Key) {
       
    53         FOpen = false;
       
    54         FKey = Key;
       
    55     }
       
    56 
       
    57     ~Registry() {
       
    58         Close();
       
    59     }
       
    60 
       
    61     void Close() {
       
    62         if (FOpen == true) {
       
    63             RegCloseKey(FOpenKey);
       
    64         }
       
    65     }
       
    66 
       
    67     bool Open(TString SubKey) {
       
    68         bool result = false;
       
    69         Close();
       
    70 
       
    71         if (RegOpenKeyEx(FKey, SubKey.data(), 0, KEY_READ, &FOpenKey) ==
       
    72                 ERROR_SUCCESS) {
       
    73             result = true;
       
    74         }
       
    75 
       
    76         return result;
       
    77     }
       
    78 
       
    79     std::list<TString> GetKeys() {
       
    80         std::list<TString> result;
       
    81         DWORD count;
       
    82 
       
    83         if (RegQueryInfoKey(FOpenKey, NULL, NULL, NULL, NULL, NULL, NULL,
       
    84                  &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
       
    85 
       
    86             DWORD length = 255;
       
    87             DynamicBuffer<TCHAR> buffer(length);
       
    88             if (buffer.GetData() == NULL) {
       
    89                 return result;
       
    90             }
       
    91 
       
    92             for (unsigned int index = 0; index < count; index++) {
       
    93                 buffer.Zero();
       
    94                 DWORD status = RegEnumValue(FOpenKey, index, buffer.GetData(),
       
    95                                             &length, NULL, NULL, NULL, NULL);
       
    96 
       
    97                 while (status == ERROR_MORE_DATA) {
       
    98                     length = length * 2;
       
    99                     if (!buffer.Resize(length)) {
       
   100                         return result;
       
   101                     }
       
   102                     status = RegEnumValue(FOpenKey, index, buffer.GetData(),
       
   103                                           &length, NULL, NULL, NULL, NULL);
       
   104                 }
       
   105 
       
   106                 if (status == ERROR_SUCCESS) {
       
   107                     TString value = buffer.GetData();
       
   108                     result.push_back(value);
       
   109                 }
       
   110             }
       
   111         }
       
   112 
       
   113         return result;
       
   114     }
       
   115 
       
   116     TString ReadString(TString Name) {
       
   117         TString result;
       
   118         DWORD length;
       
   119         DWORD dwRet;
       
   120         DynamicBuffer<wchar_t> buffer(0);
       
   121         length = 0;
       
   122 
       
   123         dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, NULL,
       
   124                 &length);
       
   125         if (dwRet == ERROR_MORE_DATA || dwRet == 0) {
       
   126             if (!buffer.Resize(length + 1)) {
       
   127                 return result;
       
   128             }
       
   129             dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL,
       
   130                     (LPBYTE)buffer.GetData(), &length);
       
   131             result = buffer.GetData();
       
   132         }
       
   133 
       
   134         return result;
       
   135     }
       
   136 };
       
   137 
       
   138 WindowsPlatform::WindowsPlatform(void) : Platform(), GenericPlatform() {
       
   139     FMainThread = ::GetCurrentThreadId();
       
   140 }
       
   141 
       
   142 WindowsPlatform::~WindowsPlatform(void) {
       
   143 }
       
   144 
       
   145 TCHAR* WindowsPlatform::ConvertStringToFileSystemString(TCHAR* Source,
       
   146         bool &release) {
       
   147     // Not Implemented.
       
   148     return NULL;
       
   149 }
       
   150 
       
   151 TCHAR* WindowsPlatform::ConvertFileSystemStringToString(TCHAR* Source,
       
   152         bool &release) {
       
   153     // Not Implemented.
       
   154     return NULL;
       
   155 }
       
   156 
       
   157 void WindowsPlatform::SetCurrentDirectory(TString Value) {
       
   158     _wchdir(Value.data());
       
   159 }
       
   160 
       
   161 TString WindowsPlatform::GetPackageRootDirectory() {
       
   162     TString filename = GetModuleFileName();
       
   163     return FilePath::ExtractFilePath(filename);
       
   164 }
       
   165 
       
   166 TString WindowsPlatform::GetAppDataDirectory() {
       
   167     TString result;
       
   168     TCHAR path[MAX_PATH];
       
   169 
       
   170     if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path) == S_OK) {
       
   171         result = path;
       
   172     }
       
   173 
       
   174     return result;
       
   175 }
       
   176 
       
   177 void WindowsPlatform::ShowMessage(TString title, TString description) {
       
   178     MessageBox(NULL, description.data(),
       
   179             !title.empty() ? title.data() : description.data(),
       
   180             MB_ICONERROR | MB_OK);
       
   181 }
       
   182 
       
   183 void WindowsPlatform::ShowMessage(TString description) {
       
   184     TString appname = GetModuleFileName();
       
   185     appname = FilePath::ExtractFileName(appname);
       
   186     MessageBox(NULL, description.data(), appname.data(), MB_ICONERROR | MB_OK);
       
   187 }
       
   188 
       
   189 MessageResponse WindowsPlatform::ShowResponseMessage(TString title,
       
   190         TString description) {
       
   191     MessageResponse result = mrCancel;
       
   192 
       
   193     if (::MessageBox(NULL, description.data(), title.data(), MB_OKCANCEL) ==
       
   194             IDOK) {
       
   195         result = mrOK;
       
   196     }
       
   197 
       
   198     return result;
       
   199 }
       
   200 
       
   201 TString WindowsPlatform::GetBundledJVMLibraryFileName(TString RuntimePath) {
       
   202     TString result = FilePath::IncludeTrailingSeparator(RuntimePath) +
       
   203         _T("jre\\bin\\jli.dll");
       
   204 
       
   205     if (FilePath::FileExists(result) == false) {
       
   206         result = FilePath::IncludeTrailingSeparator(RuntimePath) +
       
   207             _T("bin\\jli.dll");
       
   208     }
       
   209 
       
   210     return result;
       
   211 }
       
   212 
       
   213 ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) {
       
   214     IniFile *result = new IniFile();
       
   215     if (result == NULL) {
       
   216         return NULL;
       
   217     }
       
   218 
       
   219     if (result->LoadFromFile(FileName) == false) {
       
   220         // New property file format was not found,
       
   221         // attempt to load old property file format.
       
   222         Helpers::LoadOldConfigFile(FileName, result);
       
   223     }
       
   224 
       
   225     return result;
       
   226 }
       
   227 
       
   228 TString WindowsPlatform::GetModuleFileName() {
       
   229     TString result;
       
   230     DynamicBuffer<wchar_t> buffer(MAX_PATH);
       
   231     if (buffer.GetData() == NULL) {
       
   232         return result;
       
   233     }
       
   234 
       
   235     ::GetModuleFileName(NULL, buffer.GetData(),
       
   236             static_cast<DWORD>(buffer.GetSize()));
       
   237 
       
   238     while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
       
   239         if (!buffer.Resize(buffer.GetSize() * 2)) {
       
   240             return result;
       
   241         }
       
   242         ::GetModuleFileName(NULL, buffer.GetData(),
       
   243                 static_cast<DWORD>(buffer.GetSize()));
       
   244     }
       
   245 
       
   246     result = buffer.GetData();
       
   247     return result;
       
   248 }
       
   249 
       
   250 Module WindowsPlatform::LoadLibrary(TString FileName) {
       
   251     return ::LoadLibrary(FileName.data());
       
   252 }
       
   253 
       
   254 void WindowsPlatform::FreeLibrary(Module AModule) {
       
   255     ::FreeLibrary((HMODULE)AModule);
       
   256 }
       
   257 
       
   258 Procedure WindowsPlatform::GetProcAddress(Module AModule,
       
   259         std::string MethodName) {
       
   260     return ::GetProcAddress((HMODULE)AModule, MethodName.c_str());
       
   261 }
       
   262 
       
   263 bool WindowsPlatform::IsMainThread() {
       
   264     bool result = (FMainThread == ::GetCurrentThreadId());
       
   265     return result;
       
   266 }
       
   267 
       
   268 TString WindowsPlatform::GetTempDirectory() {
       
   269     TString result;
       
   270     PWSTR userDir = 0;
       
   271 
       
   272     if (SUCCEEDED(SHGetKnownFolderPath(
       
   273                     FOLDERID_Profile,
       
   274                     0,
       
   275                     NULL,
       
   276                     &userDir))) {
       
   277         result = userDir;
       
   278         result += WINDOWS_JPACKAGE_TMP_DIR;
       
   279         CoTaskMemFree(userDir);
       
   280     }
       
   281 
       
   282     return result;
       
   283 }
       
   284 
       
   285 static BOOL CALLBACK enumWindows(HWND winHandle, LPARAM lParam) {
       
   286     DWORD pid = (DWORD)lParam, wPid = 0;
       
   287     GetWindowThreadProcessId(winHandle, &wPid);
       
   288     if (pid == wPid)  {
       
   289         SetForegroundWindow(winHandle);
       
   290         return FALSE;
       
   291     }
       
   292     return TRUE;
       
   293 }
       
   294 
       
   295 void WindowsPlatform::reactivateAnotherInstance() {
       
   296     if (singleInstanceProcessId == 0) {
       
   297         printf("Unable to reactivate another instance, PID is undefined");
       
   298         return;
       
   299     }
       
   300     EnumWindows(&enumWindows, (LPARAM)singleInstanceProcessId);
       
   301 }
       
   302 
       
   303 // returns true if another instance is already running.
       
   304 // if false, we need to continue regular launch.
       
   305 bool WindowsPlatform::CheckForSingleInstance(TString name) {
       
   306     if (SingleInstance::getInstance(name)->IsAnotherInstanceRunning()) {
       
   307         // read PID
       
   308         DWORD pid = SingleInstance::getInstance(name)->readPid();
       
   309         if (pid != 0) {
       
   310             singleInstanceProcessId = pid;
       
   311             return true;
       
   312         }
       
   313     } else {
       
   314         // it is the first intance
       
   315         // write pid and continue regular launch
       
   316         SingleInstance::getInstance(name)->writePid(GetCurrentProcessId());
       
   317     }
       
   318     return false;
       
   319 }
       
   320 
       
   321 SingleInstance::SingleInstance(TString& name_): BUF_SIZE(256), _name(name_),
       
   322         _hMapFile(NULL), _pBuf(NULL) {
       
   323     _mutex = CreateMutex(NULL, TRUE, name_.data());
       
   324     _lastError = GetLastError();
       
   325     _sharedMemoryName = _T("Local\\jpackage-") + _name;
       
   326 }
       
   327 
       
   328 SingleInstance::~SingleInstance() {
       
   329     if (_pBuf != NULL) {
       
   330         UnmapViewOfFile(_pBuf);
       
   331         _pBuf = NULL;
       
   332     }
       
   333 
       
   334     if (_hMapFile != NULL) {
       
   335         CloseHandle(_hMapFile);
       
   336         _hMapFile = NULL;
       
   337     }
       
   338 
       
   339     if (_mutex != NULL) {
       
   340         CloseHandle(_mutex);
       
   341         _mutex = NULL;
       
   342     }
       
   343 }
       
   344 
       
   345 bool SingleInstance::writePid(DWORD pid) {
       
   346     _hMapFile = CreateFileMapping(
       
   347                  INVALID_HANDLE_VALUE,
       
   348                  NULL,
       
   349                  PAGE_READWRITE,
       
   350                  0,
       
   351                  BUF_SIZE,
       
   352                  _sharedMemoryName.data());
       
   353 
       
   354     if (_hMapFile == NULL) {
       
   355         return false;
       
   356     }
       
   357 
       
   358     _pBuf = (LPTSTR) MapViewOfFile(_hMapFile,
       
   359                         FILE_MAP_ALL_ACCESS,
       
   360                         0,
       
   361                         0,
       
   362                         BUF_SIZE);
       
   363 
       
   364     if (_pBuf == NULL) {
       
   365         CloseHandle(_hMapFile);
       
   366         _hMapFile = NULL;
       
   367         return false;
       
   368     }
       
   369 
       
   370     CopyMemory((PVOID)_pBuf, &pid, sizeof(DWORD));
       
   371 
       
   372     return true;
       
   373 }
       
   374 
       
   375 DWORD SingleInstance::readPid() {
       
   376     _hMapFile = OpenFileMapping(
       
   377                    FILE_MAP_ALL_ACCESS,
       
   378                    FALSE,
       
   379                    _sharedMemoryName.data());
       
   380 
       
   381     if (_hMapFile == NULL) {
       
   382         return 0;
       
   383     }
       
   384 
       
   385    _pBuf = (LPTSTR) MapViewOfFile(_hMapFile,
       
   386                FILE_MAP_ALL_ACCESS,
       
   387                0,
       
   388                0,
       
   389                BUF_SIZE);
       
   390 
       
   391     if (_pBuf == NULL) {
       
   392         CloseHandle(_hMapFile);
       
   393         _hMapFile = NULL;
       
   394         return 0;
       
   395     }
       
   396 
       
   397     DWORD pid = 0;
       
   398     CopyMemory(&pid, (PVOID)_pBuf,  sizeof(DWORD));
       
   399 
       
   400     return pid;
       
   401 }
       
   402 
       
   403 TPlatformNumber WindowsPlatform::GetMemorySize() {
       
   404     SYSTEM_INFO si;
       
   405     GetSystemInfo(&si);
       
   406     size_t result = (size_t)si.lpMaximumApplicationAddress;
       
   407     result = result / 1048576; // Convert from bytes to megabytes.
       
   408     return result;
       
   409 }
       
   410 
       
   411 std::vector<TString> WindowsPlatform::GetLibraryImports(
       
   412        const TString FileName) {
       
   413  std::vector<TString> result;
       
   414     WindowsLibrary library(FileName);
       
   415     result = library.GetImports();
       
   416  return result;
       
   417 }
       
   418 
       
   419 std::vector<TString> FilterList(std::vector<TString> &Items,
       
   420         std::wregex Pattern) {
       
   421     std::vector<TString> result;
       
   422 
       
   423     for (std::vector<TString>::iterator it = Items.begin();
       
   424             it != Items.end(); ++it) {
       
   425         TString item = *it;
       
   426         std::wsmatch match;
       
   427 
       
   428         if (std::regex_search(item, match, Pattern)) {
       
   429             result.push_back(item);
       
   430         }
       
   431     }
       
   432     return result;
       
   433 }
       
   434 
       
   435 std::vector<TString> WindowsPlatform::FilterOutRuntimeDependenciesForPlatform(
       
   436         std::vector<TString> Imports) {
       
   437     std::vector<TString> result;
       
   438     Package& package = Package::GetInstance();
       
   439     Macros& macros = Macros::GetInstance();
       
   440     TString runtimeDir = macros.ExpandMacros(package.GetJVMRuntimeDirectory());
       
   441     std::vector<TString> filelist = FilterList(Imports,
       
   442             std::wregex(_T("MSVCR.*.DLL"), std::regex_constants::icase));
       
   443 
       
   444     for (std::vector<TString>::iterator it = filelist.begin();
       
   445             it != filelist.end(); ++it) {
       
   446         TString filename = *it;
       
   447         TString msvcr100FileName = FilePath::IncludeTrailingSeparator(
       
   448                 runtimeDir) + _T("jre\\bin\\") + filename;
       
   449 
       
   450         if (FilePath::FileExists(msvcr100FileName) == true) {
       
   451             result.push_back(msvcr100FileName);
       
   452             break;
       
   453         }
       
   454         else {
       
   455             msvcr100FileName = FilePath::IncludeTrailingSeparator(runtimeDir)
       
   456                     + _T("bin\\") + filename;
       
   457 
       
   458             if (FilePath::FileExists(msvcr100FileName) == true) {
       
   459                 result.push_back(msvcr100FileName);
       
   460                 break;
       
   461             }
       
   462         }
       
   463     }
       
   464 
       
   465  return result;
       
   466 }
       
   467 
       
   468 Process* WindowsPlatform::CreateProcess() {
       
   469     return new WindowsProcess();
       
   470 }
       
   471 
       
   472 #ifdef DEBUG
       
   473 bool WindowsPlatform::IsNativeDebuggerPresent() {
       
   474     bool result = false;
       
   475 
       
   476     if (IsDebuggerPresent() == TRUE) {
       
   477         result = true;
       
   478     }
       
   479 
       
   480     return result;
       
   481 }
       
   482 
       
   483 int WindowsPlatform::GetProcessID() {
       
   484     int pid = GetProcessId(GetCurrentProcess());
       
   485     return pid;
       
   486 }
       
   487 #endif //DEBUG
       
   488 
       
   489 
       
   490 FileHandle::FileHandle(std::wstring FileName) {
       
   491     FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ,
       
   492             NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
       
   493 }
       
   494 
       
   495 FileHandle::~FileHandle() {
       
   496     if (IsValid() == true) {
       
   497         ::CloseHandle(FHandle);
       
   498     }
       
   499 }
       
   500 
       
   501 bool FileHandle::IsValid() {
       
   502     return FHandle != INVALID_HANDLE_VALUE;
       
   503 }
       
   504 
       
   505 HANDLE FileHandle::GetHandle() {
       
   506     return FHandle;
       
   507 }
       
   508 
       
   509 FileMappingHandle::FileMappingHandle(HANDLE FileHandle) {
       
   510     FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
       
   511 }
       
   512 
       
   513 bool FileMappingHandle::IsValid() {
       
   514     return FHandle != NULL;
       
   515 }
       
   516 
       
   517 FileMappingHandle::~FileMappingHandle() {
       
   518     if (IsValid() == true) {
       
   519         ::CloseHandle(FHandle);
       
   520     }
       
   521 }
       
   522 
       
   523 HANDLE FileMappingHandle::GetHandle() {
       
   524     return FHandle;
       
   525 }
       
   526 
       
   527 FileData::FileData(HANDLE Handle) {
       
   528     FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0);
       
   529 }
       
   530 
       
   531 FileData::~FileData() {
       
   532     if (IsValid() == true) {
       
   533         ::UnmapViewOfFile(FBaseAddress);
       
   534     }
       
   535 }
       
   536 
       
   537 bool FileData::IsValid() {
       
   538     return FBaseAddress != NULL;
       
   539 }
       
   540 
       
   541 LPVOID FileData::GetBaseAddress() {
       
   542     return FBaseAddress;
       
   543 }
       
   544 
       
   545 
       
   546 WindowsLibrary::WindowsLibrary(std::wstring FileName) {
       
   547     FFileName = FileName;
       
   548 }
       
   549 
       
   550 std::vector<TString> WindowsLibrary::GetImports() {
       
   551     std::vector<TString> result;
       
   552     FileHandle library(FFileName);
       
   553 
       
   554     if (library.IsValid() == true) {
       
   555         FileMappingHandle mapping(library.GetHandle());
       
   556 
       
   557         if (mapping.IsValid() == true) {
       
   558             FileData fileData(mapping.GetHandle());
       
   559 
       
   560             if (fileData.IsValid() == true) {
       
   561                 PIMAGE_DOS_HEADER dosHeader =
       
   562                         (PIMAGE_DOS_HEADER)fileData.GetBaseAddress();
       
   563                 PIMAGE_FILE_HEADER pImgFileHdr =
       
   564                         (PIMAGE_FILE_HEADER)fileData.GetBaseAddress();
       
   565                 if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
       
   566                     result = DumpPEFile(dosHeader);
       
   567                 }
       
   568             }
       
   569         }
       
   570     }
       
   571 
       
   572     return result;
       
   573 }
       
   574 
       
   575 // Given an RVA, look up the section header that encloses it and return a
       
   576 // pointer to its IMAGE_SECTION_HEADER
       
   577 PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva,
       
   578                                                 PIMAGE_NT_HEADERS pNTHeader) {
       
   579     PIMAGE_SECTION_HEADER result = 0;
       
   580     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
       
   581 
       
   582     for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections;
       
   583             index++, section++) {
       
   584         // Is the RVA is within this section?
       
   585         if ((rva >= section->VirtualAddress) &&
       
   586             (rva < (section->VirtualAddress + section->Misc.VirtualSize))) {
       
   587             result = section;
       
   588         }
       
   589     }
       
   590 
       
   591     return result;
       
   592 }
       
   593 
       
   594 LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader,
       
   595         DWORD imageBase) {
       
   596     LPVOID result = 0;
       
   597     PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva,
       
   598             pNTHeader);
       
   599 
       
   600     if (pSectionHdr != NULL) {
       
   601         INT delta = (INT)(
       
   602                 pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
       
   603         DWORD_PTR dwp = (DWORD_PTR) (imageBase + rva - delta);
       
   604         result = reinterpret_cast<LPVOID>(dwp); // VS2017 - FIXME
       
   605     }
       
   606 
       
   607     return result;
       
   608 }
       
   609 
       
   610 std::vector<TString> WindowsLibrary::GetImportsSection(DWORD base,
       
   611         PIMAGE_NT_HEADERS pNTHeader) {
       
   612     std::vector<TString> result;
       
   613 
       
   614     // Look up where the imports section is located. Normally in
       
   615     // the .idata section,
       
   616     // but not necessarily so. Therefore, grab the RVA from the data dir.
       
   617     DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[
       
   618             IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
       
   619 
       
   620     if (importsStartRVA != NULL) {
       
   621         // Get the IMAGE_SECTION_HEADER that contains the imports. This is
       
   622         // usually the .idata section, but doesn't have to be.
       
   623         PIMAGE_SECTION_HEADER pSection =
       
   624                 GetEnclosingSectionHeader(importsStartRVA, pNTHeader);
       
   625 
       
   626         if (pSection != NULL) {
       
   627             PIMAGE_IMPORT_DESCRIPTOR importDesc =
       
   628                     (PIMAGE_IMPORT_DESCRIPTOR)GetPtrFromRVA(
       
   629                     importsStartRVA, pNTHeader,base);
       
   630 
       
   631             if (importDesc != NULL) {
       
   632                 while (true)
       
   633                 {
       
   634                     // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
       
   635                     if ((importDesc->TimeDateStamp == 0) &&
       
   636                             (importDesc->Name == 0)) {
       
   637                         break;
       
   638                     }
       
   639 
       
   640                     std::string filename = (char*)GetPtrFromRVA(
       
   641                             importDesc->Name, pNTHeader, base);
       
   642                     result.push_back(PlatformString(filename));
       
   643                     importDesc++;   // advance to next IMAGE_IMPORT_DESCRIPTOR
       
   644                 }
       
   645             }
       
   646         }
       
   647     }
       
   648 
       
   649     return result;
       
   650 }
       
   651 
       
   652 std::vector<TString> WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) {
       
   653     std::vector<TString> result;
       
   654     // all of this is VS2017 - FIXME
       
   655     DWORD_PTR dwDosHeaders = reinterpret_cast<DWORD_PTR>(dosHeader);
       
   656     DWORD_PTR dwPIHeaders = dwDosHeaders + (DWORD)(dosHeader->e_lfanew);
       
   657 
       
   658     PIMAGE_NT_HEADERS pNTHeader =
       
   659                       reinterpret_cast<PIMAGE_NT_HEADERS>(dwPIHeaders);
       
   660 
       
   661     // Verify that the e_lfanew field gave us a reasonable
       
   662     // pointer and the PE signature.
       
   663     // TODO: To really fix JDK-8131321 this condition needs to be changed.
       
   664     // There is a matching change
       
   665     // in JavaVirtualMachine.cpp that also needs to be changed.
       
   666     if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) {
       
   667         DWORD base = (DWORD)(dwDosHeaders);
       
   668         result = GetImportsSection(base, pNTHeader);
       
   669     }
       
   670 
       
   671     return result;
       
   672 }
       
   673 
       
   674 #include <TlHelp32.h>
       
   675 
       
   676 WindowsJob::WindowsJob() {
       
   677     FHandle = NULL;
       
   678 }
       
   679 
       
   680 WindowsJob::~WindowsJob() {
       
   681     if (FHandle != NULL) {
       
   682         CloseHandle(FHandle);
       
   683     }
       
   684 }
       
   685 
       
   686 HANDLE WindowsJob::GetHandle() {
       
   687     if (FHandle == NULL) {
       
   688         FHandle = CreateJobObject(NULL, NULL); // GLOBAL
       
   689 
       
   690         if (FHandle == NULL)
       
   691         {
       
   692             ::MessageBox( 0, _T("Could not create job object"),
       
   693                     _T("TEST"), MB_OK);
       
   694         }
       
   695         else
       
   696         {
       
   697             JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
       
   698 
       
   699             // Configure all child processes associated with
       
   700             // the job to terminate when the
       
   701             jeli.BasicLimitInformation.LimitFlags =
       
   702                     JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
       
   703             if (0 == SetInformationJobObject(FHandle,
       
   704                     JobObjectExtendedLimitInformation, &jeli, sizeof(jeli))) {
       
   705                 ::MessageBox( 0, _T("Could not SetInformationJobObject"),
       
   706                         _T("TEST"), MB_OK);
       
   707             }
       
   708         }
       
   709     }
       
   710 
       
   711     return FHandle;
       
   712 }
       
   713 
       
   714 // Initialize static member of WindowsProcess
       
   715 WindowsJob WindowsProcess::FJob;
       
   716 
       
   717 WindowsProcess::WindowsProcess() : Process() {
       
   718     FRunning = false;
       
   719 }
       
   720 
       
   721 WindowsProcess::~WindowsProcess() {
       
   722     Terminate();
       
   723 }
       
   724 
       
   725 void WindowsProcess::Cleanup() {
       
   726     CloseHandle(FProcessInfo.hProcess);
       
   727     CloseHandle(FProcessInfo.hThread);
       
   728 }
       
   729 
       
   730 bool WindowsProcess::IsRunning() {
       
   731     bool result = false;
       
   732 
       
   733     HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
       
   734     if (handle == INVALID_HANDLE_VALUE) {
       
   735         return false;
       
   736     }
       
   737 
       
   738     PROCESSENTRY32 process = { 0 };
       
   739     process.dwSize = sizeof(process);
       
   740 
       
   741     if (::Process32First(handle, &process)) {
       
   742         do {
       
   743             if (process.th32ProcessID == FProcessInfo.dwProcessId) {
       
   744                 result = true;
       
   745                 break;
       
   746             }
       
   747         }
       
   748         while (::Process32Next(handle, &process));
       
   749     }
       
   750 
       
   751     CloseHandle(handle);
       
   752 
       
   753     return result;
       
   754 }
       
   755 
       
   756 bool WindowsProcess::Terminate() {
       
   757     bool result = false;
       
   758 
       
   759     if (IsRunning() == true && FRunning == true) {
       
   760         FRunning = false;
       
   761     }
       
   762 
       
   763     return result;
       
   764 }
       
   765 
       
   766 bool WindowsProcess::Execute(const TString Application,
       
   767         const std::vector<TString> Arguments, bool AWait) {
       
   768     bool result = false;
       
   769 
       
   770     if (FRunning == false) {
       
   771         FRunning = true;
       
   772 
       
   773         STARTUPINFO startupInfo;
       
   774         ZeroMemory(&startupInfo, sizeof(startupInfo));
       
   775         startupInfo.cb = sizeof(startupInfo);
       
   776         ZeroMemory(&FProcessInfo, sizeof(FProcessInfo));
       
   777 
       
   778         TString command = Application;
       
   779 
       
   780         for (std::vector<TString>::const_iterator iterator = Arguments.begin();
       
   781                 iterator != Arguments.end(); iterator++) {
       
   782             command += TString(_T(" ")) + *iterator;
       
   783         }
       
   784 
       
   785         if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL,
       
   786             NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo) == FALSE) {
       
   787             TString message = PlatformString::Format(
       
   788                     _T("Error: Unable to create process %s"),
       
   789                      Application.data());
       
   790             throw Exception(message);
       
   791         }
       
   792         else {
       
   793             if (FJob.GetHandle() != NULL) {
       
   794                 if (::AssignProcessToJobObject(FJob.GetHandle(),
       
   795                          FProcessInfo.hProcess) == 0) {
       
   796                     // Failed to assign process to job. It doesn't prevent
       
   797                     // anything from continuing so continue.
       
   798                 }
       
   799             }
       
   800 
       
   801             // Wait until child process exits.
       
   802             if (AWait == true) {
       
   803                 Wait();
       
   804                 // Close process and thread handles.
       
   805                 Cleanup();
       
   806             }
       
   807         }
       
   808     }
       
   809 
       
   810     return result;
       
   811 }
       
   812 
       
   813 bool WindowsProcess::Wait() {
       
   814     bool result = false;
       
   815 
       
   816     WaitForSingleObject(FProcessInfo.hProcess, INFINITE);
       
   817     return result;
       
   818 }
       
   819 
       
   820 TProcessID WindowsProcess::GetProcessID() {
       
   821     return FProcessInfo.dwProcessId;
       
   822 }
       
   823 
       
   824 bool WindowsProcess::ReadOutput() {
       
   825     bool result = false;
       
   826     // TODO implement
       
   827     return result;
       
   828 }
       
   829 
       
   830 void WindowsProcess::SetInput(TString Value) {
       
   831     // TODO implement
       
   832 }
       
   833 
       
   834 std::list<TString> WindowsProcess::GetOutput() {
       
   835     ReadOutput();
       
   836     return Process::GetOutput();
       
   837 }
       
   838 
       
   839 #endif // WINDOWS