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