diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index cc620ed98f..94fb0a8903 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -742,7 +742,7 @@ IDD
IDesktop
IDirect
idl
-IDLIST
+idlist
IDOn
IDR
idx
diff --git a/installer/PowerToysSetup/PowerRename.wxs b/installer/PowerToysSetup/PowerRename.wxs
index 6239033894..56de970b29 100644
--- a/installer/PowerToysSetup/PowerRename.wxs
+++ b/installer/PowerToysSetup/PowerRename.wxs
@@ -28,6 +28,9 @@
+
+
+
diff --git a/src/modules/powerrename/PowerRenameContextMenu/dllmain.cpp b/src/modules/powerrename/PowerRenameContextMenu/dllmain.cpp
index 6bc8b33ebb..028dc2c31b 100644
--- a/src/modules/powerrename/PowerRenameContextMenu/dllmain.cpp
+++ b/src/modules/powerrename/PowerRenameContextMenu/dllmain.cpp
@@ -93,12 +93,6 @@ public:
{
*cmdState = ECS_ENABLED;
- // We've observed that it's possible that a null gets passed instead of an empty array. Just don't show the context menu in this case.
- if (nullptr == selection) {
- *cmdState = ECS_HIDDEN;
- return S_OK;
- }
-
if (!CSettingsInstance().GetEnabled())
{
*cmdState = ECS_HIDDEN;
@@ -112,6 +106,12 @@ public:
return S_OK;
}
+ // When right clicking directory background, selection is empty. This prevents checking if there
+ // are renamable items, but internal PowerRename logic will prevent renaming non-renamable items anyway.
+ if (nullptr == selection) {
+ return S_OK;
+ }
+
// Check if at least one of the selected items is actually renamable.
if (!ShellItemArrayContainsRenamableItem(selection))
{
diff --git a/src/modules/powerrename/dll/PowerRenameExt.cpp b/src/modules/powerrename/dll/PowerRenameExt.cpp
index b4012a1899..95b42089a4 100644
--- a/src/modules/powerrename/dll/PowerRenameExt.cpp
+++ b/src/modules/powerrename/dll/PowerRenameExt.cpp
@@ -46,14 +46,26 @@ HRESULT CPowerRenameMenu::s_CreateInstance(_In_opt_ IUnknown*, _In_ REFIID riid,
}
// IShellExtInit
-HRESULT CPowerRenameMenu::Initialize(_In_opt_ PCIDLIST_ABSOLUTE, _In_ IDataObject* pdtobj, HKEY)
+HRESULT CPowerRenameMenu::Initialize(_In_opt_ PCIDLIST_ABSOLUTE idlist, _In_ IDataObject* pdtobj, HKEY)
{
// Check if we have disabled ourselves
if (!CSettingsInstance().GetEnabled())
return E_FAIL;
// Cache the data object to be used later
- m_spdo = pdtobj;
+ if (idlist != NULL)
+ {
+ CComPtr spsia;
+ if (SUCCEEDED(SHCreateShellItemArrayFromIDLists(1, &idlist, &spsia)) && spsia != NULL)
+ {
+ spsia->BindToHandler(NULL, BHID_DataObject, IID_IDataObject, reinterpret_cast(&m_spdo));
+ }
+ }
+ else
+ {
+ m_spdo = pdtobj;
+ }
+
return S_OK;
}
@@ -124,7 +136,7 @@ HRESULT CPowerRenameMenu::RunPowerRename(CMINVOKECOMMANDINFO* pici, IShellItemAr
HRESULT hr = E_FAIL;
if (CSettingsInstance().GetEnabled() &&
- (IS_INTRESOURCE(pici->lpVerb)) &&
+ pici && (IS_INTRESOURCE(pici->lpVerb)) &&
(LOWORD(pici->lpVerb) == 0))
{
Trace::Invoked();
@@ -163,14 +175,7 @@ HRESULT CPowerRenameMenu::RunPowerRename(CMINVOKECOMMANDINFO* pici, IShellItemAr
startupInfo.cb = sizeof(STARTUPINFO);
startupInfo.hStdInput = hReadPipe;
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
- if (pici)
- {
- startupInfo.wShowWindow = static_cast(pici->nShow);
- }
- else
- {
- startupInfo.wShowWindow = SW_SHOWNORMAL;
- }
+ startupInfo.wShowWindow = static_cast(pici->nShow);
PROCESS_INFORMATION processInformation;
@@ -201,15 +206,18 @@ HRESULT CPowerRenameMenu::RunPowerRename(CMINVOKECOMMANDINFO* pici, IShellItemAr
// psiItemArray is NULL if called from InvokeCommand. This part is used for the MSI installer. It is not NULL if it is called from Invoke (MSIX).
if (!psiItemArray)
{
- // Stream the input files
- HDropIterator i(m_spdo);
- for (i.First(); !i.IsDone(); i.Next())
+ if (m_spdo)
{
- CString fileName(i.CurrentItem());
- // File name can't contain '?'
- fileName.Append(_T("?"));
+ // Stream the input files
+ HDropIterator i(m_spdo);
+ 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.Write(fileName, fileName.GetLength() * sizeof(TCHAR));
+ }
}
}
else
diff --git a/src/modules/powerrename/lib/Helpers.cpp b/src/modules/powerrename/lib/Helpers.cpp
index 8ef61366b1..ecd823e4d7 100644
--- a/src/modules/powerrename/lib/Helpers.cpp
+++ b/src/modules/powerrename/lib/Helpers.cpp
@@ -551,7 +551,7 @@ bool DataObjectContainsRenamableItem(_In_ IUnknown* dataSource)
{
bool hasRenamable = false;
CComPtr spsia;
- if (SUCCEEDED(GetShellItemArrayFromDataObject(dataSource, &spsia)))
+ if (dataSource && SUCCEEDED(GetShellItemArrayFromDataObject(dataSource, &spsia)))
{
CComPtr spesi;
if (SUCCEEDED(spsia->EnumItems(&spesi)))