1 /*
   2  * Copyright (c) 2014, 2015, Oracle and/or its affiliates.
   3  * All rights reserved. Use is subject to license terms.
   4  *
   5  * This file is available and licensed under the following license:
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  *
  11  *  - Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  *  - Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in
  15  *    the documentation and/or other materials provided with the distribution.
  16  *  - Neither the name of Oracle Corporation nor the names of its
  17  *    contributors may be used to endorse or promote products derived
  18  *    from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 
  33 
  34 #include "Platform.h"
  35 
  36 #ifdef WINDOWS
  37 
  38 #include "JavaVirtualMachine.h"
  39 #include "WindowsPlatform.h"
  40 #include "Package.h"
  41 #include "Helpers.h"
  42 #include "PlatformString.h"
  43 #include "Macros.h"
  44 
  45 #include <map>
  46 #include <vector>
  47 #include <regex>
  48 
  49 
  50 //--------------------------------------------------------------------------------------------------
  51 
  52 class Registry {
  53 private:
  54     HKEY FKey;
  55     HKEY FOpenKey;
  56     bool FOpen;
  57 
  58 public:
  59     Registry(HKEY Key) {
  60         FOpen = false;
  61         FKey = Key;
  62     }
  63 
  64     ~Registry() {
  65         Close();
  66     }
  67 
  68     void Close() {
  69         if (FOpen == true) {
  70             RegCloseKey(FOpenKey);
  71         }
  72     }
  73 
  74     bool Open(TString SubKey) {
  75         bool result = false;
  76         Close();
  77 
  78         if (RegOpenKeyEx(FKey, SubKey.data(), 0, KEY_READ, &FOpenKey) == ERROR_SUCCESS) {
  79             result = true;
  80         }
  81 
  82         return result;
  83     }
  84 
  85     std::list<TString> GetKeys() {
  86         std::list<TString> result;
  87         DWORD count;
  88 
  89         if (RegQueryInfoKey(FOpenKey, NULL, NULL, NULL, NULL, NULL, NULL,
  90                             &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
  91 
  92             DWORD length = 255;
  93             DynamicBuffer<TCHAR> buffer(length);
  94 
  95             for (unsigned int index = 0; index < count; index++) {
  96                 buffer.Zero();
  97                 DWORD status = RegEnumValue(FOpenKey, index, buffer.GetData(),
  98                                             &length, NULL, NULL, NULL, NULL);
  99 
 100                 while (status == ERROR_MORE_DATA) {
 101                     length = length * 2;
 102                     buffer.Resize(length);
 103                     status = RegEnumValue(FOpenKey, index, buffer.GetData(),
 104                                           &length, NULL, NULL, NULL, NULL);
 105                 }
 106 
 107                 if (status == ERROR_SUCCESS) {
 108                     TString value = buffer.GetData();
 109                     result.push_back(value);
 110                 }
 111             }
 112         }
 113 
 114         return result;
 115     }
 116 
 117     TString ReadString(TString Name) {
 118         TString result;
 119         DWORD length;
 120         DWORD dwRet;
 121         DynamicBuffer<wchar_t> buffer(0);
 122         length = 0;
 123 
 124         dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, NULL, &length);
 125         if (dwRet == ERROR_MORE_DATA || dwRet == 0) {
 126             buffer.Resize(length + 1);
 127             dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, (LPBYTE)buffer.GetData(), &length);
 128             result = buffer.GetData();
 129         }
 130 
 131         return result;
 132     }
 133 };
 134 
 135 //--------------------------------------------------------------------------------------------------
 136 
 137 WindowsPlatform::WindowsPlatform(void) : Platform(), GenericPlatform() {
 138     FMainThread = ::GetCurrentThreadId();
 139 }
 140 
 141 WindowsPlatform::~WindowsPlatform(void) {
 142 }
 143 
 144 TCHAR* WindowsPlatform::ConvertStringToFileSystemString(TCHAR* Source, bool &release) {
 145     // Not Implemented.
 146     return NULL;
 147 }
 148 
 149 TCHAR* WindowsPlatform::ConvertFileSystemStringToString(TCHAR* Source, bool &release) {
 150     // Not Implemented.
 151     return NULL;
 152 }
 153 
 154 void WindowsPlatform::SetCurrentDirectory(TString Value) {
 155     _wchdir(Value.data());
 156 }
 157 
 158 TString WindowsPlatform::GetPackageRootDirectory() {
 159     TString filename = GetModuleFileName();
 160     return FilePath::ExtractFilePath(filename);
 161 }
 162 
 163 TString WindowsPlatform::GetAppDataDirectory() {
 164     TString result;
 165     TCHAR path[MAX_PATH];
 166 
 167     if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path) == S_OK) {
 168         result = path;
 169     }
 170 
 171     return result;
 172 }
 173 
 174 #define BUFFER_SIZE 256
 175 
 176 // try to find current Java Home from registry
 177 //
 178 // HKLM\Software\JavaSoft\Java Runtime Environment\CurrentVersion
 179 // HKLM\Software\JavaSoft\Java Runtime Environment\[CurrentVersion]\JavaHome
 180 //
 181 // note that this has been changed in JDK9 to
 182 //
 183 // HKLM\Software\JavaSoft\JRE\CurrentVersion
 184 // HKLM\Software\JavaSoft\JRE\[CurrentVersion]\JavaHome
 185 //
 186 // return non-empty string as path if found
 187 // return empty string otherwise
 188 
 189 TString GetSystemJREForSubkey(TString javaRuntimeSubkey) {
 190     Registry registry(HKEY_LOCAL_MACHINE);
 191     TString result;
 192 
 193     if (registry.Open(javaRuntimeSubkey)) {
 194         TString version = registry.ReadString(_T("CurrentVersion"));
 195 
 196         if (!version.empty()) {
 197             if (registry.Open(javaRuntimeSubkey + TString(_T("\\")) + TString(version))) {
 198                 TString javaHome = registry.ReadString(_T("JavaHome"));
 199 
 200                 if (FilePath::DirectoryExists(javaHome)) {
 201                     result = javaHome;
 202                 }
 203             }
 204         }
 205     }
 206 
 207     return result;
 208 }
 209 
 210 TString WindowsPlatform::GetSystemJRE() {
 211     if (GetAppCDSState() != cdsDisabled) {
 212         //TODO throw exception
 213         return _T("");
 214     }
 215 
 216     TString result;
 217     result = GetSystemJREForSubkey(_T("SOFTWARE\\JavaSoft\\JRE"));
 218     if (!result.empty()) {
 219         return result;
 220     }
 221 
 222     result = GetSystemJREForSubkey(_T("SOFTWARE\\JavaSoft\\Java Runtime Environment"));
 223     if (!result.empty()) {
 224         return result;
 225     }
 226 
 227     return result;
 228 }
 229 
 230 void WindowsPlatform::ShowMessage(TString title, TString description) {
 231     MessageBox(NULL, description.data(), !title.empty() ? title.data() : description.data(), MB_ICONERROR | MB_OK);
 232 }
 233 
 234 void WindowsPlatform::ShowMessage(TString description) {
 235     TString appname = GetModuleFileName();
 236     appname = FilePath::ExtractFileName(appname);
 237     MessageBox(NULL, description.data(), appname.data(), MB_ICONERROR | MB_OK);
 238 }
 239 
 240 MessageResponse WindowsPlatform::ShowResponseMessage(TString title, TString description) {
 241     MessageResponse result = mrCancel;
 242 
 243     if (::MessageBox(NULL, description.data(), title.data(), MB_OKCANCEL) == IDOK) {
 244         result = mrOK;
 245     }
 246 
 247     return result;
 248 }
 249 
 250 //MessageResponse WindowsPlatform::ShowResponseMessage(TString description) {
 251 //    TString appname = GetModuleFileName();
 252 //    appname = FilePath::ExtractFileName(appname);
 253 //    return ShowResponseMessage(appname, description);
 254 //}
 255 
 256 TString WindowsPlatform::GetBundledJVMLibraryFileName(TString RuntimePath) {
 257 #ifdef USE_JLI_LAUNCH
 258     TString result = FilePath::IncludeTrailingSeparater(RuntimePath) +
 259         _T("jre\\bin\\jli.dll");
 260 
 261     if (FilePath::FileExists(result) == false) {
 262         result = FilePath::IncludeTrailingSeparater(RuntimePath) +
 263             _T("bin\\jli.dll");
 264     }
 265 #else
 266     TString result = FilePath::IncludeTrailingSeparater(RuntimePath) +
 267         _T("jre\\bin\\client\\jvm.dll");
 268 
 269     if (FilePath::FileExists(result) == false) {
 270         result = FilePath::IncludeTrailingSeparater(RuntimePath) +
 271             _T("jre\\bin\\server\\jvm.dll");
 272     }
 273 
 274     if (FilePath::FileExists(result) == false) {
 275         result = FilePath::IncludeTrailingSeparater(RuntimePath) +
 276             _T("bin\\client\\jvm.dll");
 277     }
 278 
 279     if (FilePath::FileExists(result) == false) {
 280         result = FilePath::IncludeTrailingSeparater(RuntimePath) +
 281             _T("bin\\server\\jvm.dll");
 282     }
 283 #endif
 284 
 285     return result;
 286 }
 287 
 288 TString WindowsPlatform::GetSystemJVMLibraryFileName() {
 289     TString result;
 290     TString jvmPath = GetSystemJRE();
 291 
 292     if (jvmPath.empty() == false) {
 293         result = GetBundledJVMLibraryFileName(jvmPath);
 294     }
 295 
 296     return result;
 297 }
 298 
 299 ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) {
 300     IniFile *result = new IniFile();
 301 
 302     if (result->LoadFromFile(FileName) == false) {
 303         // New property file format was not found, attempt to load old property file format.
 304         Helpers::LoadOldConfigFile(FileName, result);
 305     }
 306 
 307     return result;
 308 }
 309 
 310 TString WindowsPlatform::GetModuleFileName() {
 311     TString result;
 312     DynamicBuffer<wchar_t> buffer(MAX_PATH);
 313     ::GetModuleFileName(NULL, buffer.GetData(), buffer.GetSize());
 314 
 315     while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
 316         buffer.Resize(buffer.GetSize() * 2);
 317         ::GetModuleFileName(NULL, buffer.GetData(), buffer.GetSize());
 318     }
 319 
 320     result = buffer.GetData();
 321     return result;
 322 }
 323 
 324 Module WindowsPlatform::LoadLibrary(TString FileName) {
 325     return ::LoadLibrary(FileName.data());
 326 }
 327 
 328 void WindowsPlatform::FreeLibrary(Module AModule) {
 329     ::FreeLibrary((HMODULE)AModule);
 330 }
 331 
 332 Procedure WindowsPlatform::GetProcAddress(Module AModule, std::string MethodName) {
 333     return ::GetProcAddress((HMODULE)AModule, MethodName.c_str());
 334 }
 335 
 336 bool WindowsPlatform::IsMainThread() {
 337     bool result = (FMainThread == ::GetCurrentThreadId());
 338     return result;
 339 }
 340 
 341 TPlatformNumber WindowsPlatform::GetMemorySize() {
 342     SYSTEM_INFO si;
 343     GetSystemInfo(&si);
 344     size_t result = (size_t)si.lpMaximumApplicationAddress;
 345     result = result / 1048576; // Convert from bytes to megabytes.
 346     return result;
 347 }
 348 
 349 std::vector<TString> WindowsPlatform::GetLibraryImports(const TString FileName) {
 350  std::vector<TString> result;
 351     WindowsLibrary library(FileName);
 352     result = library.GetImports();
 353  return result;
 354 }
 355 
 356 std::vector<TString> FilterList(std::vector<TString> &Items, std::wregex Pattern) {
 357     std::vector<TString> result;
 358 
 359     for (std::vector<TString>::iterator it = Items.begin(); it != Items.end(); ++it) {
 360         TString item = *it;
 361         std::wsmatch match;
 362 
 363         if (std::regex_search(item, match, Pattern)) {
 364             result.push_back(item);
 365         }
 366     }
 367     return result;
 368 }
 369 
 370 std::vector<TString> WindowsPlatform::FilterOutRuntimeDependenciesForPlatform(std::vector<TString> Imports) {
 371  std::vector<TString> result;
 372 
 373     Package& package = Package::GetInstance();
 374     Macros& macros = Macros::GetInstance();
 375     TString runtimeDir = macros.ExpandMacros(package.GetJVMRuntimeDirectory());
 376     std::vector<TString> filelist = FilterList(Imports, std::wregex(_T("MSVCR.*.DLL"), std::regex_constants::icase));
 377 
 378     for (std::vector<TString>::iterator it = filelist.begin(); it != filelist.end(); ++it) {
 379         TString filename = *it;
 380         TString msvcr100FileName = FilePath::IncludeTrailingSeparater(runtimeDir) + _T("jre\\bin\\") + filename;
 381 
 382         if (FilePath::FileExists(msvcr100FileName) == true) {
 383             result.push_back(msvcr100FileName);
 384             break;
 385         }
 386         else {
 387             msvcr100FileName = FilePath::IncludeTrailingSeparater(runtimeDir) + _T("bin\\") + filename;
 388 
 389             if (FilePath::FileExists(msvcr100FileName) == true) {
 390                 result.push_back(msvcr100FileName);
 391                 break;
 392             }
 393         }
 394     }
 395 
 396  return result;
 397 }
 398 
 399 Process* WindowsPlatform::CreateProcess() {
 400     return new WindowsProcess();
 401 }
 402 
 403 #ifdef DEBUG
 404 bool WindowsPlatform::IsNativeDebuggerPresent() {
 405     bool result = false;
 406 
 407     if (IsDebuggerPresent() == TRUE) {
 408         result = true;
 409     }
 410 
 411     return result;
 412 }
 413 
 414 int WindowsPlatform::GetProcessID() {
 415     int pid = GetProcessId(GetCurrentProcess());
 416     return pid;
 417 }
 418 #endif //DEBUG
 419 
 420 //--------------------------------------------------------------------------------------------------
 421 
 422 WindowsJavaUserPreferences::WindowsJavaUserPreferences(void) : JavaUserPreferences() {
 423 }
 424 
 425 WindowsJavaUserPreferences::~WindowsJavaUserPreferences(void) {
 426 }
 427 
 428 // Java Preferences API encodes it's strings, so we need to match what Java does to work with Java.
 429 // CAVEAT: Java also does unicode encoding which this doesn't do yet. Should be sufficient for jvm args.
 430 // See WindowsPreferences.java toWindowsName()
 431 TString ConvertStringToJavaEcodedString(TString Value) {
 432     TString result;
 433     TCHAR* p = (TCHAR*)Value.c_str();
 434     TCHAR c = *p;
 435 
 436     while (c != 0) {
 437         switch (c) {
 438             case '\\':
 439                 result += _T("//");
 440                 break;
 441 
 442             case '/':
 443                 result += '\\';
 444                 break;
 445             default:
 446                 if ((c >= 'A') && (c <= 'Z')) {
 447                     result += '/';
 448                     result += c;
 449                 }
 450                 else
 451                     result += c;
 452                 break;
 453         }
 454 
 455         p++;
 456         c = *p;
 457     }
 458 
 459     return result;
 460 }
 461 
 462 // Java Preferences API encodes it's strings, so we need to match what Java does to work with Java.
 463 // CAVEAT: Java also does unicode encoding which this doesn't do yet. Should be sufficient for jvm args.
 464 // See WindowsPreferences.java toJavaName()
 465 TString ConvertJavaEcodedStringToString(TString Value) {
 466     TString result;
 467 
 468     for (size_t index = 0; index < Value.length(); index++) {
 469         TCHAR c = Value[index];
 470 
 471         switch (c) {
 472             case '/':
 473                 if ((index + 1) < Value.length()) {
 474                     index++;
 475                     TCHAR nextc = Value[index];
 476 
 477                     if (nextc >= 'A' && nextc <= 'Z') {
 478                         result += nextc;
 479                     }
 480                     else if (nextc == '/') {
 481                         result += '\\';
 482                     }
 483                 }
 484                 break;
 485             case '\\':
 486                 result += '/';
 487                 break;
 488             default:
 489                 result += c;
 490                 break;
 491         }
 492     }
 493 
 494     return result;
 495 }
 496 
 497 bool WindowsJavaUserPreferences::Load(TString Appid) {
 498     bool result = false;
 499     TString lappid = Helpers::ConvertIdToFilePath(Appid);
 500     lappid = ConvertStringToJavaEcodedString(Appid);
 501     TString registryKey = TString(_T("SOFTWARE\\JavaSoft\\Prefs\\")) + lappid + TString(_T("\\/J/V/M/User/Options"));
 502     Registry registry(HKEY_CURRENT_USER);
 503 
 504     if (registry.Open(registryKey) == true) {
 505         std::list<TString> keys = registry.GetKeys();
 506         OrderedMap<TString, TString> mapOfKeysAndValues;
 507 
 508         for (std::list<TString>::const_iterator iterator = keys.begin(); iterator != keys.end(); iterator++) {
 509             TString key = *iterator;
 510             TString value = registry.ReadString(key);
 511             key = ConvertJavaEcodedStringToString(key);
 512             value = ConvertJavaEcodedStringToString(value);
 513 
 514             if (key.empty() == false) {
 515                 mapOfKeysAndValues.Append(key, value);
 516                 result = true;
 517             }
 518         }
 519 
 520         FMap = mapOfKeysAndValues;
 521     }
 522 
 523     return result;
 524 }
 525 
 526 //--------------------------------------------------------------------------------------------------
 527 
 528 FileHandle::FileHandle(std::wstring FileName) {
 529     FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ, NULL,
 530                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
 531 }
 532 
 533 FileHandle::~FileHandle() {
 534     if (IsValid() == true) {
 535         ::CloseHandle(FHandle);
 536     }
 537 }
 538 
 539 bool FileHandle::IsValid() {
 540     return FHandle != INVALID_HANDLE_VALUE;
 541 }
 542 
 543 HANDLE FileHandle::GetHandle() {
 544     return FHandle;
 545 }
 546 
 547 FileMappingHandle::FileMappingHandle(HANDLE FileHandle) {
 548     FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
 549 }
 550 
 551 bool FileMappingHandle::IsValid() {
 552     return FHandle != NULL;
 553 }
 554 
 555 FileMappingHandle::~FileMappingHandle() {
 556     if (IsValid() == true) {
 557         ::CloseHandle(FHandle);
 558     }
 559 }
 560 
 561 HANDLE FileMappingHandle::GetHandle() {
 562     return FHandle;
 563 }
 564 
 565 FileData::FileData(HANDLE Handle) {
 566     FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0);
 567 }
 568 
 569 FileData::~FileData() {
 570     if (IsValid() == true) {
 571         ::UnmapViewOfFile(FBaseAddress);
 572     }
 573 }
 574 
 575 bool FileData::IsValid() {
 576     return FBaseAddress != NULL;
 577 }
 578 
 579 LPVOID FileData::GetBaseAddress() {
 580     return FBaseAddress;
 581 }
 582 
 583 
 584 WindowsLibrary::WindowsLibrary(std::wstring FileName) {
 585     FFileName = FileName;
 586 }
 587 
 588 std::vector<TString> WindowsLibrary::GetImports() {
 589     std::vector<TString> result;
 590     FileHandle library(FFileName);
 591 
 592     if (library.IsValid() == true) {
 593         FileMappingHandle mapping(library.GetHandle());
 594 
 595         if (mapping.IsValid() == true) {
 596             FileData fileData(mapping.GetHandle());
 597 
 598             if (fileData.IsValid() == true) {
 599                 PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)fileData.GetBaseAddress();
 600                 PIMAGE_FILE_HEADER pImgFileHdr = (PIMAGE_FILE_HEADER)fileData.GetBaseAddress();
 601 
 602                 if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
 603                     result = DumpPEFile(dosHeader);
 604                 }
 605             }
 606         }
 607     }
 608 
 609     return result;
 610 }
 611 
 612 // Given an RVA, look up the section header that encloses it and return a
 613 // pointer to its IMAGE_SECTION_HEADER
 614 PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva,
 615                                                 PIMAGE_NT_HEADERS pNTHeader) {
 616     PIMAGE_SECTION_HEADER result = 0;
 617     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
 618 
 619     for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections; index++, section++) {
 620         // Is the RVA is within this section?
 621         if ((rva >= section->VirtualAddress) &&
 622             (rva < (section->VirtualAddress + section->Misc.VirtualSize))) {
 623             result = section;
 624         }
 625     }
 626 
 627     return result;
 628 }
 629 
 630 LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader, DWORD imageBase) {
 631     LPVOID result = 0;
 632     PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva, pNTHeader);
 633 
 634     if (pSectionHdr != NULL) {
 635         INT delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
 636         result = (PVOID)(imageBase + rva - delta);
 637     }
 638 
 639     return result;
 640 }
 641 
 642 std::vector<TString> WindowsLibrary::GetImportsSection(DWORD base, PIMAGE_NT_HEADERS pNTHeader) {
 643     std::vector<TString> result;
 644 
 645     // Look up where the imports section is located. Normally in the .idata section,
 646     // but not necessarily so. Therefore, grab the RVA from the data dir.
 647     DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
 648 
 649     if (importsStartRVA != NULL) {
 650         // Get the IMAGE_SECTION_HEADER that contains the imports. This is
 651         // usually the .idata section, but doesn't have to be.
 652         PIMAGE_SECTION_HEADER pSection = GetEnclosingSectionHeader(importsStartRVA, pNTHeader);
 653 
 654         if (pSection != NULL) {
 655             PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)GetPtrFromRVA(importsStartRVA, pNTHeader,base);
 656 
 657             if (importDesc != NULL) {
 658                 while (true)
 659                 {
 660                     // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
 661                     if ((importDesc->TimeDateStamp == 0) && (importDesc->Name == 0))
 662                         break;
 663 
 664                     std::string filename = (char*)GetPtrFromRVA(importDesc->Name, pNTHeader, base);
 665                     result.push_back(PlatformString(filename));
 666                     importDesc++;   // advance to next IMAGE_IMPORT_DESCRIPTOR
 667                 }
 668             }
 669         }
 670     }
 671 
 672     return result;
 673 }
 674 
 675 std::vector<TString> WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) {
 676     std::vector<TString> result;
 677     PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)(dosHeader) + (DWORD)(dosHeader->e_lfanew));
 678 
 679     // Verify that the e_lfanew field gave us a reasonable
 680     // pointer and the PE signature.
 681     // TODO: To really fix JDK-8131321 this condition needs to be changed. There is a matching change
 682     // in JavaVirtualMachine.cpp that also needs to be changed.
 683     if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) {
 684         DWORD base = (DWORD)dosHeader;
 685         result = GetImportsSection(base, pNTHeader);
 686     }
 687 
 688     return result;
 689 }
 690 
 691 //--------------------------------------------------------------------------------------------------
 692 
 693 #include <TlHelp32.h>
 694 
 695 WindowsJob::WindowsJob() {
 696     FHandle = NULL;
 697 }
 698 
 699 WindowsJob::~WindowsJob() {
 700     if (FHandle != NULL) {
 701         CloseHandle(FHandle);
 702     }
 703 }
 704 
 705 HANDLE WindowsJob::GetHandle() {
 706     if (FHandle == NULL) {
 707         FHandle = CreateJobObject(NULL, NULL); // GLOBAL
 708 
 709         if (FHandle == NULL)
 710         {
 711             ::MessageBox( 0, _T("Could not create job object"), _T("TEST"), MB_OK);
 712         }
 713         else
 714         {
 715             JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
 716 
 717             // Configure all child processes associated with the job to terminate when the
 718             jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
 719             if (0 == SetInformationJobObject(FHandle, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
 720             {
 721                 ::MessageBox( 0, _T("Could not SetInformationJobObject"), _T("TEST"), MB_OK);
 722             }
 723         }
 724     }
 725 
 726     return FHandle;
 727 }
 728 
 729 // Initialize static member of WindowsProcess
 730 WindowsJob WindowsProcess::FJob;
 731 
 732 WindowsProcess::WindowsProcess() : Process() {
 733     FRunning = false;
 734 }
 735 
 736 WindowsProcess::~WindowsProcess() {
 737     Terminate();
 738 }
 739 
 740 void WindowsProcess::Cleanup() {
 741     CloseHandle(FProcessInfo.hProcess);
 742     CloseHandle(FProcessInfo.hThread);
 743 }
 744 
 745 bool WindowsProcess::IsRunning() {
 746     bool result = false;
 747 
 748     HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
 749     PROCESSENTRY32 process = { 0 };
 750     process.dwSize = sizeof(process);
 751 
 752     if (::Process32First(handle, &process)) {
 753         do {
 754             if (process.th32ProcessID == FProcessInfo.dwProcessId) {
 755                 result = true;
 756                 break;
 757             }
 758         }
 759         while (::Process32Next(handle, &process));
 760     }
 761 
 762     CloseHandle(handle);
 763 
 764     return result;
 765 }
 766 
 767 bool WindowsProcess::Terminate() {
 768     bool result = false;
 769 
 770     if (IsRunning() == true && FRunning == true) {
 771         FRunning = false;
 772     }
 773 
 774     return result;
 775 }
 776 
 777 bool WindowsProcess::Execute(const TString Application, const std::vector<TString> Arguments, bool AWait) {
 778     bool result = false;
 779 
 780     if (FRunning == false) {
 781         FRunning = true;
 782 
 783         STARTUPINFO startupInfo;
 784         ZeroMemory(&startupInfo, sizeof(startupInfo));
 785         startupInfo.cb = sizeof(startupInfo);
 786         ZeroMemory(&FProcessInfo, sizeof(FProcessInfo));
 787 
 788         TString command = Application;
 789 
 790         for (std::vector<TString>::const_iterator iterator = Arguments.begin(); iterator != Arguments.end(); iterator++) {
 791             command += TString(_T(" ")) + *iterator;
 792         }
 793 
 794         if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL,
 795             NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo) == FALSE) {
 796             TString message = PlatformString::Format(_T("Error: Unable to create process %s"), Application.data());
 797             throw Exception(message);
 798         }
 799         else {
 800             if (FJob.GetHandle() != NULL) {
 801                 if (::AssignProcessToJobObject(FJob.GetHandle(), FProcessInfo.hProcess) == 0) {
 802                     // Failed to assign process to job. It doesn't prevent anything from continuing so continue.
 803                 }
 804             }
 805 
 806             // Wait until child process exits.
 807             if (AWait == true) {
 808                 Wait();
 809                 // Close process and thread handles.
 810                 Cleanup();
 811             }
 812         }
 813     }
 814 
 815     return result;
 816 }
 817 
 818 bool WindowsProcess::Wait() {
 819     bool result = false;
 820 
 821     WaitForSingleObject(FProcessInfo.hProcess, INFINITE);
 822     return result;
 823 }
 824 
 825 TProcessID WindowsProcess::GetProcessID() {
 826     return FProcessInfo.dwProcessId;
 827 }
 828 
 829 #endif //WINDOWS