1 /*
   2  * Copyright (c) 2014, 2016, 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     TString result = FilePath::IncludeTrailingSeparater(RuntimePath) +
 258         _T("jre\\bin\\jli.dll");
 259 
 260     if (FilePath::FileExists(result) == false) {
 261         result = FilePath::IncludeTrailingSeparater(RuntimePath) +
 262             _T("bin\\jli.dll");
 263     }
 264 
 265     return result;
 266 }
 267 
 268 TString WindowsPlatform::GetSystemJVMLibraryFileName() {
 269     TString result;
 270     TString jvmPath = GetSystemJRE();
 271 
 272     if (jvmPath.empty() == false) {
 273         result = GetBundledJVMLibraryFileName(jvmPath);
 274     }
 275 
 276     return result;
 277 }
 278 
 279 ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) {
 280     IniFile *result = new IniFile();
 281 
 282     if (result->LoadFromFile(FileName) == false) {
 283         // New property file format was not found, attempt to load old property file format.
 284         Helpers::LoadOldConfigFile(FileName, result);
 285     }
 286 
 287     return result;
 288 }
 289 
 290 TString WindowsPlatform::GetModuleFileName() {
 291     TString result;
 292     DynamicBuffer<wchar_t> buffer(MAX_PATH);
 293     ::GetModuleFileName(NULL, buffer.GetData(), buffer.GetSize());
 294 
 295     while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
 296         buffer.Resize(buffer.GetSize() * 2);
 297         ::GetModuleFileName(NULL, buffer.GetData(), buffer.GetSize());
 298     }
 299 
 300     result = buffer.GetData();
 301     return result;
 302 }
 303 
 304 Module WindowsPlatform::LoadLibrary(TString FileName) {
 305     return ::LoadLibrary(FileName.data());
 306 }
 307 
 308 void WindowsPlatform::FreeLibrary(Module AModule) {
 309     ::FreeLibrary((HMODULE)AModule);
 310 }
 311 
 312 Procedure WindowsPlatform::GetProcAddress(Module AModule, std::string MethodName) {
 313     return ::GetProcAddress((HMODULE)AModule, MethodName.c_str());
 314 }
 315 
 316 bool WindowsPlatform::IsMainThread() {
 317     bool result = (FMainThread == ::GetCurrentThreadId());
 318     return result;
 319 }
 320 
 321 TPlatformNumber WindowsPlatform::GetMemorySize() {
 322     SYSTEM_INFO si;
 323     GetSystemInfo(&si);
 324     size_t result = (size_t)si.lpMaximumApplicationAddress;
 325     result = result / 1048576; // Convert from bytes to megabytes.
 326     return result;
 327 }
 328 
 329 std::vector<TString> WindowsPlatform::GetLibraryImports(const TString FileName) {
 330  std::vector<TString> result;
 331     WindowsLibrary library(FileName);
 332     result = library.GetImports();
 333  return result;
 334 }
 335 
 336 std::vector<TString> FilterList(std::vector<TString> &Items, std::wregex Pattern) {
 337     std::vector<TString> result;
 338 
 339     for (std::vector<TString>::iterator it = Items.begin(); it != Items.end(); ++it) {
 340         TString item = *it;
 341         std::wsmatch match;
 342 
 343         if (std::regex_search(item, match, Pattern)) {
 344             result.push_back(item);
 345         }
 346     }
 347     return result;
 348 }
 349 
 350 std::vector<TString> WindowsPlatform::FilterOutRuntimeDependenciesForPlatform(std::vector<TString> Imports) {
 351  std::vector<TString> result;
 352 
 353     Package& package = Package::GetInstance();
 354     Macros& macros = Macros::GetInstance();
 355     TString runtimeDir = macros.ExpandMacros(package.GetJVMRuntimeDirectory());
 356     std::vector<TString> filelist = FilterList(Imports, std::wregex(_T("MSVCR.*.DLL"), std::regex_constants::icase));
 357 
 358     for (std::vector<TString>::iterator it = filelist.begin(); it != filelist.end(); ++it) {
 359         TString filename = *it;
 360         TString msvcr100FileName = FilePath::IncludeTrailingSeparater(runtimeDir) + _T("jre\\bin\\") + filename;
 361 
 362         if (FilePath::FileExists(msvcr100FileName) == true) {
 363             result.push_back(msvcr100FileName);
 364             break;
 365         }
 366         else {
 367             msvcr100FileName = FilePath::IncludeTrailingSeparater(runtimeDir) + _T("bin\\") + filename;
 368 
 369             if (FilePath::FileExists(msvcr100FileName) == true) {
 370                 result.push_back(msvcr100FileName);
 371                 break;
 372             }
 373         }
 374     }
 375 
 376  return result;
 377 }
 378 
 379 Process* WindowsPlatform::CreateProcess() {
 380     return new WindowsProcess();
 381 }
 382 
 383 #ifdef DEBUG
 384 bool WindowsPlatform::IsNativeDebuggerPresent() {
 385     bool result = false;
 386 
 387     if (IsDebuggerPresent() == TRUE) {
 388         result = true;
 389     }
 390 
 391     return result;
 392 }
 393 
 394 int WindowsPlatform::GetProcessID() {
 395     int pid = GetProcessId(GetCurrentProcess());
 396     return pid;
 397 }
 398 #endif //DEBUG
 399 
 400 //--------------------------------------------------------------------------------------------------
 401 
 402 WindowsJavaUserPreferences::WindowsJavaUserPreferences(void) : JavaUserPreferences() {
 403 }
 404 
 405 WindowsJavaUserPreferences::~WindowsJavaUserPreferences(void) {
 406 }
 407 
 408 // Java Preferences API encodes it's strings, so we need to match what Java does to work with Java.
 409 // CAVEAT: Java also does unicode encoding which this doesn't do yet. Should be sufficient for jvm args.
 410 // See WindowsPreferences.java toWindowsName()
 411 TString ConvertStringToJavaEcodedString(TString Value) {
 412     TString result;
 413     TCHAR* p = (TCHAR*)Value.c_str();
 414     TCHAR c = *p;
 415 
 416     while (c != 0) {
 417         switch (c) {
 418             case '\\':
 419                 result += _T("//");
 420                 break;
 421 
 422             case '/':
 423                 result += '\\';
 424                 break;
 425             default:
 426                 if ((c >= 'A') && (c <= 'Z')) {
 427                     result += '/';
 428                     result += c;
 429                 }
 430                 else
 431                     result += c;
 432                 break;
 433         }
 434 
 435         p++;
 436         c = *p;
 437     }
 438 
 439     return result;
 440 }
 441 
 442 // Java Preferences API encodes it's strings, so we need to match what Java does to work with Java.
 443 // CAVEAT: Java also does unicode encoding which this doesn't do yet. Should be sufficient for jvm args.
 444 // See WindowsPreferences.java toJavaName()
 445 TString ConvertJavaEcodedStringToString(TString Value) {
 446     TString result;
 447 
 448     for (size_t index = 0; index < Value.length(); index++) {
 449         TCHAR c = Value[index];
 450 
 451         switch (c) {
 452             case '/':
 453                 if ((index + 1) < Value.length()) {
 454                     index++;
 455                     TCHAR nextc = Value[index];
 456 
 457                     if (nextc >= 'A' && nextc <= 'Z') {
 458                         result += nextc;
 459                     }
 460                     else if (nextc == '/') {
 461                         result += '\\';
 462                     }
 463                 }
 464                 break;
 465             case '\\':
 466                 result += '/';
 467                 break;
 468             default:
 469                 result += c;
 470                 break;
 471         }
 472     }
 473 
 474     return result;
 475 }
 476 
 477 bool WindowsJavaUserPreferences::Load(TString Appid) {
 478     bool result = false;
 479     TString lappid = Helpers::ConvertIdToFilePath(Appid);
 480     lappid = ConvertStringToJavaEcodedString(Appid);
 481     TString registryKey = TString(_T("SOFTWARE\\JavaSoft\\Prefs\\")) + lappid + TString(_T("\\/J/V/M/User/Options"));
 482     Registry registry(HKEY_CURRENT_USER);
 483 
 484     if (registry.Open(registryKey) == true) {
 485         std::list<TString> keys = registry.GetKeys();
 486         OrderedMap<TString, TString> mapOfKeysAndValues;
 487 
 488         for (std::list<TString>::const_iterator iterator = keys.begin(); iterator != keys.end(); iterator++) {
 489             TString key = *iterator;
 490             TString value = registry.ReadString(key);
 491             key = ConvertJavaEcodedStringToString(key);
 492             value = ConvertJavaEcodedStringToString(value);
 493 
 494             if (key.empty() == false) {
 495                 mapOfKeysAndValues.Append(key, value);
 496                 result = true;
 497             }
 498         }
 499 
 500         FMap = mapOfKeysAndValues;
 501     }
 502 
 503     return result;
 504 }
 505 
 506 //--------------------------------------------------------------------------------------------------
 507 
 508 FileHandle::FileHandle(std::wstring FileName) {
 509     FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ, NULL,
 510                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
 511 }
 512 
 513 FileHandle::~FileHandle() {
 514     if (IsValid() == true) {
 515         ::CloseHandle(FHandle);
 516     }
 517 }
 518 
 519 bool FileHandle::IsValid() {
 520     return FHandle != INVALID_HANDLE_VALUE;
 521 }
 522 
 523 HANDLE FileHandle::GetHandle() {
 524     return FHandle;
 525 }
 526 
 527 FileMappingHandle::FileMappingHandle(HANDLE FileHandle) {
 528     FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
 529 }
 530 
 531 bool FileMappingHandle::IsValid() {
 532     return FHandle != NULL;
 533 }
 534 
 535 FileMappingHandle::~FileMappingHandle() {
 536     if (IsValid() == true) {
 537         ::CloseHandle(FHandle);
 538     }
 539 }
 540 
 541 HANDLE FileMappingHandle::GetHandle() {
 542     return FHandle;
 543 }
 544 
 545 FileData::FileData(HANDLE Handle) {
 546     FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0);
 547 }
 548 
 549 FileData::~FileData() {
 550     if (IsValid() == true) {
 551         ::UnmapViewOfFile(FBaseAddress);
 552     }
 553 }
 554 
 555 bool FileData::IsValid() {
 556     return FBaseAddress != NULL;
 557 }
 558 
 559 LPVOID FileData::GetBaseAddress() {
 560     return FBaseAddress;
 561 }
 562 
 563 
 564 WindowsLibrary::WindowsLibrary(std::wstring FileName) {
 565     FFileName = FileName;
 566 }
 567 
 568 std::vector<TString> WindowsLibrary::GetImports() {
 569     std::vector<TString> result;
 570     FileHandle library(FFileName);
 571 
 572     if (library.IsValid() == true) {
 573         FileMappingHandle mapping(library.GetHandle());
 574 
 575         if (mapping.IsValid() == true) {
 576             FileData fileData(mapping.GetHandle());
 577 
 578             if (fileData.IsValid() == true) {
 579                 PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)fileData.GetBaseAddress();
 580                 PIMAGE_FILE_HEADER pImgFileHdr = (PIMAGE_FILE_HEADER)fileData.GetBaseAddress();
 581 
 582                 if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
 583                     result = DumpPEFile(dosHeader);
 584                 }
 585             }
 586         }
 587     }
 588 
 589     return result;
 590 }
 591 
 592 // Given an RVA, look up the section header that encloses it and return a
 593 // pointer to its IMAGE_SECTION_HEADER
 594 PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva,
 595                                                 PIMAGE_NT_HEADERS pNTHeader) {
 596     PIMAGE_SECTION_HEADER result = 0;
 597     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
 598 
 599     for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections; index++, section++) {
 600         // Is the RVA is within this section?
 601         if ((rva >= section->VirtualAddress) &&
 602             (rva < (section->VirtualAddress + section->Misc.VirtualSize))) {
 603             result = section;
 604         }
 605     }
 606 
 607     return result;
 608 }
 609 
 610 LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader, DWORD imageBase) {
 611     LPVOID result = 0;
 612     PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva, pNTHeader);
 613 
 614     if (pSectionHdr != NULL) {
 615         INT delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
 616         result = (PVOID)(imageBase + rva - delta);
 617     }
 618 
 619     return result;
 620 }
 621 
 622 std::vector<TString> WindowsLibrary::GetImportsSection(DWORD base, PIMAGE_NT_HEADERS pNTHeader) {
 623     std::vector<TString> result;
 624 
 625     // Look up where the imports section is located. Normally in the .idata section,
 626     // but not necessarily so. Therefore, grab the RVA from the data dir.
 627     DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
 628 
 629     if (importsStartRVA != NULL) {
 630         // Get the IMAGE_SECTION_HEADER that contains the imports. This is
 631         // usually the .idata section, but doesn't have to be.
 632         PIMAGE_SECTION_HEADER pSection = GetEnclosingSectionHeader(importsStartRVA, pNTHeader);
 633 
 634         if (pSection != NULL) {
 635             PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)GetPtrFromRVA(importsStartRVA, pNTHeader,base);
 636 
 637             if (importDesc != NULL) {
 638                 while (true)
 639                 {
 640                     // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
 641                     if ((importDesc->TimeDateStamp == 0) && (importDesc->Name == 0))
 642                         break;
 643 
 644                     std::string filename = (char*)GetPtrFromRVA(importDesc->Name, pNTHeader, base);
 645                     result.push_back(PlatformString(filename));
 646                     importDesc++;   // advance to next IMAGE_IMPORT_DESCRIPTOR
 647                 }
 648             }
 649         }
 650     }
 651 
 652     return result;
 653 }
 654 
 655 std::vector<TString> WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) {
 656     std::vector<TString> result;
 657     PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)(dosHeader) + (DWORD)(dosHeader->e_lfanew));
 658 
 659     // Verify that the e_lfanew field gave us a reasonable
 660     // pointer and the PE signature.
 661     // TODO: To really fix JDK-8131321 this condition needs to be changed. There is a matching change
 662     // in JavaVirtualMachine.cpp that also needs to be changed.
 663     if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) {
 664         DWORD base = (DWORD)dosHeader;
 665         result = GetImportsSection(base, pNTHeader);
 666     }
 667 
 668     return result;
 669 }
 670 
 671 //--------------------------------------------------------------------------------------------------
 672 
 673 #include <TlHelp32.h>
 674 
 675 WindowsJob::WindowsJob() {
 676     FHandle = NULL;
 677 }
 678 
 679 WindowsJob::~WindowsJob() {
 680     if (FHandle != NULL) {
 681         CloseHandle(FHandle);
 682     }
 683 }
 684 
 685 HANDLE WindowsJob::GetHandle() {
 686     if (FHandle == NULL) {
 687         FHandle = CreateJobObject(NULL, NULL); // GLOBAL
 688 
 689         if (FHandle == NULL)
 690         {
 691             ::MessageBox( 0, _T("Could not create job object"), _T("TEST"), MB_OK);
 692         }
 693         else
 694         {
 695             JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
 696 
 697             // Configure all child processes associated with the job to terminate when the
 698             jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
 699             if (0 == SetInformationJobObject(FHandle, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
 700             {
 701                 ::MessageBox( 0, _T("Could not SetInformationJobObject"), _T("TEST"), MB_OK);
 702             }
 703         }
 704     }
 705 
 706     return FHandle;
 707 }
 708 
 709 // Initialize static member of WindowsProcess
 710 WindowsJob WindowsProcess::FJob;
 711 
 712 WindowsProcess::WindowsProcess() : Process() {
 713     FRunning = false;
 714 }
 715 
 716 WindowsProcess::~WindowsProcess() {
 717     Terminate();
 718 }
 719 
 720 void WindowsProcess::Cleanup() {
 721     CloseHandle(FProcessInfo.hProcess);
 722     CloseHandle(FProcessInfo.hThread);
 723 }
 724 
 725 bool WindowsProcess::IsRunning() {
 726     bool result = false;
 727 
 728     HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
 729     PROCESSENTRY32 process = { 0 };
 730     process.dwSize = sizeof(process);
 731 
 732     if (::Process32First(handle, &process)) {
 733         do {
 734             if (process.th32ProcessID == FProcessInfo.dwProcessId) {
 735                 result = true;
 736                 break;
 737             }
 738         }
 739         while (::Process32Next(handle, &process));
 740     }
 741 
 742     CloseHandle(handle);
 743 
 744     return result;
 745 }
 746 
 747 bool WindowsProcess::Terminate() {
 748     bool result = false;
 749 
 750     if (IsRunning() == true && FRunning == true) {
 751         FRunning = false;
 752     }
 753 
 754     return result;
 755 }
 756 
 757 bool WindowsProcess::Execute(const TString Application, const std::vector<TString> Arguments, bool AWait) {
 758     bool result = false;
 759 
 760     if (FRunning == false) {
 761         FRunning = true;
 762 
 763         STARTUPINFO startupInfo;
 764         ZeroMemory(&startupInfo, sizeof(startupInfo));
 765         startupInfo.cb = sizeof(startupInfo);
 766         ZeroMemory(&FProcessInfo, sizeof(FProcessInfo));
 767 
 768         TString command = Application;
 769 
 770         for (std::vector<TString>::const_iterator iterator = Arguments.begin(); iterator != Arguments.end(); iterator++) {
 771             command += TString(_T(" ")) + *iterator;
 772         }
 773 
 774         if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL,
 775             NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo) == FALSE) {
 776             TString message = PlatformString::Format(_T("Error: Unable to create process %s"), Application.data());
 777             throw Exception(message);
 778         }
 779         else {
 780             if (FJob.GetHandle() != NULL) {
 781                 if (::AssignProcessToJobObject(FJob.GetHandle(), FProcessInfo.hProcess) == 0) {
 782                     // Failed to assign process to job. It doesn't prevent anything from continuing so continue.
 783                 }
 784             }
 785 
 786             // Wait until child process exits.
 787             if (AWait == true) {
 788                 Wait();
 789                 // Close process and thread handles.
 790                 Cleanup();
 791             }
 792         }
 793     }
 794 
 795     return result;
 796 }
 797 
 798 bool WindowsProcess::Wait() {
 799     bool result = false;
 800 
 801     WaitForSingleObject(FProcessInfo.hProcess, INFINITE);
 802     return result;
 803 }
 804 
 805 TProcessID WindowsProcess::GetProcessID() {
 806     return FProcessInfo.dwProcessId;
 807 }
 808 
 809 bool WindowsProcess::ReadOutput() {
 810     bool result = false;
 811     //TODO implement
 812     return result;
 813 }
 814 
 815 void WindowsProcess::SetInput(TString Value) {
 816     //TODO implement
 817 }
 818 
 819 std::list<TString> WindowsProcess::GetOutput() {
 820     ReadOutput();
 821     return Process::GetOutput();
 822 }
 823 
 824 #endif //WINDOWS