| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "DebugClient.h" |
|
|
| #include <windows.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
|
|
| #include <algorithm> |
| #include <string> |
|
|
| #include "winpty_snprintf.h" |
|
|
| const wchar_t *const kPipeName = L"\\\\.\\pipe\\DebugServer"; |
|
|
| void *volatile g_debugConfig; |
|
|
| namespace { |
|
|
| |
| |
| |
| |
| class PreserveLastError { |
| public: |
| PreserveLastError() : m_lastError(GetLastError()) {} |
| ~PreserveLastError() { SetLastError(m_lastError); } |
| private: |
| DWORD m_lastError; |
| }; |
|
|
| } |
|
|
| static void sendToDebugServer(const char *message) |
| { |
| HANDLE tracePipe = INVALID_HANDLE_VALUE; |
|
|
| do { |
| |
| |
| |
| |
| |
| tracePipe = CreateFileW( |
| kPipeName, |
| GENERIC_READ | GENERIC_WRITE, |
| 0, NULL, OPEN_EXISTING, |
| SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, |
| NULL); |
| } while (tracePipe == INVALID_HANDLE_VALUE && |
| GetLastError() == ERROR_PIPE_BUSY && |
| WaitNamedPipeW(kPipeName, NMPWAIT_WAIT_FOREVER)); |
|
|
| if (tracePipe != INVALID_HANDLE_VALUE) { |
| DWORD newMode = PIPE_READMODE_MESSAGE; |
| SetNamedPipeHandleState(tracePipe, &newMode, NULL, NULL); |
| char response[16]; |
| DWORD actual = 0; |
| TransactNamedPipe(tracePipe, |
| const_cast<char*>(message), strlen(message), |
| response, sizeof(response), &actual, NULL); |
| CloseHandle(tracePipe); |
| } |
| } |
|
|
| |
| |
| |
| |
| static long long unixTimeMillis() |
| { |
| FILETIME fileTime; |
| GetSystemTimeAsFileTime(&fileTime); |
| long long msTime = (((long long)fileTime.dwHighDateTime << 32) + |
| fileTime.dwLowDateTime) / 10000; |
| return msTime - 134774LL * 24 * 3600 * 1000; |
| } |
|
|
| static const char *getDebugConfig() |
| { |
| if (g_debugConfig == NULL) { |
| PreserveLastError preserve; |
| const int bufSize = 256; |
| char buf[bufSize]; |
| DWORD actualSize = |
| GetEnvironmentVariableA("WINPTY_DEBUG", buf, bufSize); |
| if (actualSize == 0 || actualSize >= static_cast<DWORD>(bufSize)) { |
| buf[0] = '\0'; |
| } |
| const size_t len = strlen(buf) + 1; |
| char *newConfig = new char[len]; |
| std::copy(buf, buf + len, newConfig); |
| void *oldValue = InterlockedCompareExchangePointer( |
| &g_debugConfig, newConfig, NULL); |
| if (oldValue != NULL) { |
| delete [] newConfig; |
| } |
| } |
| return static_cast<const char*>(g_debugConfig); |
| } |
|
|
| bool isTracingEnabled() |
| { |
| static bool disabled, enabled; |
| if (disabled) { |
| return false; |
| } else if (enabled) { |
| return true; |
| } else { |
| |
| PreserveLastError preserve; |
| bool value = hasDebugFlag("trace") || hasDebugFlag("1"); |
| disabled = !value; |
| enabled = value; |
| return value; |
| } |
| } |
|
|
| bool hasDebugFlag(const char *flag) |
| { |
| if (strchr(flag, ',') != NULL) { |
| trace("INTERNAL ERROR: hasDebugFlag flag has comma: '%s'", flag); |
| abort(); |
| } |
| const char *const configCStr = getDebugConfig(); |
| if (configCStr[0] == '\0') { |
| return false; |
| } |
| PreserveLastError preserve; |
| std::string config(configCStr); |
| std::string flagStr(flag); |
| config = "," + config + ","; |
| flagStr = "," + flagStr + ","; |
| return config.find(flagStr) != std::string::npos; |
| } |
|
|
| void trace(const char *format, ...) |
| { |
| if (!isTracingEnabled()) |
| return; |
|
|
| PreserveLastError preserve; |
| char message[1024]; |
|
|
| va_list ap; |
| va_start(ap, format); |
| winpty_vsnprintf(message, format, ap); |
| message[sizeof(message) - 1] = '\0'; |
| va_end(ap); |
|
|
| const int currentTime = (int)(unixTimeMillis() % (100000 * 1000)); |
|
|
| char moduleName[1024]; |
| moduleName[0] = '\0'; |
| GetModuleFileNameA(NULL, moduleName, sizeof(moduleName)); |
| const char *baseName = strrchr(moduleName, '\\'); |
| baseName = (baseName != NULL) ? baseName + 1 : moduleName; |
|
|
| char fullMessage[1024]; |
| winpty_snprintf(fullMessage, |
| "[%05d.%03d %s,p%04d,t%04d]: %s", |
| currentTime / 1000, currentTime % 1000, |
| baseName, (int)GetCurrentProcessId(), (int)GetCurrentThreadId(), |
| message); |
| fullMessage[sizeof(fullMessage) - 1] = '\0'; |
|
|
| sendToDebugServer(fullMessage); |
| } |
|
|