| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #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); |
| | } |
| |
|