mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-12-04 11:59:07 +08:00
WIP
This commit is contained in:
parent
fef50971af
commit
fed3f4a483
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h FileLocksmithContextMenu.base.rc FileLocksmithContextMenu.rc" />
|
||||
</Target>
|
||||
@ -120,11 +121,14 @@ MakeAppx.exe pack /d . /p $(OutDir)FileLocksmithContextMenuPackage.msix /nv</Com
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>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}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
@ -37,6 +37,31 @@
|
||||
<None Include="Resources.resx">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Assets\FileLocksmith\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="FileLocksmithContextMenu.base.rc">
|
||||
|
@ -5,17 +5,20 @@
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/elevation.h>
|
||||
|
||||
#include "FileLocksmithLib/IPC.h"
|
||||
#include "FileLocksmithLib/Settings.h"
|
||||
#include "FileLocksmithLib/Trace.h"
|
||||
|
||||
#include <atlstr.h>
|
||||
#include <atlfile.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <shobjidl_core.h>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <wrl/module.h>
|
||||
|
||||
#include "Generated Files/resource.h"
|
||||
|
||||
#define BUFSIZE 4096 * 4
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
@ -92,18 +95,34 @@ public:
|
||||
IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept
|
||||
{
|
||||
Trace::Invoked();
|
||||
ipc::Writer writer;
|
||||
|
||||
if (selection == nullptr)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (HRESULT result = writer.start(); FAILED(result))
|
||||
std::wstring pipe_name(L"\\\\.\\pipe\\powertoys_filelocksmithinput_");
|
||||
UUID temp_uuid;
|
||||
wchar_t* uuid_chars = nullptr;
|
||||
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
|
||||
{
|
||||
Trace::InvokedRet(result);
|
||||
return result;
|
||||
auto val = get_last_error_message(GetLastError());
|
||||
Logger::warn(L"UuidCreate can not create guid. {}", val.has_value() ? val.value() : L"");
|
||||
}
|
||||
else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(&uuid_chars)) != RPC_S_OK)
|
||||
{
|
||||
auto val = get_last_error_message(GetLastError());
|
||||
Logger::warn(L"UuidToString can not convert to string. {}", val.has_value() ? val.value() : L"");
|
||||
}
|
||||
|
||||
if (uuid_chars != nullptr)
|
||||
{
|
||||
pipe_name += std::wstring(uuid_chars);
|
||||
RpcStringFree(reinterpret_cast<RPC_WSTR*>(&uuid_chars));
|
||||
uuid_chars = nullptr;
|
||||
}
|
||||
create_pipe_thread = std::thread(&FileLocksmithContextMenuCommand::StartNamedPipeServerAndSendData, this, pipe_name);
|
||||
|
||||
|
||||
std::wstring path = get_module_folderpath(g_hInst);
|
||||
path = path + L"\\PowerToys.FileLocksmithUI.exe";
|
||||
@ -117,26 +136,28 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
DWORD num_items;
|
||||
selection->GetCount(&num_items);
|
||||
|
||||
for (DWORD i = 0; i < num_items; i++)
|
||||
if (hPipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
IShellItem* item;
|
||||
result = selection->GetItemAt(i, &item);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
LPWSTR file_path;
|
||||
result = item->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
// TODO Aggregate items and send to UI
|
||||
writer.add_path(file_path);
|
||||
CoTaskMemFree(file_path);
|
||||
}
|
||||
CAtlFile writePipe(hPipe);
|
||||
|
||||
item->Release();
|
||||
DWORD fileCount = 0;
|
||||
// Gets the list of files currently selected using the IShellItemArray
|
||||
selection->GetCount(&fileCount);
|
||||
// Iterate over the list of files
|
||||
for (DWORD i = 0; i < fileCount; i++)
|
||||
{
|
||||
IShellItem* shellItem;
|
||||
selection->GetItemAt(i, &shellItem);
|
||||
LPWSTR itemName;
|
||||
// Retrieves the entire file system path of the file from its shell item
|
||||
shellItem->GetDisplayName(SIGDN_FILESYSPATH, &itemName);
|
||||
CString fileName(itemName);
|
||||
// File name can't contain '?'
|
||||
fileName.Append(_T("?"));
|
||||
// Write the file path into the input stream for image resizer
|
||||
writePipe.Write(fileName, fileName.GetLength() * sizeof(TCHAR));
|
||||
}
|
||||
writePipe.Close();
|
||||
}
|
||||
|
||||
Trace::InvokedRet(S_OK);
|
||||
@ -166,7 +187,47 @@ protected:
|
||||
ComPtr<IUnknown> m_site;
|
||||
|
||||
private:
|
||||
HRESULT StartNamedPipeServerAndSendData(std::wstring pipe_name)
|
||||
{
|
||||
hPipe = CreateNamedPipe(
|
||||
pipe_name.c_str(),
|
||||
PIPE_ACCESS_DUPLEX |
|
||||
WRITE_DAC,
|
||||
PIPE_TYPE_MESSAGE |
|
||||
PIPE_READMODE_MESSAGE |
|
||||
PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES,
|
||||
BUFSIZE,
|
||||
BUFSIZE,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (hPipe == NULL || hPipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// This call blocks until a client process connects to the pipe
|
||||
BOOL connected = ConnectNamedPipe(hPipe, NULL);
|
||||
if (!connected)
|
||||
{
|
||||
if (GetLastError() == ERROR_PIPE_CONNECTED)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
std::wstring context_menu_caption = GET_RESOURCE_STRING_FALLBACK(IDS_FILE_LOCKSMITH_CONTEXT_MENU_ENTRY, L"Unlock with File Locksmith");
|
||||
std::thread create_pipe_thread;
|
||||
HANDLE hPipe = INVALID_HANDLE_VALUE;
|
||||
};
|
||||
|
||||
CoCreatableClass(FileLocksmithContextMenuCommand)
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
</packages>
|
@ -11,6 +11,7 @@
|
||||
#include <common/themes/icon_helpers.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/HDropIterator.h>
|
||||
|
||||
// Implementations of inherited IUnknown methods
|
||||
|
||||
@ -167,48 +168,13 @@ IFACEMETHODIMP ExplorerCommand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UI
|
||||
IFACEMETHODIMP ExplorerCommand::InvokeCommand(CMINVOKECOMMANDINFO* pici)
|
||||
{
|
||||
Trace::Invoked();
|
||||
ipc::Writer writer;
|
||||
|
||||
if (HRESULT result = writer.start(); FAILED(result))
|
||||
if (HRESULT result = LaunchUI(pici); FAILED(result))
|
||||
{
|
||||
Trace::InvokedRet(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (HRESULT result = LaunchUI(pici, &writer); FAILED(result))
|
||||
{
|
||||
Trace::InvokedRet(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
IShellItemArray* shell_item_array;
|
||||
HRESULT result = SHCreateShellItemArrayFromDataObject(m_data_obj, __uuidof(IShellItemArray), reinterpret_cast<void**>(&shell_item_array));
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
DWORD num_items;
|
||||
shell_item_array->GetCount(&num_items);
|
||||
for (DWORD i = 0; i < num_items; i++)
|
||||
{
|
||||
IShellItem* item;
|
||||
result = shell_item_array->GetItemAt(i, &item);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
LPWSTR file_path;
|
||||
result = item->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
// TODO Aggregate items and send to UI
|
||||
writer.add_path(file_path);
|
||||
CoTaskMemFree(file_path);
|
||||
}
|
||||
|
||||
item->Release();
|
||||
}
|
||||
}
|
||||
|
||||
shell_item_array->Release();
|
||||
}
|
||||
|
||||
Trace::InvokedRet(S_OK);
|
||||
return S_OK;
|
||||
}
|
||||
@ -242,47 +208,97 @@ ExplorerCommand::~ExplorerCommand()
|
||||
--globals::ref_count;
|
||||
}
|
||||
|
||||
HRESULT ExplorerCommand::LaunchUI(CMINVOKECOMMANDINFO* pici, ipc::Writer* writer)
|
||||
HRESULT ExplorerCommand::LaunchUI(CMINVOKECOMMANDINFO* pici)
|
||||
{
|
||||
// Compute exe path
|
||||
std::wstring exe_path = get_module_folderpath(globals::instance);
|
||||
exe_path += L'\\';
|
||||
exe_path += constants::nonlocalizable::FileNameUIExe;
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
STARTUPINFO startupInfo;
|
||||
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
|
||||
startupInfo.cb = sizeof(STARTUPINFO);
|
||||
startupInfo.dwFlags = STARTF_USESHOWWINDOW;
|
||||
|
||||
if (pici)
|
||||
if (FileLocksmithSettings().GetEnabled() &&
|
||||
pici && (IS_INTRESOURCE(pici->lpVerb)) &&
|
||||
(LOWORD(pici->lpVerb) == 0))
|
||||
{
|
||||
startupInfo.wShowWindow = pici->nShow;
|
||||
}
|
||||
else
|
||||
{
|
||||
startupInfo.wShowWindow = SW_SHOWNORMAL;
|
||||
Trace::Invoked();
|
||||
|
||||
// Compute exe path
|
||||
std::wstring exe_path = get_module_folderpath(globals::instance);
|
||||
exe_path += L'\\';
|
||||
exe_path += constants::nonlocalizable::FileNameUIExe;
|
||||
|
||||
// Create an anonymous pipe to stream filenames
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
HANDLE hReadPipe;
|
||||
HANDLE hWritePipe;
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
}
|
||||
if (!SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT, 0))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
}
|
||||
CAtlFile writePipe(hWritePipe);
|
||||
|
||||
CString commandLine;
|
||||
commandLine.Format(_T("\"%s\""), exe_path.data());
|
||||
|
||||
int nSize = commandLine.GetLength() + 1;
|
||||
LPTSTR lpszCommandLine = new TCHAR[nSize];
|
||||
_tcscpy_s(lpszCommandLine, nSize, commandLine);
|
||||
|
||||
STARTUPINFO startupInfo;
|
||||
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
|
||||
startupInfo.cb = sizeof(STARTUPINFO);
|
||||
startupInfo.hStdInput = hReadPipe;
|
||||
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
||||
startupInfo.wShowWindow = static_cast<WORD>(pici->nShow);
|
||||
|
||||
PROCESS_INFORMATION processInformation;
|
||||
|
||||
// Start the resizer
|
||||
CreateProcess(
|
||||
NULL,
|
||||
lpszCommandLine,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&startupInfo,
|
||||
&processInformation);
|
||||
delete[] lpszCommandLine;
|
||||
if (!CloseHandle(processInformation.hProcess))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
}
|
||||
if (!CloseHandle(processInformation.hThread))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (m_data_obj)
|
||||
{
|
||||
// Stream the input files
|
||||
HDropIterator i(m_data_obj);
|
||||
for (i.First(); !i.IsDone(); i.Next())
|
||||
{
|
||||
CString fileName(i.CurrentItem());
|
||||
// File name can't contain '?'
|
||||
fileName.Append(_T("?"));
|
||||
|
||||
writePipe.Write(fileName, fileName.GetLength() * sizeof(TCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
writePipe.Close();
|
||||
}
|
||||
Trace::InvokedRet(hr);
|
||||
|
||||
PROCESS_INFORMATION processInformation;
|
||||
std::wstring command_line = L"\"";
|
||||
command_line += exe_path;
|
||||
command_line += L"\"\0";
|
||||
|
||||
CreateProcessW(
|
||||
NULL,
|
||||
command_line.data(),
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&startupInfo,
|
||||
&processInformation);
|
||||
|
||||
// Discard handles
|
||||
CloseHandle(processInformation.hProcess);
|
||||
CloseHandle(processInformation.hThread);
|
||||
|
||||
return S_OK;
|
||||
return hr;
|
||||
}
|
@ -2,8 +2,6 @@
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "FileLocksmithLib/IPC.h"
|
||||
|
||||
#define EXPLORER_COMMAND_UUID_STR "84d68575-e186-46ad-b0cb-baeb45ee29c0"
|
||||
|
||||
class __declspec(uuid(EXPLORER_COMMAND_UUID_STR)) ExplorerCommand : public IExplorerCommand, public IShellExtInit, public IContextMenu
|
||||
@ -45,7 +43,7 @@ private:
|
||||
HBITMAP m_hbmpIcon = nullptr;
|
||||
|
||||
// Helpers
|
||||
HRESULT LaunchUI(CMINVOKECOMMANDINFO* pici, ipc::Writer* writer);
|
||||
HRESULT LaunchUI(CMINVOKECOMMANDINFO* pici);
|
||||
|
||||
std::atomic<ULONG> m_ref_count = 1;
|
||||
IDataObject* m_data_obj = NULL;
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <ShlObj_core.h>
|
||||
#include <atlbase.h>
|
||||
#include <commctrl.h>
|
||||
#include <atlfile.h>
|
||||
#include <atlstr.h>
|
||||
|
||||
// C++ Standard library
|
||||
#include <atomic>
|
||||
|
@ -65,14 +65,12 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Constants.h" />
|
||||
<ClInclude Include="IPC.h" />
|
||||
<ClInclude Include="Settings.h" />
|
||||
<ClInclude Include="Trace.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="IPC.cpp" />
|
||||
<ClCompile Include="Settings.cpp" />
|
||||
<ClCompile Include="Trace.cpp" />
|
||||
<ClCompile Include="FileLocksmithLib.cpp" />
|
||||
|
@ -27,9 +27,6 @@
|
||||
<ClInclude Include="Settings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IPC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Constants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -41,9 +38,6 @@
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IPC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Settings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1,62 +0,0 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "IPC.h"
|
||||
#include "Constants.h"
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
constexpr DWORD DefaultPipeBufferSize = 8192;
|
||||
constexpr DWORD DefaultPipeTimeoutMillis = 200;
|
||||
|
||||
namespace ipc
|
||||
{
|
||||
Writer::Writer()
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
Writer::~Writer()
|
||||
{
|
||||
finish();
|
||||
}
|
||||
|
||||
HRESULT Writer::start()
|
||||
{
|
||||
std::wstring path = PTSettingsHelper::get_module_save_folder_location(constants::nonlocalizable::PowerToyName);
|
||||
path += L"\\";
|
||||
path += constants::nonlocalizable::LastRunPath;
|
||||
|
||||
try
|
||||
{
|
||||
m_stream = std::ofstream(path);
|
||||
return S_OK;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Writer::add_path(LPCWSTR path)
|
||||
{
|
||||
int length = lstrlenW(path);
|
||||
if (!m_stream.write(reinterpret_cast<const char*>(path), length * sizeof(WCHAR)))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
WCHAR line_break = L'\n';
|
||||
if (!m_stream.write(reinterpret_cast<const char*>(&line_break), sizeof(WCHAR)))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Writer::finish()
|
||||
{
|
||||
add_path(L"");
|
||||
m_stream.close();
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace ipc
|
||||
{
|
||||
class Writer
|
||||
{
|
||||
public:
|
||||
Writer();
|
||||
~Writer();
|
||||
HRESULT start();
|
||||
HRESULT add_path(LPCWSTR path);
|
||||
void finish();
|
||||
HANDLE get_read_handle();
|
||||
|
||||
private:
|
||||
std::ofstream m_stream;
|
||||
};
|
||||
}
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "../FileLocksmithLib/Constants.h"
|
||||
|
||||
#define BUFSIZE 4096 * 4
|
||||
|
||||
namespace FileLocksmith::Interop
|
||||
{
|
||||
public ref struct ProcessResult
|
||||
@ -92,40 +94,79 @@ namespace FileLocksmith::Interop
|
||||
return from_wstring_view(path_cpp);
|
||||
}
|
||||
|
||||
static array<System::String^>^ ReadPathsFromFile()
|
||||
static array<System::String ^>^ ReadPathsFromPipe(System::String^ pipeName)
|
||||
{
|
||||
std::ifstream stream(paths_file());
|
||||
std::wstring pipe = from_system_string(pipeName);
|
||||
HANDLE hStdin;
|
||||
|
||||
std::vector<std::wstring> result_cpp;
|
||||
std::wstring line;
|
||||
|
||||
bool finished = false;
|
||||
|
||||
while (!finished)
|
||||
if (pipe.size() > 0)
|
||||
{
|
||||
WCHAR ch{};
|
||||
// We have to read data like this
|
||||
if (!stream.read(reinterpret_cast<char*>(&ch), 2))
|
||||
while (1)
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
else if (ch == L'\n')
|
||||
{
|
||||
if (line.empty())
|
||||
hStdin = CreateFile(
|
||||
pipe.c_str(), // pipe name
|
||||
GENERIC_READ | GENERIC_WRITE, // read and write
|
||||
0, // no sharing
|
||||
NULL, // default security attributes
|
||||
OPEN_EXISTING, // opens existing pipe
|
||||
0, // default attributes
|
||||
NULL); // no template file
|
||||
|
||||
// Break if the pipe handle is valid.
|
||||
if (hStdin != INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
// Exit if an error other than ERROR_PIPE_BUSY occurs.
|
||||
auto error = GetLastError();
|
||||
if (error != ERROR_PIPE_BUSY)
|
||||
{
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
if (!WaitNamedPipe(pipe.c_str(), 3))
|
||||
{
|
||||
result_cpp.push_back(line);
|
||||
line = {};
|
||||
printf("Could not open pipe: 20 second wait timed out.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
line += ch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
}
|
||||
|
||||
if (hStdin == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
BOOL bSuccess;
|
||||
WCHAR chBuf[BUFSIZE];
|
||||
DWORD dwRead;
|
||||
|
||||
std::vector<std::wstring> result_cpp;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Read from standard input and stop on error or no data.
|
||||
bSuccess = ReadFile(hStdin, chBuf, BUFSIZE * sizeof(wchar_t), &dwRead, NULL);
|
||||
|
||||
if (!bSuccess || dwRead == 0)
|
||||
break;
|
||||
|
||||
std::wstring inputBatch{ chBuf, dwRead / sizeof(wchar_t) };
|
||||
|
||||
std::wstringstream ss(inputBatch);
|
||||
std::wstring item;
|
||||
wchar_t delimiter = '?';
|
||||
while (std::getline(ss, item, delimiter))
|
||||
{
|
||||
result_cpp.push_back(item);
|
||||
}
|
||||
|
||||
if (!bSuccess)
|
||||
break;
|
||||
}
|
||||
CloseHandle(hStdin);
|
||||
|
||||
auto result = gcnew array<System::String ^>(static_cast<int>(result_cpp.size()));
|
||||
for (int i = 0; i < result->Length; i++)
|
||||
|
@ -17,3 +17,4 @@
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
@ -9,6 +9,7 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using FileLocksmith.Interop;
|
||||
@ -78,7 +79,11 @@ namespace PowerToys.FileLocksmithUI.ViewModels
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
paths = NativeMethods.ReadPathsFromFile();
|
||||
var args = Environment.GetCommandLineArgs();
|
||||
var pipeName = args.Where(s => s.Contains("\\\\.\\pipe\\")).FirstOrDefault();
|
||||
|
||||
MessageBox.Show(args.ToString());
|
||||
paths = NativeMethods.ReadPathsFromPipe(pipeName);
|
||||
Logger.LogInfo($"Starting FileLocksmith with {paths.Length} files selected.");
|
||||
LoadProcessesCommand = new AsyncRelayCommand(LoadProcessesAsync);
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ HRESULT CPowerRenameMenu::RunPowerRename(CMINVOKECOMMANDINFO* pici, IShellItemAr
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0))
|
||||
if (!CreatePipe(&hReadPipe, &hWritePipe, NULL, 0))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
return hr;
|
||||
|
Loading…
Reference in New Issue
Block a user