diff options
Diffstat (limited to 'src/libs/utils/process_stub_win.c')
-rw-r--r-- | src/libs/utils/process_stub_win.c | 204 |
1 files changed, 0 insertions, 204 deletions
diff --git a/src/libs/utils/process_stub_win.c b/src/libs/utils/process_stub_win.c deleted file mode 100644 index 09f220a6c6..0000000000 --- a/src/libs/utils/process_stub_win.c +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 /* WinXP, needed for DebugActiveProcessStop() */ - -#include <windows.h> -#include <shellapi.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <direct.h> - -static FILE *qtcFd; -static wchar_t *sleepMsg; - -enum RunMode { Run, Debug, Suspend }; - -/* Print some "press enter" message, wait for that, exit. */ -static void doExit(int code) -{ - char buf[2]; - _putws(sleepMsg); - fgets(buf, 2, stdin); /* Minimal size to make it wait */ - exit(code); -} - -/* Print an error message for unexpected Windows system errors, wait, exit. */ -static void systemError(const char *str) -{ - fprintf(stderr, str, GetLastError()); - doExit(3); -} - -/* Send a message to the master. */ -static void sendMsg(const char *msg, int num) -{ - int pidStrLen; - char pidStr[64]; - - pidStrLen = sprintf(pidStr, msg, num); - if (fwrite(pidStr, pidStrLen, 1, qtcFd) != 1 || fflush(qtcFd)) { - fprintf(stderr, "Cannot write to creator comm socket: %s\n", - strerror(errno)); - doExit(3); - } -} - -/* Ignore the first ctrl-c/break within a second. */ -static BOOL WINAPI ctrlHandler(DWORD dwCtrlType) -{ - static ULARGE_INTEGER lastTime; - ULARGE_INTEGER thisTime; - SYSTEMTIME sysTime; - FILETIME fileTime; - - if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) { - GetSystemTime(&sysTime); - SystemTimeToFileTime(&sysTime, &fileTime); - thisTime.LowPart = fileTime.dwLowDateTime; - thisTime.HighPart = fileTime.dwHighDateTime; - if (lastTime.QuadPart + 10000000 < thisTime.QuadPart) { - lastTime.QuadPart = thisTime.QuadPart; - return TRUE; - } - } - return FALSE; -} - -enum { - ArgCmd = 0, - ArgAction, - ArgSocket, - ArgDir, - ArgEnv, - ArgCmdLine, - ArgMsg, - ArgCount -}; - -/* syntax: $0 {"run"|"debug"} <pid-socket> <workdir> <env-file> <cmdline> <continuation-msg> */ -/* exit codes: 0 = ok, 1 = invocation error, 3 = internal error */ -int main() -{ - int argc; - int creationFlags; - wchar_t **argv; - wchar_t *env = 0; - STARTUPINFOW si; - PROCESS_INFORMATION pi; - DEBUG_EVENT dbev; - enum RunMode mode = Run; - HANDLE image = NULL; - - argv = CommandLineToArgvW(GetCommandLine(), &argc); - - if (argc != ArgCount) { - fprintf(stderr, "This is an internal helper of Qt Creator. Do not run it manually.\n"); - return 1; - } - sleepMsg = argv[ArgMsg]; - - /* Connect to the master, i.e. Creator. */ - if (!(qtcFd = _wfopen(argv[ArgSocket], L"w"))) { - fprintf(stderr, "Cannot connect creator comm pipe %S: %s\n", - argv[ArgSocket], strerror(errno)); - doExit(1); - } - - if (*argv[ArgDir] && !SetCurrentDirectoryW(argv[ArgDir])) { - /* Only expected error: no such file or direcotry */ - sendMsg("err:chdir %d\n", GetLastError()); - return 1; - } - - if (*argv[ArgEnv]) { - FILE *envFd; - long size; - if (!(envFd = _wfopen(argv[ArgEnv], L"rb"))) { - fprintf(stderr, "Cannot read creator env file %S: %s\n", - argv[ArgEnv], strerror(errno)); - doExit(1); - } - fseek(envFd, 0, SEEK_END); - size = ftell(envFd); - rewind(envFd); - env = malloc(size); - if (fread(env, 1, size, envFd) != size) { - perror("Failed to read env file"); - doExit(1); - } - fclose(envFd); - } - - ZeroMemory(&pi, sizeof(pi)); - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - creationFlags = CREATE_UNICODE_ENVIRONMENT; - if (!wcscmp(argv[ArgAction], L"debug")) { - mode = Debug; - } else if (!wcscmp(argv[ArgAction], L"suspend")) { - mode = Suspend; - } - - switch (mode) { - case Debug: - creationFlags |= DEBUG_ONLY_THIS_PROCESS; - break; - case Suspend: - creationFlags |= CREATE_SUSPENDED; - break; - default: - break; - } - if (!CreateProcessW(0, argv[ArgCmdLine], 0, 0, FALSE, creationFlags, env, 0, &si, &pi)) { - /* Only expected error: no such file or direcotry, i.e. executable not found */ - sendMsg("err:exec %d\n", GetLastError()); - doExit(1); - } - - /* This is somewhat convoluted. What we actually want is creating a - suspended process and letting gdb attach to it. Unfortunately, - the Windows kernel runs amok when we attempt this. - So instead we start a debugged process, eat all the initial - debug events, suspend the process and detach from it. If gdb - tries to attach *now*, everything goes smoothly. Yay. */ - if (mode == Debug) { - do { - if (!WaitForDebugEvent (&dbev, INFINITE)) - systemError("Cannot fetch debug event, error %d\n"); - if (dbev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) - image = dbev.u.CreateProcessInfo.hFile; - if (dbev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { - /* The first exception to be delivered is a trap - which indicates completion of startup. */ - if (SuspendThread(pi.hThread) == (DWORD)-1) - systemError("Cannot suspend debugee, error %d\n"); - } - if (!ContinueDebugEvent(dbev.dwProcessId, dbev.dwThreadId, DBG_CONTINUE)) - systemError("Cannot continue debug event, error %d\n"); - } while (dbev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT); - if (!DebugActiveProcessStop(dbev.dwProcessId)) - systemError("Cannot detach from debugee, error %d\n"); - if (image) - CloseHandle(image); - } - - SetConsoleCtrlHandler(ctrlHandler, TRUE); - - sendMsg("thread %d\n", pi.dwThreadId); - sendMsg("pid %d\n", pi.dwProcessId); - - if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) - systemError("Wait for debugee failed, error %d\n"); - - /* Don't close the process/thread handles, so that the kernel doesn't free - the resources before ConsoleProcess is able to obtain handles to them - - this would be a problem if the child process exits very quickly. */ - doExit(0); - - return 0; -} |