#include "pch.h" #include "FileLocksmith.h" #include "../FileLocksmithExt/Constants.h" namespace FileLocksmith::Interop { public ref struct ProcessResult { System::String^ name; System::UInt32 pid; array^ files; System::Boolean isExpanded; // For helping in the UI }; System::String^ from_wstring_view(std::wstring_view str) { return gcnew System::String(str.data(), 0, static_cast(str.size())); } std::wstring from_system_string(System::String^ str) { // TODO use some built-in method auto chars = str->ToCharArray(); std::wstring result(chars->Length, 0); for (int i = 0; i < chars->Length; i++) { result[i] = chars[i]; } return result; } std::wstring paths_file() { std::wstring path = from_system_string(interop::Constants::AppDataPath()); path += L"\\"; path += constants::nonlocalizable::PowerToyName; path += L"\\"; path += constants::nonlocalizable::LastRunPath; return path; } std::wstring executable_path() { return pid_to_full_path(GetCurrentProcessId()); } public ref struct NativeMethods { static array ^ FindProcessesRecursive(array^ paths) { const int n = paths->Length; std::vector paths_cpp(n); for (int i = 0; i < n; i++) { paths_cpp[i] = from_system_string(paths[i]); } auto result_cpp = find_processes_recursive(paths_cpp); const auto result_size = static_cast(result_cpp.size()); auto result = gcnew array(result_size); for (int i = 0; i < result_size; i++) { auto item = gcnew ProcessResult; item->name = from_wstring_view(result_cpp[i].name); item->pid = result_cpp[i].pid; const int n_files = static_cast(result_cpp[i].files.size()); item->files = gcnew array(n_files); for (int j = 0; j < n_files; j++) { item->files[j] = from_wstring_view(result_cpp[i].files[j]); } item->isExpanded = false; result[i] = item; } return result; } static System::String^ PidToUser(System::UInt32 pid) { auto user_cpp = pid_to_user(pid); return from_wstring_view(user_cpp); } static System::String^ PidToFullPath(System::UInt32 pid) { auto path_cpp = pid_to_full_path(pid); return from_wstring_view(path_cpp); } static array^ ReadPathsFromFile() { std::ifstream stream(paths_file()); std::vector result_cpp; std::wstring line; bool finished = false; while (!finished) { WCHAR ch; // We have to read data like this if (!stream.read(reinterpret_cast(&ch), 2)) { finished = true; } else if (ch == L'\n') { if (line.empty()) { finished = true; } else { result_cpp.push_back(line); line = {}; } } else { line += ch; } } auto result = gcnew array(static_cast(result_cpp.size())); for (int i = 0; i < result->Length; i++) { result[i] = from_wstring_view(result_cpp[i]); } return result; } static System::Boolean StartAsElevated(array ^ paths) { std::ofstream stream(paths_file()); const WCHAR newline = L'\n'; for (int i = 0; i < paths->Length; i++) { auto path_cpp = from_system_string(paths[i]); stream.write(reinterpret_cast(path_cpp.c_str()), path_cpp.size() * sizeof(WCHAR)); stream.write(reinterpret_cast(&newline), sizeof(WCHAR)); } stream.write(reinterpret_cast(&newline), sizeof(WCHAR)); if (!stream) { return false; } stream.close(); auto exec_path = executable_path(); SHELLEXECUTEINFOW exec_info; exec_info.cbSize = sizeof(exec_info); exec_info.fMask = SEE_MASK_NOCLOSEPROCESS; exec_info.hwnd = NULL; exec_info.lpVerb = L"runas"; exec_info.lpFile = exec_path.c_str(); exec_info.lpParameters = L"--elevated"; exec_info.lpDirectory = NULL; exec_info.nShow = SW_SHOW; exec_info.hInstApp = NULL; if (ShellExecuteExW(&exec_info)) { CloseHandle(exec_info.hProcess); return true; } return false; } }; }