Switch to named pipes

Unregister package on uninstall
Remove unneeded files
Cleanup
This commit is contained in:
Stefan Markovic
2022-06-07 10:23:01 +02:00
parent 0fbb14cb95
commit c6d8ac5834
13 changed files with 514 additions and 243 deletions

View File

@@ -221,8 +221,11 @@
<Custom Action="UnApplyModulesRegistryChangeSets" Before="RemoveFiles">
Installed AND (REMOVE="ALL")
</Custom>
<Custom Action="UnRegisterContextMenuPackages" Before="RemoveFiles">
Installed AND (REMOVE="ALL")
</Custom>
<!-- TODO: Use to activate embedded MSIX -->
<!-- TODO: Use to activate embedded MSIX -->
<!--<Custom Action="UninstallEmbeddedMSIXTask" After="InstallFinalize">
Installed AND (REMOVE="ALL")
</Custom>-->
@@ -369,8 +372,16 @@
DllEntry="UnApplyModulesRegistryChangeSetsCA"
/>
<CustomAction Id="UnRegisterContextMenuPackages"
Return="ignore"
Impersonate="yes"
Execute="deferred"
BinaryKey="PTCustomActions"
DllEntry="UnRegisterContextMenuPackagesCA"
/>
<!-- Close 'PowerToys.exe' before uninstall-->
<!-- Close 'PowerToys.exe' before uninstall-->
<Property Id="MSIRESTARTMANAGERCONTROL" Value="DisableShutdown" />
<Property Id="MSIFASTINSTALL" Value="DisableShutdown" />
<util:CloseApplication CloseMessage="yes" Target="PowerToys.exe" ElevatedCloseMessage="yes" RebootPrompt="no" TerminateProcess="0" />

View File

@@ -11,6 +11,10 @@
#include "../../src/common/updating/installer.h"
#include "../../src/common/version/version.h"
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Management.Deployment.h>
using namespace std;
HINSTANCE DLL_HANDLE = nullptr;
@@ -912,7 +916,7 @@ LExit:
if (!SUCCEEDED(hr))
{
PMSIHANDLE hRecord = MsiCreateRecord(0);
MsiRecordSetString(hRecord, 0, TEXT("Filed to iminstall virtual camera driver"));
MsiRecordSetString(hRecord, 0, TEXT("Failed to uninstall virtual camera driver"));
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
}
@@ -920,6 +924,78 @@ LExit:
return WcaFinalize(er);
}
UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall)
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Management::Deployment;
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "UnRegisterContextMenuPackagesCA"); // original func name is too long
try
{
// Packages to unregister
const std::vector<std::wstring> packagesToRemoveDisplayName{ { L"PowerRenameContextMenu" } };
PackageManager packageManager;
for (auto const& package : packageManager.FindPackages())
{
const auto& packageFullName = std::wstring{ package.Id().FullName() };
for (const auto& packageToRemove : packagesToRemoveDisplayName)
{
if (packageFullName.contains(packageToRemove))
{
auto deploymentOperation{ packageManager.RemovePackageAsync(packageFullName) };
deploymentOperation.get();
// Check the status of the operation
if (deploymentOperation.Status() == AsyncStatus::Error)
{
auto deploymentResult{ deploymentOperation.GetResults() };
auto errorCode = deploymentOperation.ErrorCode();
auto errorText = deploymentResult.ErrorText();
Logger::error(L"Unregister {} package failed. ErrorCode: {}, ErrorText: {}", packageFullName, std::to_wstring(errorCode), errorText);
er = ERROR_INSTALL_FAILURE;
}
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
{
Logger::error(L"Unregister {} package canceled.", packageFullName);
er = ERROR_INSTALL_FAILURE;
}
else if (deploymentOperation.Status() == AsyncStatus::Completed)
{
Logger::info(L"Unregister {} package completed.", packageFullName);
}
else
{
Logger::debug(L"Unregister {} package started.", packageFullName);
}
}
}
}
}
catch (std::exception e)
{
std::string errorMessage{ "Exception thrown while trying to unregister sparse packages: " };
errorMessage += e.what();
Logger::error(errorMessage);
er = ERROR_INSTALL_FAILURE;
}
er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er;
return WcaFinalize(er);
}
UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;

View File

@@ -14,10 +14,10 @@ EXPORTS
TelemetryLogRepairCancelCA
TelemetryLogRepairFailCA
TerminateProcessesCA
TerminateProcessesCA
CertifyVirtualCameraDriverCA
InstallVirtualCameraDriverCA
InstallEmbeddedMSIXCA
UnApplyModulesRegistryChangeSetsCA
UninstallVirtualCameraDriverCA
UnRegisterContextMenuPackagesCA
UninstallEmbeddedMSIXCA

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\wix.props"
Condition="Exists('..\wix.props')" />
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" />
<Import Project="..\wix.props" Condition="Exists('..\wix.props')" />
<PropertyGroup Label="Globals">
<ProjectGuid>{32f3882b-f2d6-4586-b5ed-11e39e522bd3}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
@@ -43,7 +43,6 @@
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\..\src\common\Telemetry;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>inc;..\..\src\;..\..\src\common\Telemetry;telemetry;$(WixSdkPath)VS2017\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -56,7 +55,6 @@
<ModuleDefinitionFile>CustomAction.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -65,7 +63,6 @@
<AdditionalLibraryDirectories>$(WixSdkPath)VS2017\lib\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
@@ -127,5 +124,14 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\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.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

View File

@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.220418.1" targetFramework="native" />
</packages>

View File

@@ -37,6 +37,12 @@
<Extensions>
<desktop4:Extension Category="windows.fileExplorerContextMenus">
<desktop4:FileExplorerContextMenus>
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
</desktop5:ItemType>
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
</desktop5:ItemType>
<desktop5:ItemType Type="*">
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
</desktop5:ItemType>

View File

@@ -1,22 +0,0 @@
// PowerRenameContextMenu.cpp : Defines the exported functions for the DLL.
//
#include "pch.h"
#include "framework.h"
#include "PowerRenameContextMenu.h"
// This is an example of an exported variable
POWERRENAMECONTEXTMENU_API int nPowerRenameContextMenu=0;
// This is an example of an exported function.
POWERRENAMECONTEXTMENU_API int fnPowerRenameContextMenu(void)
{
return 0;
}
// This is the constructor of a class that has been exported.
CPowerRenameContextMenu::CPowerRenameContextMenu()
{
return;
}

View File

@@ -1,22 +0,0 @@
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the POWERRENAMECONTEXTMENU_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// POWERRENAMECONTEXTMENU_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef POWERRENAMECONTEXTMENU_EXPORTS
#define POWERRENAMECONTEXTMENU_API __declspec(dllexport)
#else
#define POWERRENAMECONTEXTMENU_API __declspec(dllimport)
#endif
// This class is exported from the dll
class POWERRENAMECONTEXTMENU_API CPowerRenameContextMenu {
public:
CPowerRenameContextMenu(void);
// TODO: add your methods here.
};
extern POWERRENAMECONTEXTMENU_API int nPowerRenameContextMenu;
POWERRENAMECONTEXTMENU_API int fnPowerRenameContextMenu(void);

View File

@@ -84,7 +84,6 @@ MakeAppx.exe pack /d . /p $(OutDir)PowerRenameContextMenuPackage.msix /nv</Comma
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="PowerRenameContextMenu.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
@@ -92,7 +91,6 @@ MakeAppx.exe pack /d . /p $(OutDir)PowerRenameContextMenuPackage.msix /nv</Comma
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="PowerRenameContextMenu.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@@ -18,9 +18,6 @@
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PowerRenameContextMenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -29,9 +26,6 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="PowerRenameContextMenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -41,6 +35,177 @@
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="PowerRenameUI.ico">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PowerRenameContextMenu.rc">
@@ -48,9 +213,6 @@
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="PowerRenameUI.ico">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\BadgeLogo.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
@@ -543,12 +705,6 @@
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\BadgeLogo.scale-100.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\BadgeLogo.scale-125.png">
<Filter>Resource Files</Filter>
</Image>

View File

@@ -22,12 +22,15 @@
#include <trace.h>
#include <mutex>
#include <thread>
#include <shellapi.h>
using namespace Microsoft::WRL;
HINSTANCE g_hInst = 0;
#define BUFSIZE 4096 * 4
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
@@ -94,34 +97,11 @@ public:
IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept
try
{
HWND parent = nullptr;
if (m_site)
{
ComPtr<IOleWindow> oleWindow;
RETURN_IF_FAILED(m_site.As(&oleWindow));
RETURN_IF_FAILED(oleWindow->GetWindow(&parent));
}
std::wostringstream title;
title << Title();
if (selection)
{
DWORD count;
RETURN_IF_FAILED(selection->GetCount(&count));
title << L" (" << count << L" selected items)";
RunPowerRename(selection);
}
else
{
title << L"(no selected items)";
}
std::filesystem::path modulePath{ wil::GetModuleFileNameW<std::wstring>() };
std::wstring path = get_module_folderpath(g_hInst);
path = path + L"\\PowerToys.PowerRename.exe";
std::wstring iconResourcePath = get_module_filename();
MessageBox(parent, iconResourcePath.c_str(), iconResourcePath.c_str(), MB_OK);
RunPowerRename(selection);
return S_OK;
}
CATCH_RETURN();
@@ -149,111 +129,110 @@ protected:
ComPtr<IUnknown> m_site;
private:
HRESULT RunPowerRename(IShellItemArray* psiItemArray)
HRESULT StartNamedPipeServerAndSendData(std::wstring pipe_name, IShellItemArray* psiItemArray)
{
HRESULT hr = E_FAIL;
HWND parent = nullptr;
if (m_site)
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)
{
ComPtr<IOleWindow> oleWindow;
RETURN_IF_FAILED(m_site.As(&oleWindow));
RETURN_IF_FAILED(oleWindow->GetWindow(&parent));
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;
}
HRESULT RunPowerRename(IShellItemArray* psiItemArray)
{
if (CSettingsInstance().GetEnabled())
{
Trace::Invoked();
// Set the application path based on the location of the dll
std::wstring path = get_module_folderpath(g_hInst);
path = path + L"\\PowerToys.PowerRename.exe";
LPTSTR lpApplicationName = (LPTSTR)path.c_str();
// 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))
std::wstring pipe_name(L"\\\\.\\pipe\\powertoys_powerrenameinput_");
UUID temp_uuid;
wchar_t* uuid_chars = nullptr;
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidCreate can not create guid. {}", val.has_value() ? val.value() : L"");
}
if (!SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT, 0))
else if (UuidToString(&temp_uuid, (RPC_WSTR*)&uuid_chars) != RPC_S_OK)
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
CAtlFile writePipe(hWritePipe);
CString commandLine;
commandLine.Format(_T("\"%s\""), lpApplicationName);
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 = SW_SHOWNORMAL;
PROCESS_INFORMATION processInformation;
// Start the resizer
CreateProcess(
NULL,
lpszCommandLine,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&startupInfo,
&processInformation);
RunNonElevatedEx(path.c_str(), {}, get_module_folderpath(g_hInst));
delete[] lpszCommandLine;
if (!CloseHandle(processInformation.hProcess))
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
if (!CloseHandle(processInformation.hThread))
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidToString can not convert to string. {}", val.has_value() ? val.value() : L"");
}
//m_pdtobj will be NULL when invoked from the MSIX build as Initialize is never called (IShellExtInit functions aren't called in case of MSIX).
DWORD fileCount = 0;
// Gets the list of files currently selected using the IShellItemArray
psiItemArray->GetCount(&fileCount);
// Iterate over the list of files
for (DWORD i = 0; i < fileCount; i++)
if (uuid_chars != nullptr)
{
IShellItem* shellItem;
psiItemArray->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));
pipe_name += std::wstring(uuid_chars);
RpcStringFree((RPC_WSTR*)&uuid_chars);
uuid_chars = nullptr;
}
create_pipe_thread = std::thread(&PowerRenameContextMenuCommand::StartNamedPipeServerAndSendData, this, pipe_name, psiItemArray);
RunNonElevatedEx(path.c_str(), pipe_name, get_module_folderpath(g_hInst));
create_pipe_thread.join();
if (hPipe != INVALID_HANDLE_VALUE)
{
CAtlFile writePipe(hPipe);
DWORD fileCount = 0;
// Gets the list of files currently selected using the IShellItemArray
psiItemArray->GetCount(&fileCount);
// Iterate over the list of files
for (DWORD i = 0; i < fileCount; i++)
{
IShellItem* shellItem;
psiItemArray->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();
}
writePipe.Close();
}
Trace::InvokedRet(hr);
Trace::InvokedRet(S_OK);
return hr;
return S_OK;
}
std::thread create_pipe_thread;
HANDLE hPipe = INVALID_HANDLE_VALUE;
std::wstring app_name = L"PowerRename";
};

View File

@@ -53,15 +53,61 @@ void App::OnLaunched(LaunchActivatedEventArgs const&)
{
LoggerHelpers::init_logger(moduleName, L"", LogSettings::powerRenameLoggerName);
#define BUFSIZE 4096 * 4
auto args = std::wstring{ GetCommandLine() };
size_t pos{ args.rfind(' ') };
std::wstring pipe_name;
if (pos != std::wstring::npos)
{
pipe_name = args.substr(pos + 1);
}
HANDLE hStdin;
if (pipe_name.size() > 0)
{
while (1)
{
hStdin = CreateFile(
pipe_name.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)
{
break;
}
if (!WaitNamedPipe(pipe_name.c_str(), 3))
{
printf("Could not open pipe: 20 second wait timed out.");
}
}
}
else
{
hStdin = GetStdHandle(STD_INPUT_HANDLE);
}
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE)
{
Logger::error(L"Invalid input handle.");
ExitProcess(1);
}
#define BUFSIZE 4096 * 4
BOOL bSuccess;
WCHAR chBuf[BUFSIZE];
DWORD dwRead;
@@ -86,6 +132,7 @@ void App::OnLaunched(LaunchActivatedEventArgs const&)
if (!bSuccess)
break;
}
CloseHandle(hStdin);
Logger::debug(L"Starting PowerRename with {} files selected", g_files.size());

View File

@@ -10,13 +10,103 @@
#include <common/utils/resources.h>
#include "Generated Files/resource.h"
#include <atomic>
#include <versionhelpers.h>
#include <dll/PowerRenameConstants.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Management.Deployment.h>
#include <bcrypt.h>
std::atomic<DWORD> g_dwModuleRefCount = 0;
HINSTANCE g_hInst = 0;
#define STATUS_SUCCESS 0x00000000
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
namespace
{
RTL_OSVERSIONINFOW GetRealOSVersion()
{
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
if (hMod)
{
RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
if (fxPtr != nullptr)
{
RTL_OSVERSIONINFOW info = { 0 };
info.dwOSVersionInfoSize = sizeof(info);
if (STATUS_SUCCESS == fxPtr(&info))
{
return info;
}
}
}
RTL_OSVERSIONINFOW info = { 0 };
return info;
}
bool IsWindows11()
{
auto info = GetRealOSVersion();
return info.dwMajorVersion >= 10 && info.dwBuildNumber >= 22000;
}
bool RegisterSparsePackage(std::wstring externalLocation, std::wstring sparsePkgPath)
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Management::Deployment;
try
{
Uri externalUri{ externalLocation };
Uri packageUri{ sparsePkgPath };
PackageManager packageManager;
// Declare use of an external location
AddPackageOptions options;
options.ExternalLocationUri(externalUri);
IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options);
deploymentOperation.get();
// Check the status of the operation
if (deploymentOperation.Status() == AsyncStatus::Error)
{
auto deploymentResult{ deploymentOperation.GetResults() };
auto errorCode = deploymentOperation.ErrorCode();
auto errorText = deploymentResult.ErrorText();
Logger::error(L"Register PowerRenameContextMenu package failed. ErrorCode: {}, ErrorText: {}", std::to_wstring(errorCode), errorText);
return false;
}
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
{
Logger::error(L"Register PowerRenameContextMenu package canceled.");
return false;
}
else if (deploymentOperation.Status() == AsyncStatus::Completed)
{
Logger::info(L"Register PowerRenameContextMenu package completed.");
}
else
{
Logger::debug(L"Register PowerRenameContextMenu package started.");
}
return true;
}
catch (std::exception e)
{
std::string errorMessage{ "Exception thrown while trying to register PowerRenameContextMenu package: " };
errorMessage += e.what();
Logger::error(errorMessage);
return false;
}
}
}
class CPowerRenameClassFactory : public IClassFactory
{
public:
@@ -164,64 +254,6 @@ private:
std::wstring app_key;
public:
bool registerSparsePackage(std::wstring externalLocation, std::wstring sparsePkgPath)
{
bool registration = false;
try
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Management::Deployment;
Uri externalUri{ externalLocation };
Uri packageUri{ sparsePkgPath };
// Console.WriteLine("exe Location {0}", externalLocation);
// Console.WriteLine("msix Address {0}", sparsePkgPath);
// Console.WriteLine(" exe Uri {0}", externalUri);
// Console.WriteLine(" msix Uri {0}", packageUri);
PackageManager packageManager;
// Declare use of an external location
AddPackageOptions options;
options.ExternalLocationUri(externalUri);
IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options);
//IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageAsync(packageUri, nullptr, DeploymentOptions::None);
deploymentOperation.get();
int returnValue = 0;
// Check the status of the operation
if (deploymentOperation.Status() == AsyncStatus::Error)
{
auto deploymentResult{ deploymentOperation.GetResults() };
auto errorCode = deploymentOperation.ErrorCode();
auto errorText = deploymentResult.ErrorText().c_str();
returnValue = 1;
}
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
{
returnValue = 1;
}
else if (deploymentOperation.Status() == AsyncStatus::Completed)
{
returnValue = 1;
}
else
{
returnValue = 1;
}
return returnValue;
// Other progress and error-handling code omitted for brevity...
}
catch (...)
{
}
return true;
}
// Return the localized display name of the powertoy
@@ -239,13 +271,16 @@ public:
// Enable the powertoy
virtual void enable()
{
std::wstring path = get_module_folderpath(g_hInst);
std::wstring packageUri = path + L"\\PowerRenameContextMenuPackage.msix";
//std::wstring externalLocation = L"C:\\Users\\stefan\\Projects\\PowerToys\\x64\\Debug\\modules\\PowerRename";
//std::wstring packageUri = L"C:\\Users\\stefan\\Projects\\PowerToys\\src\\modules\\powerrename\\PowerRenameContextMenu\\MyPackage.msix";
registerSparsePackage(path, packageUri);
Logger::info(L"PowerRename enabled");
m_enabled = true;
if (IsWindows11())
{
std::wstring path = get_module_folderpath(g_hInst);
std::wstring packageUri = path + L"\\PowerRenameContextMenuPackage.msix";
RegisterSparsePackage(path, packageUri);
}
save_settings();
}