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