diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json index b417597184..72840bebbd 100644 --- a/.pipelines/ESRPSigning_core.json +++ b/.pipelines/ESRPSigning_core.json @@ -117,6 +117,7 @@ "WinUI3Apps\\PowerToys.FileLocksmithUI.dll", "WinUI3Apps\\PowerToys.FileLocksmithContextMenu.dll", "FileLocksmithContextMenuPackage.msix", + "FileLocksmithCLI.exe", "WinUI3Apps\\Peek.Common.dll", "WinUI3Apps\\Peek.FilePreviewer.dll", diff --git a/PowerToys.slnx b/PowerToys.slnx index 8bcadb8f1c..ac006fdbf4 100644 --- a/PowerToys.slnx +++ b/PowerToys.slnx @@ -420,6 +420,7 @@ + @@ -429,6 +430,9 @@ + + + diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.cpp b/src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.cpp new file mode 100644 index 0000000000..17015e1ea3 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.cpp @@ -0,0 +1,248 @@ +#include "pch.h" +#include "CLILogic.h" +#include +#include +#include +#include +#include "resource.h" +#include +#include +#include + +template +DWORD_PTR ToDwordPtr(T val) +{ + if constexpr (std::is_pointer_v) + { + return reinterpret_cast(val); + } + else + { + return static_cast(val); + } +} + +template +std::wstring FormatString(IStringProvider& strings, UINT id, Args... args) +{ + std::wstring format = strings.GetString(id); + if (format.empty()) return L""; + + DWORD_PTR arguments[] = { ToDwordPtr(args)..., 0 }; + + LPWSTR buffer = nullptr; + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, + format.c_str(), + 0, + 0, + reinterpret_cast(&buffer), + 0, + reinterpret_cast(arguments)); + + if (buffer) + { + std::wstring result(buffer); + LocalFree(buffer); + return result; + } + return L""; +} + +std::wstring get_usage(IStringProvider& strings) +{ + return strings.GetString(IDS_USAGE); +} + +std::wstring get_json(const std::vector& results) +{ + json::JsonObject root; + json::JsonArray processes; + + for (const auto& result : results) + { + json::JsonObject process; + process.SetNamedValue(L"pid", json::JsonValue::CreateNumberValue(result.pid)); + process.SetNamedValue(L"name", json::JsonValue::CreateStringValue(result.name)); + process.SetNamedValue(L"user", json::JsonValue::CreateStringValue(result.user)); + + json::JsonArray files; + for (const auto& file : result.files) + { + files.Append(json::JsonValue::CreateStringValue(file)); + } + process.SetNamedValue(L"files", files); + + processes.Append(process); + } + + root.SetNamedValue(L"processes", processes); + return root.Stringify().c_str(); +} + +std::wstring get_text(const std::vector& results, IStringProvider& strings) +{ + std::wstringstream ss; + if (results.empty()) + { + ss << strings.GetString(IDS_NO_PROCESSES); + return ss.str(); + } + + ss << strings.GetString(IDS_HEADER); + for (const auto& result : results) + { + ss << result.pid << L"\t" + << result.user << L"\t" + << result.name << std::endl; + } + return ss.str(); +} + +std::wstring kill_processes(const std::vector& results, IProcessTerminator& terminator, IStringProvider& strings) +{ + std::wstringstream ss; + for (const auto& result : results) + { + if (terminator.terminate(result.pid)) + { + ss << FormatString(strings, IDS_TERMINATED, result.pid, result.name.c_str()); + } + else + { + ss << FormatString(strings, IDS_FAILED_TERMINATE, result.pid, result.name.c_str()); + } + } + return ss.str(); +} + +CommandResult run_command(int argc, wchar_t* argv[], IProcessFinder& finder, IProcessTerminator& terminator, IStringProvider& strings) +{ + Logger::info("Parsing arguments"); + if (argc < 2) + { + Logger::warn("No arguments provided"); + return { 1, get_usage(strings) }; + } + + bool json_output = false; + bool kill = false; + bool wait = false; + int timeout_ms = -1; + std::vector paths; + + for (int i = 1; i < argc; ++i) + { + std::wstring arg = argv[i]; + if (arg == L"--json") + { + json_output = true; + } + else if (arg == L"--kill") + { + kill = true; + } + else if (arg == L"--wait") + { + wait = true; + } + else if (arg == L"--timeout") + { + if (i + 1 < argc) + { + try + { + timeout_ms = std::stoi(argv[++i]); + } + catch (...) + { + Logger::error("Invalid timeout value"); + return { 1, strings.GetString(IDS_ERROR_INVALID_TIMEOUT) }; + } + } + else + { + Logger::error("Timeout argument missing"); + return { 1, strings.GetString(IDS_ERROR_TIMEOUT_ARG) }; + } + } + else if (arg == L"--help") + { + return { 0, get_usage(strings) }; + } + else + { + paths.push_back(arg); + } + } + + if (paths.empty()) + { + Logger::error("No paths specified"); + return { 1, strings.GetString(IDS_ERROR_NO_PATHS) }; + } + + Logger::info("Processing {} paths", paths.size()); + + if (wait) + { + std::wstringstream ss; + if (json_output) + { + Logger::warn("Wait is incompatible with JSON output"); + ss << strings.GetString(IDS_WARN_JSON_WAIT); + json_output = false; + } + + ss << strings.GetString(IDS_WAITING); + auto start_time = std::chrono::steady_clock::now(); + while (true) + { + auto results = finder.find(paths); + if (results.empty()) + { + Logger::info("Files unlocked"); + ss << strings.GetString(IDS_UNLOCKED); + break; + } + + if (timeout_ms >= 0) + { + auto current_time = std::chrono::steady_clock::now(); + auto elapsed = std::chrono::duration_cast(current_time - start_time).count(); + if (elapsed > timeout_ms) + { + Logger::warn("Timeout waiting for files to be unlocked"); + ss << strings.GetString(IDS_TIMEOUT); + return { 1, ss.str() }; + } + } + + Sleep(200); + } + return { 0, ss.str() }; + } + + auto results = finder.find(paths); + Logger::info("Found {} processes locking the files", results.size()); + std::wstringstream output_ss; + + if (kill) + { + Logger::info("Killing processes"); + output_ss << kill_processes(results, terminator, strings); + // Re-check after killing + results = finder.find(paths); + Logger::info("Remaining processes: {}", results.size()); + } + + if (json_output) + { + output_ss << get_json(results) << std::endl; + } + else + { + output_ss << get_text(results, strings); + } + + return { 0, output_ss.str() }; +} diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.h b/src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.h new file mode 100644 index 0000000000..c8f519592f --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/CLILogic.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include "FileLocksmithLib/FileLocksmith.h" +#include + +struct CommandResult +{ + int exit_code; + std::wstring output; +}; + +struct IProcessFinder +{ + virtual std::vector find(const std::vector& paths) = 0; + virtual ~IProcessFinder() = default; +}; + +struct IProcessTerminator +{ + virtual bool terminate(DWORD pid) = 0; + virtual ~IProcessTerminator() = default; +}; + +struct IStringProvider +{ + virtual std::wstring GetString(UINT id) = 0; + virtual ~IStringProvider() = default; +}; + +CommandResult run_command(int argc, wchar_t* argv[], IProcessFinder& finder, IProcessTerminator& terminator, IStringProvider& strings); diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.rc b/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.rc new file mode 100644 index 0000000000..641c19fb49 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.rc @@ -0,0 +1,19 @@ +#include "resource.h" +#include + +STRINGTABLE +BEGIN + IDS_USAGE "Usage: FileLocksmithCLI.exe [options] [path2] ...\nOptions:\n --kill Kill processes locking the files\n --json Output results in JSON format\n --wait Wait for files to be unlocked\n --timeout Timeout in milliseconds for --wait\n --help Show this help message\n" + IDS_NO_PROCESSES "No processes found locking the file(s).\n" + IDS_HEADER "PID\tUser\tProcess\n" + IDS_TERMINATED "Terminated process %1!d! (%2)\n" + IDS_FAILED_TERMINATE "Failed to terminate process %1!d! (%2)\n" + IDS_FAILED_OPEN "Failed to open process %1!d! (%2)\n" + IDS_ERROR_NO_PATHS "Error: No paths specified.\n" + IDS_WARN_JSON_WAIT "Warning: --wait is incompatible with --json. Ignoring --json.\n" + IDS_WAITING "Waiting for files to be unlocked...\n" + IDS_UNLOCKED "Files unlocked.\n" + IDS_TIMEOUT "Timeout waiting for files to be unlocked.\n" + IDS_ERROR_INVALID_TIMEOUT "Error: Invalid timeout value.\n" + IDS_ERROR_TIMEOUT_ARG "Error: --timeout requires an argument.\n" +END diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj b/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj new file mode 100644 index 0000000000..ca85b58d28 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj @@ -0,0 +1,119 @@ + + + + + 17.0 + Win32Proj + {49D456D3-F485-45AF-8875-45B44F193DDC} + FileLocksmithCLI + 10.0 + FileLocksmithCLI + + + + + Application + true + v143 + Unicode + + + Application + false + v143 + Unicode + + + + + + + + + + + + ..\..\..\..\$(Platform)\$(Configuration) + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + $(ProjectDir)..;$(ProjectDir)..\..\..;$(ProjectDir)..\..;%(AdditionalIncludeDirectories) + Use + pch.h + false + + + Console + true + shlwapi.lib;ntdll.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + $(ProjectDir)..;$(ProjectDir)..\..\..;$(ProjectDir)..\..;%(AdditionalIncludeDirectories) + Use + pch.h + false + + + Console + true + true + true + shlwapi.lib;ntdll.lib;%(AdditionalDependencies) + + + + + + + Create + + + + + + + + + + + + + {9d52fd25-ef90-4f9a-a015-91efc5daf54f} + + + {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} + + + {6955446d-23f7-4023-9bb3-8657f904af99} + + + {1248566c-272a-43c0-88d6-e6675d569a09} + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj.filters b/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj.filters new file mode 100644 index 0000000000..e8a641d95d --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + + diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/main.cpp b/src/modules/FileLocksmith/FileLocksmithCLI/main.cpp new file mode 100644 index 0000000000..67a4304b4e --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/main.cpp @@ -0,0 +1,71 @@ +#include "pch.h" +#include "CLILogic.h" +#include "FileLocksmithLib/FileLocksmith.h" +#include +#include "resource.h" +#include +#include + +struct RealProcessFinder : IProcessFinder +{ + std::vector find(const std::vector& paths) override + { + return find_processes_recursive(paths); + } +}; + +struct RealProcessTerminator : IProcessTerminator +{ + bool terminate(DWORD pid) override + { + HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + if (hProcess) + { + bool result = TerminateProcess(hProcess, 0); + CloseHandle(hProcess); + return result; + } + return false; + } +}; + +struct RealStringProvider : IStringProvider +{ + std::wstring GetString(UINT id) override + { + wchar_t buffer[4096]; + int len = LoadStringW(GetModuleHandle(NULL), id, buffer, ARRAYSIZE(buffer)); + if (len > 0) + { + return std::wstring(buffer, len); + } + return L""; + } +}; + +#ifndef UNIT_TEST +int wmain(int argc, wchar_t* argv[]) +{ + winrt::init_apartment(); + LoggerHelpers::init_logger(L"FileLocksmithCLI", L"", LogSettings::fileLocksmithLoggerName); + Logger::info("FileLocksmithCLI started"); + + RealProcessFinder finder; + RealProcessTerminator terminator; + RealStringProvider strings; + + auto result = run_command(argc, argv, finder, terminator, strings); + + if (result.exit_code != 0) + { + Logger::error("Command failed with exit code {}", result.exit_code); + } + else + { + Logger::info("Command succeeded"); + } + + std::wcout << result.output; + return result.exit_code; +} +#endif diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/packages.config b/src/modules/FileLocksmith/FileLocksmithCLI/packages.config new file mode 100644 index 0000000000..2e5039eb82 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/pch.cpp b/src/modules/FileLocksmith/FileLocksmithCLI/pch.cpp new file mode 100644 index 0000000000..1d9f38c57d --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/pch.h b/src/modules/FileLocksmith/FileLocksmithCLI/pch.h new file mode 100644 index 0000000000..6099342b41 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/pch.h @@ -0,0 +1,22 @@ +#pragma once + +#ifndef PCH_H +#define PCH_H + +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#endif // PCH_H diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/resource.h b/src/modules/FileLocksmith/FileLocksmithCLI/resource.h new file mode 100644 index 0000000000..be12cac3ac --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/resource.h @@ -0,0 +1,16 @@ +// resource.h +#pragma once + +#define IDS_USAGE 101 +#define IDS_NO_PROCESSES 102 +#define IDS_HEADER 103 +#define IDS_TERMINATED 104 +#define IDS_FAILED_TERMINATE 105 +#define IDS_FAILED_OPEN 106 +#define IDS_ERROR_NO_PATHS 107 +#define IDS_WARN_JSON_WAIT 108 +#define IDS_WAITING 109 +#define IDS_UNLOCKED 110 +#define IDS_TIMEOUT 111 +#define IDS_ERROR_INVALID_TIMEOUT 112 +#define IDS_ERROR_TIMEOUT_ARG 113 diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLITests.cpp b/src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLITests.cpp new file mode 100644 index 0000000000..a67e42badf --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLITests.cpp @@ -0,0 +1,130 @@ +#include "pch.h" +#include "CppUnitTest.h" +#include "../CLILogic.h" +#include + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace FileLocksmithCLIUnitTests +{ + struct MockProcessFinder : IProcessFinder + { + std::vector results; + std::vector find(const std::vector& paths) override + { + (void)paths; + return results; + } + }; + + struct MockProcessTerminator : IProcessTerminator + { + bool shouldSucceed = true; + std::vector terminatedPids; + bool terminate(DWORD pid) override + { + terminatedPids.push_back(pid); + return shouldSucceed; + } + }; + + struct MockStringProvider : IStringProvider + { + std::map strings; + std::wstring GetString(UINT id) override + { + if (strings.count(id)) return strings[id]; + return L"String_" + std::to_wstring(id); + } + }; + + TEST_CLASS(CLITests) + { + public: + + TEST_METHOD(TestNoArgs) + { + MockProcessFinder finder; + MockProcessTerminator terminator; + MockStringProvider strings; + + wchar_t* argv[] = { (wchar_t*)L"exe" }; + auto result = run_command(1, argv, finder, terminator, strings); + + Assert::AreEqual(1, result.exit_code); + } + + TEST_METHOD(TestHelp) + { + MockProcessFinder finder; + MockProcessTerminator terminator; + MockStringProvider strings; + + wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"--help" }; + auto result = run_command(2, argv, finder, terminator, strings); + + Assert::AreEqual(0, result.exit_code); + } + + TEST_METHOD(TestFindProcesses) + { + MockProcessFinder finder; + finder.results = { { L"process", 123, L"user", { L"file1" } } }; + MockProcessTerminator terminator; + MockStringProvider strings; + + wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"file1" }; + auto result = run_command(2, argv, finder, terminator, strings); + + Assert::AreEqual(0, result.exit_code); + Assert::IsTrue(result.output.find(L"123") != std::wstring::npos); + Assert::IsTrue(result.output.find(L"process") != std::wstring::npos); + } + + TEST_METHOD(TestJsonOutput) + { + MockProcessFinder finder; + finder.results = { { L"process", 123, L"user", { L"file1" } } }; + MockProcessTerminator terminator; + MockStringProvider strings; + + wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"file1", (wchar_t*)L"--json" }; + auto result = run_command(3, argv, finder, terminator, strings); + + Microsoft::VisualStudio::CppUnitTestFramework::Logger::WriteMessage(result.output.c_str()); + + Assert::AreEqual(0, result.exit_code); + Assert::IsTrue(result.output.find(L"\"pid\"") != std::wstring::npos); + Assert::IsTrue(result.output.find(L"123") != std::wstring::npos); + } + + TEST_METHOD(TestKill) + { + MockProcessFinder finder; + finder.results = { { L"process", 123, L"user", { L"file1" } } }; + MockProcessTerminator terminator; + MockStringProvider strings; + + wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"file1", (wchar_t*)L"--kill" }; + auto result = run_command(3, argv, finder, terminator, strings); + + Assert::AreEqual(0, result.exit_code); + Assert::AreEqual((size_t)1, terminator.terminatedPids.size()); + Assert::AreEqual((DWORD)123, terminator.terminatedPids[0]); + } + + TEST_METHOD(TestTimeout) + { + MockProcessFinder finder; + // Always return results so it waits + finder.results = { { L"process", 123, L"user", { L"file1" } } }; + MockProcessTerminator terminator; + MockStringProvider strings; + + wchar_t* argv[] = { (wchar_t*)L"exe", (wchar_t*)L"file1", (wchar_t*)L"--wait", (wchar_t*)L"--timeout", (wchar_t*)L"100" }; + auto result = run_command(5, argv, finder, terminator, strings); + + Assert::AreEqual(1, result.exit_code); + } + }; +} diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj b/src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj new file mode 100644 index 0000000000..4b423c0183 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj @@ -0,0 +1,84 @@ + + + + + {A1B2C3D4-E5F6-7890-1234-567890ABCDEF} + Win32Proj + FileLocksmithCLIUnitTests + FileLocksmithCLI.UnitTests + 10.0 + + + + + v143 + DynamicLibrary + Unicode + + + + + + + + + + + + ..\..\..\..\..\$(Platform)\$(Configuration)\tests\FileLocksmithCLI\ + + + + ..\;..\..\;..\..\..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;UNIT_TEST;%(PreprocessorDefinitions) + true + Use + pch.h + 26466;%(DisableSpecificWarnings) + + + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + shlwapi.lib;ntdll.lib;%(AdditionalDependencies) + + + + + + + + Create + + + + NotUsing + + + + + {9d52fd25-ef90-4f9a-a015-91efc5daf54f} + + + {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} + + + {6955446d-23f7-4023-9bb3-8657f904af99} + + + {1248566c-272a-43c0-88d6-e6675d569a09} + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/tests/packages.config b/src/modules/FileLocksmith/FileLocksmithCLI/tests/packages.config new file mode 100644 index 0000000000..2e5039eb82 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/tests/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.cpp b/src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.cpp new file mode 100644 index 0000000000..1d9f38c57d --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.h b/src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.h new file mode 100644 index 0000000000..7041294e28 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithCLI/tests/pch.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include "CppUnitTest.h" diff --git a/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmith.h b/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmith.h new file mode 100644 index 0000000000..087df84a68 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmith.h @@ -0,0 +1,9 @@ +#pragma once + +#include "ProcessResult.h" + +// Second version, checks handles towards files and all subfiles and folders of given dirs, if any. +std::vector find_processes_recursive(const std::vector& paths); + +// Gives the full path of the executable, given the process id +std::wstring pid_to_full_path(DWORD pid); diff --git a/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj b/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj index ebbeb20895..fdfb0c666f 100644 --- a/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj +++ b/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj @@ -34,9 +34,9 @@ Level3 true - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;FILELOCKSMITH_LIB_STATIC;%(PreprocessorDefinitions) true - ../../..;../..; + ..\FileLocksmithLibInterop;../../..;../..; @@ -50,9 +50,9 @@ true true true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;FILELOCKSMITH_LIB_STATIC;%(PreprocessorDefinitions) true - ../../..;../..; + ..\FileLocksmithLibInterop;../../..;../..; @@ -68,13 +68,15 @@ - + + + Create diff --git a/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj.filters b/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj.filters index ed6b2674fc..c38c9b2d2e 100644 --- a/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj.filters +++ b/src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj.filters @@ -38,6 +38,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + Source Files diff --git a/src/modules/FileLocksmith/FileLocksmithLib/ProcessResult.h b/src/modules/FileLocksmith/FileLocksmithLib/ProcessResult.h new file mode 100644 index 0000000000..614e38a209 --- /dev/null +++ b/src/modules/FileLocksmith/FileLocksmithLib/ProcessResult.h @@ -0,0 +1,12 @@ +#pragma once +#include +#include +#include + +struct ProcessResult +{ + std::wstring name; + DWORD pid; + std::wstring user; + std::vector files; +}; diff --git a/src/modules/FileLocksmith/FileLocksmithLib/Settings.cpp b/src/modules/FileLocksmith/FileLocksmithLib/Settings.cpp index de997144ca..c30387df5d 100644 --- a/src/modules/FileLocksmith/FileLocksmithLib/Settings.cpp +++ b/src/modules/FileLocksmith/FileLocksmithLib/Settings.cpp @@ -2,6 +2,7 @@ #include "Settings.h" #include "Constants.h" +#include #include #include diff --git a/src/modules/FileLocksmith/FileLocksmithLib/pch.h b/src/modules/FileLocksmith/FileLocksmithLib/pch.h deleted file mode 100644 index 885d5d62e4..0000000000 --- a/src/modules/FileLocksmith/FileLocksmithLib/pch.h +++ /dev/null @@ -1,13 +0,0 @@ -// pch.h: This is a precompiled header file. -// Files listed below are compiled only once, improving build performance for future builds. -// This also affects IntelliSense performance, including code completion and many code browsing features. -// However, files listed here are ALL re-compiled if any one of them is updated between builds. -// Do not add files here that you will be updating frequently as this negates the performance advantage. - -#ifndef PCH_H -#define PCH_H - -// add headers that you want to pre-compile here -#include "framework.h" - -#endif //PCH_H diff --git a/src/modules/FileLocksmith/FileLocksmithLibInterop/pch.h b/src/modules/FileLocksmith/FileLocksmithLibInterop/pch.h index f2449b1578..4f47976891 100644 --- a/src/modules/FileLocksmith/FileLocksmithLibInterop/pch.h +++ b/src/modules/FileLocksmith/FileLocksmithLibInterop/pch.h @@ -18,4 +18,6 @@ #include #include +#ifndef FILELOCKSMITH_LIB_STATIC #include +#endif