Win32 API calls that are Unicode aware require wide character strings, but LLDB uses UTF8 everywhere. This patch does conversions wherever necessary when passing strings into and out of Win32 API calls. Patch by Cameron Differential Revision: http://reviews.llvm.org/D17107 Reviewed By: zturner, amccarth llvm-svn: 264074
145 lines
3.8 KiB
C++
145 lines
3.8 KiB
C++
//===-- HostProcessWindows.cpp ----------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Host/FileSpec.h"
|
|
#include "lldb/Host/HostThread.h"
|
|
#include "lldb/Host/ThreadLauncher.h"
|
|
#include "lldb/Host/windows/windows.h"
|
|
#include "lldb/Host/windows/HostProcessWindows.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Support/ConvertUTF.h"
|
|
|
|
#include <Psapi.h>
|
|
|
|
using namespace lldb_private;
|
|
|
|
namespace
|
|
{
|
|
struct MonitorInfo
|
|
{
|
|
HostProcess::MonitorCallback callback;
|
|
void *baton;
|
|
HANDLE process_handle;
|
|
};
|
|
}
|
|
|
|
HostProcessWindows::HostProcessWindows()
|
|
: HostNativeProcessBase()
|
|
, m_owns_handle(true)
|
|
{
|
|
}
|
|
|
|
HostProcessWindows::HostProcessWindows(lldb::process_t process)
|
|
: HostNativeProcessBase(process)
|
|
, m_owns_handle(true)
|
|
{
|
|
}
|
|
|
|
HostProcessWindows::~HostProcessWindows()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
void
|
|
HostProcessWindows::SetOwnsHandle(bool owns)
|
|
{
|
|
m_owns_handle = owns;
|
|
}
|
|
|
|
Error HostProcessWindows::Terminate()
|
|
{
|
|
Error error;
|
|
if (m_process == nullptr)
|
|
error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
|
|
|
|
if (!::TerminateProcess(m_process, 0))
|
|
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
|
|
|
|
return error;
|
|
}
|
|
|
|
Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const
|
|
{
|
|
Error error;
|
|
if (m_process == nullptr)
|
|
error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
|
|
|
|
std::vector<wchar_t> wpath(PATH_MAX);
|
|
if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size()))
|
|
{
|
|
std::string path;
|
|
if (llvm::convertWideToUTF8(wpath.data(), path))
|
|
file_spec.SetFile(path, false);
|
|
else
|
|
error.SetErrorString("Error converting path to UTF-8");
|
|
}
|
|
else
|
|
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
|
|
|
|
return error;
|
|
}
|
|
|
|
lldb::pid_t HostProcessWindows::GetProcessId() const
|
|
{
|
|
return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process);
|
|
}
|
|
|
|
bool HostProcessWindows::IsRunning() const
|
|
{
|
|
if (m_process == nullptr)
|
|
return false;
|
|
|
|
DWORD code = 0;
|
|
if (!::GetExitCodeProcess(m_process, &code))
|
|
return false;
|
|
|
|
return (code == STILL_ACTIVE);
|
|
}
|
|
|
|
HostThread
|
|
HostProcessWindows::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals)
|
|
{
|
|
HostThread monitor_thread;
|
|
MonitorInfo *info = new MonitorInfo;
|
|
info->callback = callback;
|
|
info->baton = callback_baton;
|
|
|
|
// Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that
|
|
// the monitor thread can have ownership over its own copy of the handle.
|
|
HostThread result;
|
|
if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
|
result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr);
|
|
return result;
|
|
}
|
|
|
|
lldb::thread_result_t
|
|
HostProcessWindows::MonitorThread(void *thread_arg)
|
|
{
|
|
DWORD exit_code;
|
|
|
|
MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg);
|
|
if (info)
|
|
{
|
|
::WaitForSingleObject(info->process_handle, INFINITE);
|
|
::GetExitCodeProcess(info->process_handle, &exit_code);
|
|
info->callback(info->baton, ::GetProcessId(info->process_handle), true, 0, exit_code);
|
|
::CloseHandle(info->process_handle);
|
|
delete (info);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void HostProcessWindows::Close()
|
|
{
|
|
if (m_owns_handle && m_process != LLDB_INVALID_PROCESS)
|
|
::CloseHandle(m_process);
|
|
m_process = nullptr;
|
|
}
|