------------------------------------------------------------------------------
| 74 | |
| 75 | //------------------------------------------------------------------------------ |
| 76 | int vtkWin32ProcessOutputWindow::Initialize() |
| 77 | { |
| 78 | // Write the executable as a temporary file. It will delete itself. |
| 79 | char tempDir[_MAX_PATH + 1] = ""; |
| 80 | |
| 81 | // We will try putting the executable in the system temp directory. |
| 82 | // Note that the returned path already has a trailing slash. |
| 83 | DWORD length = GetTempPath(_MAX_PATH + 1, tempDir); |
| 84 | if (length <= 0 || length > _MAX_PATH) |
| 85 | { |
| 86 | return 0; |
| 87 | } |
| 88 | |
| 89 | // Construct the executable name from the process id, pointer to |
| 90 | // this output window instance, and a count. This should be unique. |
| 91 | // Construct the executable name from the process id, pointer to this output window instance, and |
| 92 | // a count. |
| 93 | auto exeName = vtk::format( |
| 94 | "vtkWin32OWP_{}_{:p}_{}.exe", GetCurrentProcessId(), static_cast<void*>(this), this->Count++); |
| 95 | |
| 96 | // Construct the full path to the executable.¬ |
| 97 | auto exeFullPath = vtk::format("{:s}{:s}", tempDir, exeName); |
| 98 | |
| 99 | // Try to write the executable to disk. |
| 100 | if (!vtkEncodedArrayWin32OutputWindowProcessWrite(exeFullPath.c_str())) |
| 101 | { |
| 102 | return 0; |
| 103 | } |
| 104 | |
| 105 | // Create a process and a pipe connected to its stdin. |
| 106 | STARTUPINFO si; |
| 107 | PROCESS_INFORMATION pi; |
| 108 | ZeroMemory(&si, sizeof(si)); |
| 109 | si.cb = sizeof(si); |
| 110 | si.dwFlags |= STARTF_USESHOWWINDOW; |
| 111 | si.dwFlags |= STARTF_USESTDHANDLES; |
| 112 | si.wShowWindow = SW_SHOWDEFAULT; |
| 113 | |
| 114 | // Create a pipe with an inherited read end. |
| 115 | if (!CreatePipe(&si.hStdInput, &this->OutputPipe, 0, 0) || |
| 116 | !DuplicateHandle(GetCurrentProcess(), si.hStdInput, GetCurrentProcess(), &si.hStdInput, 0, TRUE, |
| 117 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) |
| 118 | { |
| 119 | DeleteFile(exeFullPath.c_str()); |
| 120 | return 0; |
| 121 | } |
| 122 | |
| 123 | // Create the child process. |
| 124 | if (!CreateProcess(0, exeFullPath.data(), 0, 0, TRUE, NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi)) |
| 125 | { |
| 126 | DeleteFile(exeFullPath.c_str()); |
| 127 | CloseHandle(si.hStdInput); |
| 128 | return 0; |
| 129 | } |
| 130 | |
| 131 | // We only need to keep the pipe write end. Close all other handles. |
| 132 | CloseHandle(si.hStdInput); |
| 133 | CloseHandle(pi.hThread); |
no test coverage detected