src/jdk.incubator.jpackage/windows/native/libapplauncher/WindowsPlatform.cpp
branchJDK-8200758-branch
changeset 58994 b09ba68c6a19
parent 57909 c7de06ed4b54
equal deleted inserted replaced
58993:b5e1baa9d2c3 58994:b09ba68c6a19
       
     1 /*
       
     2  * Copyright (c) 2014, 2019, 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 #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) ==
       
    75                 ERROR_SUCCESS) {
       
    76             result = true;
       
    77         }
       
    78 
       
    79         return result;
       
    80     }
       
    81 
       
    82     std::list<TString> GetKeys() {
       
    83         std::list<TString> result;
       
    84         DWORD count;
       
    85 
       
    86         if (RegQueryInfoKey(FOpenKey, NULL, NULL, NULL, NULL, NULL, NULL,
       
    87                 &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
       
    88 
       
    89             DWORD length = 255;
       
    90             DynamicBuffer<TCHAR> buffer(length);
       
    91             if (buffer.GetData() == NULL) {
       
    92                 return result;
       
    93             }
       
    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                     if (!buffer.Resize(length)) {
       
   103                         return result;
       
   104                     }
       
   105                     status = RegEnumValue(FOpenKey, index, buffer.GetData(),
       
   106                             &length, NULL, NULL, NULL, NULL);
       
   107                 }
       
   108 
       
   109                 if (status == ERROR_SUCCESS) {
       
   110                     TString value = buffer.GetData();
       
   111                     result.push_back(value);
       
   112                 }
       
   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 TString WindowsPlatform::GetPackageRootDirectory() {
       
   174     TString result;
       
   175     TString filename = GetModuleFileName();
       
   176     return FilePath::ExtractFilePath(filename);
       
   177 }
       
   178 
       
   179 TString WindowsPlatform::GetAppDataDirectory() {
       
   180     TString result;
       
   181     TCHAR path[MAX_PATH];
       
   182 
       
   183     if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path) == S_OK) {
       
   184         result = path;
       
   185     }
       
   186 
       
   187     return result;
       
   188 }
       
   189 
       
   190 TString WindowsPlatform::GetAppName() {
       
   191     TString result = GetModuleFileName();
       
   192     result = FilePath::ExtractFileName(result);
       
   193     result = FilePath::ChangeFileExt(result, _T(""));
       
   194     return result;
       
   195 }
       
   196 
       
   197 void WindowsPlatform::ShowMessage(TString title, TString description) {
       
   198     MessageBox(NULL, description.data(),
       
   199             !title.empty() ? title.data() : description.data(),
       
   200             MB_ICONERROR | MB_OK);
       
   201 }
       
   202 
       
   203 void WindowsPlatform::ShowMessage(TString description) {
       
   204     TString appname = GetModuleFileName();
       
   205     appname = FilePath::ExtractFileName(appname);
       
   206     MessageBox(NULL, description.data(), appname.data(), MB_ICONERROR | MB_OK);
       
   207 }
       
   208 
       
   209 MessageResponse WindowsPlatform::ShowResponseMessage(TString title,
       
   210         TString description) {
       
   211     MessageResponse result = mrCancel;
       
   212 
       
   213     if (::MessageBox(NULL, description.data(), title.data(), MB_OKCANCEL) ==
       
   214             IDOK) {
       
   215         result = mrOK;
       
   216     }
       
   217 
       
   218     return result;
       
   219 }
       
   220 
       
   221 TString WindowsPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
       
   222     TString result = FilePath::IncludeTrailingSeparator(RuntimePath) +
       
   223             _T("jre\\bin\\jli.dll");
       
   224 
       
   225     if (FilePath::FileExists(result) == false) {
       
   226         result = FilePath::IncludeTrailingSeparator(RuntimePath) +
       
   227                 _T("bin\\jli.dll");
       
   228     }
       
   229 
       
   230     return result;
       
   231 }
       
   232 
       
   233 ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) {
       
   234     IniFile *result = new IniFile();
       
   235     if (result == NULL) {
       
   236         return NULL;
       
   237     }
       
   238 
       
   239     result->LoadFromFile(FileName);
       
   240 
       
   241     return result;
       
   242 }
       
   243 
       
   244 TString WindowsPlatform::GetModuleFileName() {
       
   245     TString result;
       
   246     DynamicBuffer<wchar_t> buffer(MAX_PATH);
       
   247     if (buffer.GetData() == NULL) {
       
   248         return result;
       
   249     }
       
   250 
       
   251     ::GetModuleFileName(NULL, buffer.GetData(),
       
   252             static_cast<DWORD> (buffer.GetSize()));
       
   253 
       
   254     while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
       
   255         if (!buffer.Resize(buffer.GetSize() * 2)) {
       
   256             return result;
       
   257         }
       
   258         ::GetModuleFileName(NULL, buffer.GetData(),
       
   259                 static_cast<DWORD> (buffer.GetSize()));
       
   260     }
       
   261 
       
   262     result = buffer.GetData();
       
   263     return result;
       
   264 }
       
   265 
       
   266 Module WindowsPlatform::LoadLibrary(TString FileName) {
       
   267     return ::LoadLibrary(FileName.data());
       
   268 }
       
   269 
       
   270 void WindowsPlatform::FreeLibrary(Module AModule) {
       
   271     ::FreeLibrary((HMODULE) AModule);
       
   272 }
       
   273 
       
   274 Procedure WindowsPlatform::GetProcAddress(Module AModule,
       
   275         std::string MethodName) {
       
   276     return ::GetProcAddress((HMODULE) AModule, MethodName.c_str());
       
   277 }
       
   278 
       
   279 bool WindowsPlatform::IsMainThread() {
       
   280     bool result = (FMainThread == ::GetCurrentThreadId());
       
   281     return result;
       
   282 }
       
   283 
       
   284 TString WindowsPlatform::GetTempDirectory() {
       
   285     TString result;
       
   286     PWSTR userDir = 0;
       
   287 
       
   288     if (SUCCEEDED(SHGetKnownFolderPath(
       
   289             FOLDERID_Profile,
       
   290             0,
       
   291             NULL,
       
   292             &userDir))) {
       
   293         result = userDir;
       
   294         result += WINDOWS_JPACKAGE_TMP_DIR;
       
   295         CoTaskMemFree(userDir);
       
   296     }
       
   297 
       
   298     return result;
       
   299 }
       
   300 
       
   301 static BOOL CALLBACK enumWindows(HWND winHandle, LPARAM lParam) {
       
   302     DWORD pid = (DWORD) lParam, wPid = 0;
       
   303     GetWindowThreadProcessId(winHandle, &wPid);
       
   304     if (pid == wPid) {
       
   305         SetForegroundWindow(winHandle);
       
   306         return FALSE;
       
   307     }
       
   308     return TRUE;
       
   309 }
       
   310 
       
   311 TPlatformNumber WindowsPlatform::GetMemorySize() {
       
   312     SYSTEM_INFO si;
       
   313     GetSystemInfo(&si);
       
   314     size_t result = (size_t) si.lpMaximumApplicationAddress;
       
   315     result = result / 1048576; // Convert from bytes to megabytes.
       
   316     return result;
       
   317 }
       
   318 
       
   319 std::vector<TString> FilterList(std::vector<TString> &Items,
       
   320         std::wregex Pattern) {
       
   321     std::vector<TString> result;
       
   322 
       
   323     for (std::vector<TString>::iterator it = Items.begin();
       
   324             it != Items.end(); ++it) {
       
   325         TString item = *it;
       
   326         std::wsmatch match;
       
   327 
       
   328         if (std::regex_search(item, match, Pattern)) {
       
   329             result.push_back(item);
       
   330         }
       
   331     }
       
   332     return result;
       
   333 }
       
   334 
       
   335 Process* WindowsPlatform::CreateProcess() {
       
   336     return new WindowsProcess();
       
   337 }
       
   338 
       
   339 void WindowsPlatform::InitStreamLocale(wios *stream) {
       
   340     const std::locale empty_locale = std::locale::empty();
       
   341     const std::locale utf8_locale =
       
   342                 std::locale(empty_locale, new std::codecvt_utf8<wchar_t>());
       
   343     stream->imbue(utf8_locale);
       
   344 }
       
   345 
       
   346 void WindowsPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) {
       
   347     if (pJavaLibrary == NULL) {
       
   348         return;
       
   349     }
       
   350 
       
   351     if (FilePath::FileExists(_T("msvcr100.dll")) == true) {
       
   352         pJavaLibrary->AddDependency(_T("msvcr100.dll"));
       
   353     }
       
   354 
       
   355     TString runtimeBin = GetPackageRuntimeBinDirectory();
       
   356     SetDllDirectory(runtimeBin.c_str());
       
   357 }
       
   358 
       
   359 void Platform::CopyString(char *Destination,
       
   360         size_t NumberOfElements, const char *Source) {
       
   361     strcpy_s(Destination, NumberOfElements, Source);
       
   362 
       
   363     if (NumberOfElements > 0) {
       
   364         Destination[NumberOfElements - 1] = '\0';
       
   365     }
       
   366 }
       
   367 
       
   368 void Platform::CopyString(wchar_t *Destination,
       
   369         size_t NumberOfElements, const wchar_t *Source) {
       
   370     wcscpy_s(Destination, NumberOfElements, Source);
       
   371 
       
   372     if (NumberOfElements > 0) {
       
   373         Destination[NumberOfElements - 1] = '\0';
       
   374     }
       
   375 }
       
   376 
       
   377 // Owner must free the return value.
       
   378 MultibyteString Platform::WideStringToMultibyteString(
       
   379         const wchar_t* value) {
       
   380     MultibyteString result;
       
   381     size_t count = 0;
       
   382 
       
   383     if (value == NULL) {
       
   384         return result;
       
   385     }
       
   386 
       
   387     count = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL);
       
   388 
       
   389     if (count > 0) {
       
   390         result.data = new char[count + 1];
       
   391         result.length = WideCharToMultiByte(CP_UTF8, 0, value, -1,
       
   392                 result.data, (int)count, NULL, NULL);
       
   393     }
       
   394 
       
   395     return result;
       
   396 }
       
   397 
       
   398 // Owner must free the return value.
       
   399 WideString Platform::MultibyteStringToWideString(const char* value) {
       
   400     WideString result;
       
   401     size_t count = 0;
       
   402 
       
   403     if (value == NULL) {
       
   404         return result;
       
   405     }
       
   406 
       
   407     mbstowcs_s(&count, NULL, 0, value, _TRUNCATE);
       
   408 
       
   409     if (count > 0) {
       
   410         result.data = new wchar_t[count + 1];
       
   411         mbstowcs_s(&result.length, result.data, count, value, count);
       
   412     }
       
   413 
       
   414     return result;
       
   415 }
       
   416 
       
   417 FileHandle::FileHandle(std::wstring FileName) {
       
   418     FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ,
       
   419             NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
       
   420 }
       
   421 
       
   422 FileHandle::~FileHandle() {
       
   423     if (IsValid() == true) {
       
   424         ::CloseHandle(FHandle);
       
   425     }
       
   426 }
       
   427 
       
   428 bool FileHandle::IsValid() {
       
   429     return FHandle != INVALID_HANDLE_VALUE;
       
   430 }
       
   431 
       
   432 HANDLE FileHandle::GetHandle() {
       
   433     return FHandle;
       
   434 }
       
   435 
       
   436 FileMappingHandle::FileMappingHandle(HANDLE FileHandle) {
       
   437     FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
       
   438 }
       
   439 
       
   440 bool FileMappingHandle::IsValid() {
       
   441     return FHandle != NULL;
       
   442 }
       
   443 
       
   444 FileMappingHandle::~FileMappingHandle() {
       
   445     if (IsValid() == true) {
       
   446         ::CloseHandle(FHandle);
       
   447     }
       
   448 }
       
   449 
       
   450 HANDLE FileMappingHandle::GetHandle() {
       
   451     return FHandle;
       
   452 }
       
   453 
       
   454 FileData::FileData(HANDLE Handle) {
       
   455     FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0);
       
   456 }
       
   457 
       
   458 FileData::~FileData() {
       
   459     if (IsValid() == true) {
       
   460         ::UnmapViewOfFile(FBaseAddress);
       
   461     }
       
   462 }
       
   463 
       
   464 bool FileData::IsValid() {
       
   465     return FBaseAddress != NULL;
       
   466 }
       
   467 
       
   468 LPVOID FileData::GetBaseAddress() {
       
   469     return FBaseAddress;
       
   470 }
       
   471 
       
   472 WindowsLibrary::WindowsLibrary(std::wstring FileName) {
       
   473     FFileName = FileName;
       
   474 }
       
   475 
       
   476 std::vector<TString> WindowsLibrary::GetImports() {
       
   477     std::vector<TString> result;
       
   478     FileHandle library(FFileName);
       
   479 
       
   480     if (library.IsValid() == true) {
       
   481         FileMappingHandle mapping(library.GetHandle());
       
   482 
       
   483         if (mapping.IsValid() == true) {
       
   484             FileData fileData(mapping.GetHandle());
       
   485 
       
   486             if (fileData.IsValid() == true) {
       
   487                 PIMAGE_DOS_HEADER dosHeader =
       
   488                         (PIMAGE_DOS_HEADER) fileData.GetBaseAddress();
       
   489                 PIMAGE_FILE_HEADER pImgFileHdr =
       
   490                         (PIMAGE_FILE_HEADER) fileData.GetBaseAddress();
       
   491                 if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
       
   492                     result = DumpPEFile(dosHeader);
       
   493                 }
       
   494             }
       
   495         }
       
   496     }
       
   497 
       
   498     return result;
       
   499 }
       
   500 
       
   501 // Given an RVA, look up the section header that encloses it and return a
       
   502 // pointer to its IMAGE_SECTION_HEADER
       
   503 
       
   504 PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva,
       
   505         PIMAGE_NT_HEADERS pNTHeader) {
       
   506     PIMAGE_SECTION_HEADER result = 0;
       
   507     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
       
   508 
       
   509     for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections;
       
   510             index++, section++) {
       
   511         // Is the RVA is within this section?
       
   512         if ((rva >= section->VirtualAddress) &&
       
   513                 (rva < (section->VirtualAddress + section->Misc.VirtualSize))) {
       
   514             result = section;
       
   515         }
       
   516     }
       
   517 
       
   518     return result;
       
   519 }
       
   520 
       
   521 LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader,
       
   522         DWORD imageBase) {
       
   523     LPVOID result = 0;
       
   524     PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva,
       
   525             pNTHeader);
       
   526 
       
   527     if (pSectionHdr != NULL) {
       
   528         INT delta = (INT) (
       
   529                 pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData);
       
   530         DWORD_PTR dwp = (DWORD_PTR) (imageBase + rva - delta);
       
   531         result = reinterpret_cast<LPVOID> (dwp); // VS2017 - FIXME
       
   532     }
       
   533 
       
   534     return result;
       
   535 }
       
   536 
       
   537 std::vector<TString> WindowsLibrary::GetImportsSection(DWORD base,
       
   538         PIMAGE_NT_HEADERS pNTHeader) {
       
   539     std::vector<TString> result;
       
   540 
       
   541     // Look up where the imports section is located. Normally in
       
   542     // the .idata section,
       
   543     // but not necessarily so. Therefore, grab the RVA from the data dir.
       
   544     DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[
       
   545             IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
       
   546 
       
   547     if (importsStartRVA != NULL) {
       
   548         // Get the IMAGE_SECTION_HEADER that contains the imports. This is
       
   549         // usually the .idata section, but doesn't have to be.
       
   550         PIMAGE_SECTION_HEADER pSection =
       
   551                 GetEnclosingSectionHeader(importsStartRVA, pNTHeader);
       
   552 
       
   553         if (pSection != NULL) {
       
   554             PIMAGE_IMPORT_DESCRIPTOR importDesc =
       
   555                     (PIMAGE_IMPORT_DESCRIPTOR) GetPtrFromRVA(
       
   556                     importsStartRVA, pNTHeader, base);
       
   557 
       
   558             if (importDesc != NULL) {
       
   559                 while (true) {
       
   560                     // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
       
   561                     if ((importDesc->TimeDateStamp == 0) &&
       
   562                             (importDesc->Name == 0)) {
       
   563                         break;
       
   564                     }
       
   565 
       
   566                     std::string filename = (char*) GetPtrFromRVA(
       
   567                             importDesc->Name, pNTHeader, base);
       
   568                     result.push_back(PlatformString(filename));
       
   569                     importDesc++; // advance to next IMAGE_IMPORT_DESCRIPTOR
       
   570                 }
       
   571             }
       
   572         }
       
   573     }
       
   574 
       
   575     return result;
       
   576 }
       
   577 
       
   578 std::vector<TString> WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) {
       
   579     std::vector<TString> result;
       
   580     // all of this is VS2017 - FIXME
       
   581     DWORD_PTR dwDosHeaders = reinterpret_cast<DWORD_PTR> (dosHeader);
       
   582     DWORD_PTR dwPIHeaders = dwDosHeaders + (DWORD) (dosHeader->e_lfanew);
       
   583 
       
   584     PIMAGE_NT_HEADERS pNTHeader =
       
   585             reinterpret_cast<PIMAGE_NT_HEADERS> (dwPIHeaders);
       
   586 
       
   587     // Verify that the e_lfanew field gave us a reasonable
       
   588     // pointer and the PE signature.
       
   589     // TODO: To really fix JDK-8131321 this condition needs to be changed.
       
   590     // There is a matching change
       
   591     // in JavaVirtualMachine.cpp that also needs to be changed.
       
   592     if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) {
       
   593         DWORD base = (DWORD) (dwDosHeaders);
       
   594         result = GetImportsSection(base, pNTHeader);
       
   595     }
       
   596 
       
   597     return result;
       
   598 }
       
   599 
       
   600 #include <TlHelp32.h>
       
   601 
       
   602 WindowsJob::WindowsJob() {
       
   603     FHandle = NULL;
       
   604 }
       
   605 
       
   606 WindowsJob::~WindowsJob() {
       
   607     if (FHandle != NULL) {
       
   608         CloseHandle(FHandle);
       
   609     }
       
   610 }
       
   611 
       
   612 HANDLE WindowsJob::GetHandle() {
       
   613     if (FHandle == NULL) {
       
   614         FHandle = CreateJobObject(NULL, NULL); // GLOBAL
       
   615 
       
   616         if (FHandle == NULL) {
       
   617             ::MessageBox(0, _T("Could not create job object"),
       
   618                     _T("TEST"), MB_OK);
       
   619         } else {
       
   620             JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
       
   621 
       
   622             // Configure all child processes associated with
       
   623             // the job to terminate when the
       
   624             jeli.BasicLimitInformation.LimitFlags =
       
   625                     JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
       
   626             if (0 == SetInformationJobObject(FHandle,
       
   627                     JobObjectExtendedLimitInformation, &jeli, sizeof (jeli))) {
       
   628                 ::MessageBox(0, _T("Could not SetInformationJobObject"),
       
   629                         _T("TEST"), MB_OK);
       
   630             }
       
   631         }
       
   632     }
       
   633 
       
   634     return FHandle;
       
   635 }
       
   636 
       
   637 // Initialize static member of WindowsProcess
       
   638 WindowsJob WindowsProcess::FJob;
       
   639 
       
   640 WindowsProcess::WindowsProcess() : Process() {
       
   641     FRunning = false;
       
   642 }
       
   643 
       
   644 WindowsProcess::~WindowsProcess() {
       
   645     Terminate();
       
   646 }
       
   647 
       
   648 void WindowsProcess::Cleanup() {
       
   649     CloseHandle(FProcessInfo.hProcess);
       
   650     CloseHandle(FProcessInfo.hThread);
       
   651 }
       
   652 
       
   653 bool WindowsProcess::IsRunning() {
       
   654     bool result = false;
       
   655 
       
   656     HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
       
   657     if (handle == INVALID_HANDLE_VALUE) {
       
   658         return false;
       
   659     }
       
   660 
       
   661     PROCESSENTRY32 process = {0};
       
   662     process.dwSize = sizeof (process);
       
   663 
       
   664     if (::Process32First(handle, &process)) {
       
   665         do {
       
   666             if (process.th32ProcessID == FProcessInfo.dwProcessId) {
       
   667                 result = true;
       
   668                 break;
       
   669             }
       
   670         } while (::Process32Next(handle, &process));
       
   671     }
       
   672 
       
   673     CloseHandle(handle);
       
   674 
       
   675     return result;
       
   676 }
       
   677 
       
   678 bool WindowsProcess::Terminate() {
       
   679     bool result = false;
       
   680 
       
   681     if (IsRunning() == true && FRunning == true) {
       
   682         FRunning = false;
       
   683     }
       
   684 
       
   685     return result;
       
   686 }
       
   687 
       
   688 bool WindowsProcess::Execute(const TString Application,
       
   689         const std::vector<TString> Arguments, bool AWait) {
       
   690     bool result = false;
       
   691 
       
   692     if (FRunning == false) {
       
   693         FRunning = true;
       
   694 
       
   695         STARTUPINFO startupInfo;
       
   696         ZeroMemory(&startupInfo, sizeof (startupInfo));
       
   697         startupInfo.cb = sizeof (startupInfo);
       
   698         ZeroMemory(&FProcessInfo, sizeof (FProcessInfo));
       
   699 
       
   700         TString command = Application;
       
   701 
       
   702         for (std::vector<TString>::const_iterator iterator = Arguments.begin();
       
   703                 iterator != Arguments.end(); iterator++) {
       
   704             command += TString(_T(" ")) + *iterator;
       
   705         }
       
   706 
       
   707         if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL,
       
   708                 NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo)
       
   709                 == FALSE) {
       
   710             TString message = PlatformString::Format(
       
   711                     _T("Error: Unable to create process %s"),
       
   712                     Application.data());
       
   713             throw Exception(message);
       
   714         } else {
       
   715             if (FJob.GetHandle() != NULL) {
       
   716                 if (::AssignProcessToJobObject(FJob.GetHandle(),
       
   717                         FProcessInfo.hProcess) == 0) {
       
   718                     // Failed to assign process to job. It doesn't prevent
       
   719                     // anything from continuing so continue.
       
   720                 }
       
   721             }
       
   722 
       
   723             // Wait until child process exits.
       
   724             if (AWait == true) {
       
   725                 Wait();
       
   726                 // Close process and thread handles.
       
   727                 Cleanup();
       
   728             }
       
   729         }
       
   730     }
       
   731 
       
   732     return result;
       
   733 }
       
   734 
       
   735 bool WindowsProcess::Wait() {
       
   736     bool result = false;
       
   737 
       
   738     WaitForSingleObject(FProcessInfo.hProcess, INFINITE);
       
   739     return result;
       
   740 }
       
   741 
       
   742 TProcessID WindowsProcess::GetProcessID() {
       
   743     return FProcessInfo.dwProcessId;
       
   744 }
       
   745 
       
   746 bool WindowsProcess::ReadOutput() {
       
   747     bool result = false;
       
   748     // TODO implement
       
   749     return result;
       
   750 }
       
   751 
       
   752 void WindowsProcess::SetInput(TString Value) {
       
   753     // TODO implement
       
   754 }
       
   755 
       
   756 std::list<TString> WindowsProcess::GetOutput() {
       
   757     ReadOutput();
       
   758     return Process::GetOutput();
       
   759 }