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_JPACKAGER_TMP_DIR \ 42 L"\\AppData\\LocalLow\\Sun\\Java\\JPackager\\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_JPACKAGER_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\\jpackager-") + _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