* Ensure rename dialog is centered

* Ensure children are renamed before parent items
* Add settings handler
* Replace old text referencing smart rename with power rename
This commit is contained in:
Chris Davis
2019-11-11 11:00:42 -08:00
parent 997ea3a2f5
commit 1e89054897
21 changed files with 1042 additions and 281 deletions

View File

@@ -4,6 +4,8 @@
#include <PowerRenameItem.h> #include <PowerRenameItem.h>
#include <PowerRenameManager.h> #include <PowerRenameManager.h>
#include <trace.h> #include <trace.h>
#include <Helpers.h>
#include <Settings.h>
#include "resource.h" #include "resource.h"
extern HINSTANCE g_hInst; extern HINSTANCE g_hInst;
@@ -14,24 +16,6 @@ struct InvokeStruct
IStream* pstrm; IStream* pstrm;
}; };
const wchar_t powerRenameRegPath[] = L"Software\\Microsoft\\PowerRename";
const wchar_t powerRenameRegEnabledName[] = L"Enabled";
bool CPowerRenameMenu::IsEnabled()
{
DWORD type = REG_DWORD;
DWORD dwEnabled = 0;
DWORD cb = sizeof(dwEnabled);
SHGetValue(HKEY_CURRENT_USER, powerRenameRegPath, powerRenameRegEnabledName, &type, &dwEnabled, &cb);
return (dwEnabled == 0) ? false : true;
}
bool CPowerRenameMenu::SetEnabled(_In_ bool enabled)
{
DWORD dwEnabled = enabled ? 1 : 0;
return SUCCEEDED(HRESULT_FROM_WIN32(SHSetValueW(HKEY_CURRENT_USER, powerRenameRegPath, powerRenameRegEnabledName, REG_DWORD, &dwEnabled, sizeof(dwEnabled))));
}
CPowerRenameMenu::CPowerRenameMenu() CPowerRenameMenu::CPowerRenameMenu()
{ {
DllAddRef(); DllAddRef();
@@ -60,7 +44,7 @@ HRESULT CPowerRenameMenu::s_CreateInstance(_In_opt_ IUnknown*, _In_ REFIID riid,
HRESULT CPowerRenameMenu::Initialize(_In_opt_ PCIDLIST_ABSOLUTE, _In_ IDataObject *pdtobj, HKEY) HRESULT CPowerRenameMenu::Initialize(_In_opt_ PCIDLIST_ABSOLUTE, _In_ IDataObject *pdtobj, HKEY)
{ {
// Check if we have disabled ourselves // Check if we have disabled ourselves
if (!IsEnabled()) if (!CSettings::GetEnabled())
return E_FAIL; return E_FAIL;
// Cache the data object to be used later // Cache the data object to be used later
@@ -72,7 +56,11 @@ HRESULT CPowerRenameMenu::Initialize(_In_opt_ PCIDLIST_ABSOLUTE, _In_ IDataObjec
HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirst, UINT, UINT uFlags) HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirst, UINT, UINT uFlags)
{ {
// Check if we have disabled ourselves // Check if we have disabled ourselves
if (!IsEnabled()) if (!CSettings::GetEnabled())
return E_FAIL;
// Check if we should only be on the extended context menu
if (CSettings::GetExtendedContextMenuOnly() && (!(uFlags & CMF_EXTENDEDVERBS)))
return E_FAIL; return E_FAIL;
HRESULT hr = E_UNEXPECTED; HRESULT hr = E_UNEXPECTED;
@@ -80,8 +68,34 @@ HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirs
{ {
wchar_t menuName[64] = { 0 }; wchar_t menuName[64] = { 0 };
LoadString(g_hInst, IDS_POWERRENAME, menuName, ARRAYSIZE(menuName)); LoadString(g_hInst, IDS_POWERRENAME, menuName, ARRAYSIZE(menuName));
InsertMenu(hMenu, index, MF_STRING | MF_BYPOSITION, uIDFirst++, menuName);
hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 1); MENUITEMINFO mii;
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.wID = uIDFirst++;
mii.fType = MFT_STRING;
mii.dwTypeData = (PWSTR)menuName;
mii.fState = MFS_ENABLED;
if (CSettings::GetShowIconOnMenu())
{
HICON hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_RENAME), IMAGE_ICON, 16, 16, 0);
if (hIcon)
{
mii.fMask |= MIIM_BITMAP;
mii.hbmpItem = CreateBitmapFromIcon(hIcon);
DestroyIcon(hIcon);
}
}
if (!InsertMenuItem(hMenu, index, TRUE, &mii))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 1);
}
} }
return hr; return hr;
@@ -91,7 +105,7 @@ HRESULT CPowerRenameMenu::InvokeCommand(_In_ LPCMINVOKECOMMANDINFO pici)
{ {
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
if (IsEnabled() && if (CSettings::GetEnabled() &&
(IS_INTRESOURCE(pici->lpVerb)) && (IS_INTRESOURCE(pici->lpVerb)) &&
(LOWORD(pici->lpVerb) == 0)) (LOWORD(pici->lpVerb) == 0))
{ {
@@ -129,7 +143,7 @@ DWORD WINAPI CPowerRenameMenu::s_PowerRenameUIThreadProc(_In_ void* pData)
HRESULT hr = CoGetInterfaceAndReleaseStream(pInvokeData->pstrm, IID_PPV_ARGS(&spdo)); HRESULT hr = CoGetInterfaceAndReleaseStream(pInvokeData->pstrm, IID_PPV_ARGS(&spdo));
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// Create the smart rename manager // Create the rename manager
CComPtr<IPowerRenameManager> spsrm; CComPtr<IPowerRenameManager> spsrm;
hr = CPowerRenameManager::s_CreateInstance(&spsrm); hr = CPowerRenameManager::s_CreateInstance(&spsrm);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@@ -140,10 +154,10 @@ DWORD WINAPI CPowerRenameMenu::s_PowerRenameUIThreadProc(_In_ void* pData)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// Pass the factory to the manager // Pass the factory to the manager
hr = spsrm->put_smartRenameItemFactory(spsrif); hr = spsrm->put_renameItemFactory(spsrif);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// Create the smart rename UI instance and pass the smart rename manager // Create the rename UI instance and pass the rename manager
CComPtr<IPowerRenameUI> spsrui; CComPtr<IPowerRenameUI> spsrui;
hr = CPowerRenameUI::s_CreateInstance(spsrm, spdo, false, &spsrui); hr = CPowerRenameUI::s_CreateInstance(spsrm, spdo, false, &spsrui);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))

View File

@@ -1,6 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "PowerRenameExt.h" #include "PowerRenameExt.h"
#include <interface/powertoy_module_interface.h> #include <interface/powertoy_module_interface.h>
#include <settings.h>
#include <trace.h> #include <trace.h>
#include <common/settings_objects.h> #include <common/settings_objects.h>
@@ -9,10 +10,10 @@ HINSTANCE g_hInst = 0;
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
class CSmartRenameClassFactory : public IClassFactory class CPowerRenameClassFactory : public IClassFactory
{ {
public: public:
CSmartRenameClassFactory(_In_ REFCLSID clsid) : CPowerRenameClassFactory(_In_ REFCLSID clsid) :
m_refCount(1), m_refCount(1),
m_clsid(clsid) m_clsid(clsid)
{ {
@@ -24,7 +25,7 @@ public:
{ {
static const QITAB qit[] = static const QITAB qit[] =
{ {
QITABENT(CSmartRenameClassFactory, IClassFactory), QITABENT(CPowerRenameClassFactory, IClassFactory),
{ 0 } { 0 }
}; };
return QISearch(this, qit, riid, ppv); return QISearch(this, qit, riid, ppv);
@@ -82,7 +83,7 @@ public:
} }
private: private:
~CSmartRenameClassFactory() ~CPowerRenameClassFactory()
{ {
DllRelease(); DllRelease();
} }
@@ -122,7 +123,7 @@ STDAPI DllGetClassObject(_In_ REFCLSID clsid, _In_ REFIID riid, _Outptr_ void **
{ {
*ppv = NULL; *ppv = NULL;
HRESULT hr = E_OUTOFMEMORY; HRESULT hr = E_OUTOFMEMORY;
CSmartRenameClassFactory *pClassFactory = new CSmartRenameClassFactory(clsid); CPowerRenameClassFactory *pClassFactory = new CPowerRenameClassFactory(clsid);
if (pClassFactory) if (pClassFactory)
{ {
hr = pClassFactory->QueryInterface(riid, ppv); hr = pClassFactory->QueryInterface(riid, ppv);
@@ -235,13 +236,13 @@ public:
void init_settings() void init_settings()
{ {
m_enabled = CPowerRenameMenu::IsEnabled(); m_enabled = CSettings::GetEnabled();
Trace::EnablePowerRename(m_enabled); Trace::EnablePowerRename(m_enabled);
} }
void save_settings() void save_settings()
{ {
CPowerRenameMenu::SetEnabled(m_enabled); CSettings::SetEnabled(m_enabled);
Trace::EnablePowerRename(m_enabled); Trace::EnablePowerRename(m_enabled);
} }

View File

@@ -1,4 +1,5 @@
#define IDS_POWERRENAME 801 #define IDS_POWERRENAME 801
#define IDI_RENAME 132
// Next default values for new objects // Next default values for new objects
// //

View File

@@ -25,6 +25,71 @@ HRESULT GetIconIndexFromPath(_In_ PCWSTR path, _Out_ int* index)
return hr; return hr;
} }
HBITMAP CreateBitmapFromIcon(_In_ HICON hIcon, _In_opt_ UINT width, _In_opt_ UINT height)
{
HBITMAP hBitmapResult = NULL;
// Create compatible DC
HDC hDC = CreateCompatibleDC(NULL);
if (hDC != NULL)
{
// Get bitmap rectangle size
RECT rc = { 0 };
rc.left = 0;
rc.right = (width != 0) ? width : GetSystemMetrics(SM_CXSMICON);
rc.top = 0;
rc.bottom = (height != 0) ? height : GetSystemMetrics(SM_CYSMICON);
// Create bitmap compatible with DC
BITMAPINFO BitmapInfo;
ZeroMemory(&BitmapInfo, sizeof(BITMAPINFO));
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = rc.right;
BitmapInfo.bmiHeader.biHeight = rc.bottom;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 32;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
HDC hDCBitmap = GetDC(NULL);
HBITMAP hBitmap = CreateDIBSection(hDCBitmap, &BitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0);
ReleaseDC(NULL, hDCBitmap);
if (hBitmap != NULL)
{
// Select bitmap into DC
HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDC, hBitmap);
if (hBitmapOld != NULL)
{
// Draw icon into DC
if (DrawIconEx(hDC, 0, 0, hIcon, rc.right, rc.bottom, 0, NULL, DI_NORMAL))
{
// Restore original bitmap in DC
hBitmapResult = (HBITMAP)SelectObject(hDC, hBitmapOld);
hBitmapOld = NULL;
hBitmap = NULL;
}
if (hBitmapOld != NULL)
{
SelectObject(hDC, hBitmapOld);
}
}
if (hBitmap != NULL)
{
DeleteObject(hBitmap);
}
}
DeleteDC(hDC);
}
return hBitmapResult;
}
HRESULT _ParseEnumItems(_In_ IEnumShellItems* pesi, _In_ IPowerRenameManager* psrm, _In_ int depth = 0) HRESULT _ParseEnumItems(_In_ IEnumShellItems* pesi, _In_ IPowerRenameManager* psrm, _In_ int depth = 0)
{ {
HRESULT hr = E_INVALIDARG; HRESULT hr = E_INVALIDARG;
@@ -40,7 +105,7 @@ HRESULT _ParseEnumItems(_In_ IEnumShellItems* pesi, _In_ IPowerRenameManager* ps
while ((S_OK == pesi->Next(1, &spsi, &celtFetched)) && (SUCCEEDED(hr))) while ((S_OK == pesi->Next(1, &spsi, &celtFetched)) && (SUCCEEDED(hr)))
{ {
CComPtr<IPowerRenameItemFactory> spsrif; CComPtr<IPowerRenameItemFactory> spsrif;
hr = psrm->get_smartRenameItemFactory(&spsrif); hr = psrm->get_renameItemFactory(&spsrif);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
CComPtr<IPowerRenameItem> spNewItem; CComPtr<IPowerRenameItem> spNewItem;

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include "stdafx.h"
HRESULT EnumerateDataObject(_In_ IDataObject* pdo, _In_ IPowerRenameManager* psrm); HRESULT EnumerateDataObject(_In_ IDataObject* pdo, _In_ IPowerRenameManager* psrm);
HRESULT GetIconIndexFromPath(_In_ PCWSTR path, _Out_ int* index); HRESULT GetIconIndexFromPath(_In_ PCWSTR path, _Out_ int* index);
HBITMAP CreateBitmapFromIcon(_In_ HICON hIcon, _In_opt_ UINT width = 0, _In_opt_ UINT height = 0);
HWND CreateMsgWindow(_In_ HINSTANCE hInst, _In_ WNDPROC pfnWndProc, _In_ void* p); HWND CreateMsgWindow(_In_ HINSTANCE hInst, _In_ WNDPROC pfnWndProc, _In_ void* p);
BOOL GetEnumeratedFileName( BOOL GetEnumeratedFileName(
__out_ecount(cchMax) PWSTR pszUniqueName, UINT cchMax, __out_ecount(cchMax) PWSTR pszUniqueName, UINT cchMax,

View File

@@ -93,10 +93,10 @@ public:
IFACEMETHOD(GetRenameItemCount)(_Out_ UINT* count) = 0; IFACEMETHOD(GetRenameItemCount)(_Out_ UINT* count) = 0;
IFACEMETHOD(get_flags)(_Out_ DWORD* flags) = 0; IFACEMETHOD(get_flags)(_Out_ DWORD* flags) = 0;
IFACEMETHOD(put_flags)(_In_ DWORD flags) = 0; IFACEMETHOD(put_flags)(_In_ DWORD flags) = 0;
IFACEMETHOD(get_smartRenameRegEx)(_COM_Outptr_ IPowerRenameRegEx** ppRegEx) = 0; IFACEMETHOD(get_renameRegEx)(_COM_Outptr_ IPowerRenameRegEx** ppRegEx) = 0;
IFACEMETHOD(put_smartRenameRegEx)(_In_ IPowerRenameRegEx* pRegEx) = 0; IFACEMETHOD(put_renameRegEx)(_In_ IPowerRenameRegEx* pRegEx) = 0;
IFACEMETHOD(get_smartRenameItemFactory)(_COM_Outptr_ IPowerRenameItemFactory** ppItemFactory) = 0; IFACEMETHOD(get_renameItemFactory)(_COM_Outptr_ IPowerRenameItemFactory** ppItemFactory) = 0;
IFACEMETHOD(put_smartRenameItemFactory)(_In_ IPowerRenameItemFactory* pItemFactory) = 0; IFACEMETHOD(put_renameItemFactory)(_In_ IPowerRenameItemFactory* pItemFactory) = 0;
}; };
interface __declspec(uuid("E6679DEB-460D-42C1-A7A8-E25897061C99")) IPowerRenameUI : public IUnknown interface __declspec(uuid("E6679DEB-460D-42C1-A7A8-E25897061C99")) IPowerRenameUI : public IUnknown
@@ -107,3 +107,9 @@ public:
IFACEMETHOD(Update)() = 0; IFACEMETHOD(Update)() = 0;
}; };
interface __declspec(uuid("04AAFABE-B76E-4E13-993A-B5941F52B139")) IPowerRenameMRU : public IUnknown
{
public:
IFACEMETHOD(AddMRUString)(_In_ PCWSTR entry) = 0;
};

View File

@@ -147,6 +147,7 @@
<ClInclude Include="PowerRenameInterfaces.h" /> <ClInclude Include="PowerRenameInterfaces.h" />
<ClInclude Include="PowerRenameManager.h" /> <ClInclude Include="PowerRenameManager.h" />
<ClInclude Include="PowerRenameRegEx.h" /> <ClInclude Include="PowerRenameRegEx.h" />
<ClInclude Include="Settings.h" />
<ClInclude Include="srwlock.h" /> <ClInclude Include="srwlock.h" />
<ClInclude Include="stdafx.h" /> <ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" /> <ClInclude Include="targetver.h" />
@@ -157,6 +158,7 @@
<ClCompile Include="PowerRenameItem.cpp" /> <ClCompile Include="PowerRenameItem.cpp" />
<ClCompile Include="PowerRenameManager.cpp" /> <ClCompile Include="PowerRenameManager.cpp" />
<ClCompile Include="PowerRenameRegEx.cpp" /> <ClCompile Include="PowerRenameRegEx.cpp" />
<ClCompile Include="Settings.cpp" />
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>

View File

@@ -44,7 +44,7 @@ IFACEMETHODIMP CPowerRenameManager::Advise(_In_ IPowerRenameManagerEvents* renam
{ {
CSRWExclusiveAutoLock lock(&m_lockEvents); CSRWExclusiveAutoLock lock(&m_lockEvents);
m_cookie++; m_cookie++;
SMART_RENAME_MGR_EVENT srme; RENAME_MGR_EVENT srme;
srme.cookie = m_cookie; srme.cookie = m_cookie;
srme.pEvents = renameOpEvents; srme.pEvents = renameOpEvents;
renameOpEvents->AddRef(); renameOpEvents->AddRef();
@@ -117,9 +117,9 @@ IFACEMETHODIMP CPowerRenameManager::AddItem(_In_ IPowerRenameItem* pItem)
int id = 0; int id = 0;
pItem->get_id(&id); pItem->get_id(&id);
// Verify the item isn't already added // Verify the item isn't already added
if (m_smartRenameItems.find(id) == m_smartRenameItems.end()) if (m_renameItems.find(id) == m_renameItems.end())
{ {
m_smartRenameItems[id] = pItem; m_renameItems[id] = pItem;
pItem->AddRef(); pItem->AddRef();
hr = S_OK; hr = S_OK;
} }
@@ -138,9 +138,9 @@ IFACEMETHODIMP CPowerRenameManager::GetItemByIndex(_In_ UINT index, _COM_Outptr_
*ppItem = nullptr; *ppItem = nullptr;
CSRWSharedAutoLock lock(&m_lockItems); CSRWSharedAutoLock lock(&m_lockItems);
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
if (index < m_smartRenameItems.size()) if (index < m_renameItems.size())
{ {
std::map<int, IPowerRenameItem*>::iterator it = m_smartRenameItems.begin(); std::map<int, IPowerRenameItem*>::iterator it = m_renameItems.begin();
std::advance(it, index); std::advance(it, index);
*ppItem = it->second; *ppItem = it->second;
(*ppItem)->AddRef(); (*ppItem)->AddRef();
@@ -157,10 +157,10 @@ IFACEMETHODIMP CPowerRenameManager::GetItemById(_In_ int id, _COM_Outptr_ IPower
CSRWSharedAutoLock lock(&m_lockItems); CSRWSharedAutoLock lock(&m_lockItems);
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
std::map<int, IPowerRenameItem*>::iterator it; std::map<int, IPowerRenameItem*>::iterator it;
it = m_smartRenameItems.find(id); it = m_renameItems.find(id);
if (it != m_smartRenameItems.end()) if (it != m_renameItems.end())
{ {
*ppItem = m_smartRenameItems[id]; *ppItem = m_renameItems[id];
(*ppItem)->AddRef(); (*ppItem)->AddRef();
hr = S_OK; hr = S_OK;
} }
@@ -171,7 +171,7 @@ IFACEMETHODIMP CPowerRenameManager::GetItemById(_In_ int id, _COM_Outptr_ IPower
IFACEMETHODIMP CPowerRenameManager::GetItemCount(_Out_ UINT* count) IFACEMETHODIMP CPowerRenameManager::GetItemCount(_Out_ UINT* count)
{ {
CSRWSharedAutoLock lock(&m_lockItems); CSRWSharedAutoLock lock(&m_lockItems);
*count = static_cast<UINT>(m_smartRenameItems.size()); *count = static_cast<UINT>(m_renameItems.size());
return S_OK; return S_OK;
} }
@@ -180,7 +180,7 @@ IFACEMETHODIMP CPowerRenameManager::GetSelectedItemCount(_Out_ UINT* count)
*count = 0; *count = 0;
CSRWSharedAutoLock lock(&m_lockItems); CSRWSharedAutoLock lock(&m_lockItems);
for (auto it : m_smartRenameItems) for (auto it : m_renameItems)
{ {
IPowerRenameItem* pItem = it.second; IPowerRenameItem* pItem = it.second;
bool selected = false; bool selected = false;
@@ -198,7 +198,7 @@ IFACEMETHODIMP CPowerRenameManager::GetRenameItemCount(_Out_ UINT* count)
*count = 0; *count = 0;
CSRWSharedAutoLock lock(&m_lockItems); CSRWSharedAutoLock lock(&m_lockItems);
for (auto it : m_smartRenameItems) for (auto it : m_renameItems)
{ {
IPowerRenameItem* pItem = it.second; IPowerRenameItem* pItem = it.second;
bool shouldRename = false; bool shouldRename = false;
@@ -229,7 +229,7 @@ IFACEMETHODIMP CPowerRenameManager::put_flags(_In_ DWORD flags)
return S_OK; return S_OK;
} }
IFACEMETHODIMP CPowerRenameManager::get_smartRenameRegEx(_COM_Outptr_ IPowerRenameRegEx** ppRegEx) IFACEMETHODIMP CPowerRenameManager::get_renameRegEx(_COM_Outptr_ IPowerRenameRegEx** ppRegEx)
{ {
*ppRegEx = nullptr; *ppRegEx = nullptr;
HRESULT hr = _EnsureRegEx(); HRESULT hr = _EnsureRegEx();
@@ -241,14 +241,14 @@ IFACEMETHODIMP CPowerRenameManager::get_smartRenameRegEx(_COM_Outptr_ IPowerRena
return hr; return hr;
} }
IFACEMETHODIMP CPowerRenameManager::put_smartRenameRegEx(_In_ IPowerRenameRegEx* pRegEx) IFACEMETHODIMP CPowerRenameManager::put_renameRegEx(_In_ IPowerRenameRegEx* pRegEx)
{ {
_ClearRegEx(); _ClearRegEx();
m_spRegEx = pRegEx; m_spRegEx = pRegEx;
return S_OK; return S_OK;
} }
IFACEMETHODIMP CPowerRenameManager::get_smartRenameItemFactory(_COM_Outptr_ IPowerRenameItemFactory** ppItemFactory) IFACEMETHODIMP CPowerRenameManager::get_renameItemFactory(_COM_Outptr_ IPowerRenameItemFactory** ppItemFactory)
{ {
*ppItemFactory = nullptr; *ppItemFactory = nullptr;
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
@@ -261,7 +261,7 @@ IFACEMETHODIMP CPowerRenameManager::get_smartRenameItemFactory(_COM_Outptr_ IPow
return hr; return hr;
} }
IFACEMETHODIMP CPowerRenameManager::put_smartRenameItemFactory(_In_ IPowerRenameItemFactory* pItemFactory) IFACEMETHODIMP CPowerRenameManager::put_renameItemFactory(_In_ IPowerRenameItemFactory* pItemFactory)
{ {
m_spItemFactory = pItemFactory; m_spItemFactory = pItemFactory;
return S_OK; return S_OK;
@@ -281,7 +281,7 @@ IFACEMETHODIMP CPowerRenameManager::OnReplaceTermChanged(_In_ PCWSTR /*replaceTe
IFACEMETHODIMP CPowerRenameManager::OnFlagsChanged(_In_ DWORD flags) IFACEMETHODIMP CPowerRenameManager::OnFlagsChanged(_In_ DWORD flags)
{ {
// Flags were updated in the smart rename regex. Update our preview. // Flags were updated in the rename regex. Update our preview.
m_flags = flags; m_flags = flags;
_PerformRegExRename(); _PerformRegExRename();
return S_OK; return S_OK;
@@ -330,7 +330,7 @@ HRESULT CPowerRenameManager::_Init()
// Custom messages for worker threads // Custom messages for worker threads
enum enum
{ {
SRM_REGEX_ITEM_UPDATED = (WM_APP + 1), // Single smart rename item processed by regex worker thread SRM_REGEX_ITEM_UPDATED = (WM_APP + 1), // Single rename item processed by regex worker thread
SRM_REGEX_STARTED, // RegEx operation was started SRM_REGEX_STARTED, // RegEx operation was started
SRM_REGEX_CANCELED, // Regex operation was canceled SRM_REGEX_CANCELED, // Regex operation was canceled
SRM_REGEX_COMPLETE, // Regex worker thread completed SRM_REGEX_COMPLETE, // Regex worker thread completed
@@ -546,7 +546,7 @@ DWORD WINAPI CPowerRenameManager::s_fileOpWorkerThread(_In_ void* pv)
if (WaitForSingleObject(pwtd->startEvent, INFINITE) == WAIT_OBJECT_0) if (WaitForSingleObject(pwtd->startEvent, INFINITE) == WAIT_OBJECT_0)
{ {
CComPtr<IPowerRenameRegEx> spRenameRegEx; CComPtr<IPowerRenameRegEx> spRenameRegEx;
if (SUCCEEDED(pwtd->spsrm->get_smartRenameRegEx(&spRenameRegEx))) if (SUCCEEDED(pwtd->spsrm->get_renameRegEx(&spRenameRegEx)))
{ {
// Create IFileOperation interface // Create IFileOperation interface
CComPtr<IFileOperation> spFileOp; CComPtr<IFileOperation> spFileOp;
@@ -557,24 +557,45 @@ DWORD WINAPI CPowerRenameManager::s_fileOpWorkerThread(_In_ void* pv)
UINT itemCount = 0; UINT itemCount = 0;
pwtd->spsrm->GetItemCount(&itemCount); pwtd->spsrm->GetItemCount(&itemCount);
// Add each rename operation
for (UINT u = 0; u <= itemCount; u++) // We add the items to the operation in depth-first order. This allows child items to be
// renamed before parent items.
// Creating a vector of vectors of items of the same depth
std::vector<std::vector<UINT>> matrix(itemCount);
for (UINT u = 0; u < itemCount; u++)
{ {
CComPtr<IPowerRenameItem> spItem; CComPtr<IPowerRenameItem> spItem;
if (SUCCEEDED(pwtd->spsrm->GetItemByIndex(u, &spItem))) if (SUCCEEDED(pwtd->spsrm->GetItemByIndex(u, &spItem)))
{ {
bool shouldRename = false; UINT depth = 0;
if (SUCCEEDED(spItem->ShouldRenameItem(flags, &shouldRename)) && shouldRename) spItem->get_depth(&depth);
matrix[depth].push_back(u);
}
}
// From the greatest depth first, add all items of that depth to the operation
for (LONG v = itemCount - 1; v >= 0; v--)
{
for (auto it : matrix[v])
{
CComPtr<IPowerRenameItem> spItem;
if (SUCCEEDED(pwtd->spsrm->GetItemByIndex(it, &spItem)))
{ {
PWSTR newName = nullptr; bool shouldRename = false;
if (SUCCEEDED(spItem->get_newName(&newName))) if (SUCCEEDED(spItem->ShouldRenameItem(flags, &shouldRename)) && shouldRename)
{ {
CComPtr<IShellItem> spShellItem; PWSTR newName = nullptr;
if (SUCCEEDED(spItem->get_shellItem(&spShellItem))) if (SUCCEEDED(spItem->get_newName(&newName)))
{ {
spFileOp->RenameItem(spShellItem, newName, nullptr); CComPtr<IShellItem> spShellItem;
if (SUCCEEDED(spItem->get_shellItem(&spShellItem)))
{
spFileOp->RenameItem(spShellItem, newName, nullptr);
}
CoTaskMemFree(newName);
} }
CoTaskMemFree(newName);
} }
} }
} }
@@ -674,7 +695,7 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
if (WaitForSingleObject(pwtd->startEvent, INFINITE) == WAIT_OBJECT_0) if (WaitForSingleObject(pwtd->startEvent, INFINITE) == WAIT_OBJECT_0)
{ {
CComPtr<IPowerRenameRegEx> spRenameRegEx; CComPtr<IPowerRenameRegEx> spRenameRegEx;
if (SUCCEEDED(pwtd->spsrm->get_smartRenameRegEx(&spRenameRegEx))) if (SUCCEEDED(pwtd->spsrm->get_renameRegEx(&spRenameRegEx)))
{ {
DWORD flags = 0; DWORD flags = 0;
spRenameRegEx->get_flags(&flags); spRenameRegEx->get_flags(&flags);
@@ -1022,14 +1043,14 @@ void CPowerRenameManager::_ClearPowerRenameItems()
{ {
CSRWExclusiveAutoLock lock(&m_lockItems); CSRWExclusiveAutoLock lock(&m_lockItems);
// Cleanup smart rename items // Cleanup rename items
for (auto it : m_smartRenameItems) for (auto it : m_renameItems)
{ {
IPowerRenameItem* pItem = it.second; IPowerRenameItem* pItem = it.second;
pItem->Release(); pItem->Release();
} }
m_smartRenameItems.clear(); m_renameItems.clear();
} }
void CPowerRenameManager::_Cleanup() void CPowerRenameManager::_Cleanup()

View File

@@ -29,10 +29,10 @@ public:
IFACEMETHODIMP GetRenameItemCount(_Out_ UINT* count); IFACEMETHODIMP GetRenameItemCount(_Out_ UINT* count);
IFACEMETHODIMP get_flags(_Out_ DWORD* flags); IFACEMETHODIMP get_flags(_Out_ DWORD* flags);
IFACEMETHODIMP put_flags(_In_ DWORD flags); IFACEMETHODIMP put_flags(_In_ DWORD flags);
IFACEMETHODIMP get_smartRenameRegEx(_COM_Outptr_ IPowerRenameRegEx** ppRegEx); IFACEMETHODIMP get_renameRegEx(_COM_Outptr_ IPowerRenameRegEx** ppRegEx);
IFACEMETHODIMP put_smartRenameRegEx(_In_ IPowerRenameRegEx* pRegEx); IFACEMETHODIMP put_renameRegEx(_In_ IPowerRenameRegEx* pRegEx);
IFACEMETHODIMP get_smartRenameItemFactory(_COM_Outptr_ IPowerRenameItemFactory** ppItemFactory); IFACEMETHODIMP get_renameItemFactory(_COM_Outptr_ IPowerRenameItemFactory** ppItemFactory);
IFACEMETHODIMP put_smartRenameItemFactory(_In_ IPowerRenameItemFactory* pItemFactory); IFACEMETHODIMP put_renameItemFactory(_In_ IPowerRenameItemFactory* pItemFactory);
// IPowerRenameRegExEvents // IPowerRenameRegExEvents
IFACEMETHODIMP OnSearchTermChanged(_In_ PCWSTR searchTerm); IFACEMETHODIMP OnSearchTermChanged(_In_ PCWSTR searchTerm);
@@ -99,7 +99,7 @@ protected:
DWORD m_cookie = 0; DWORD m_cookie = 0;
DWORD m_regExAdviseCookie = 0; DWORD m_regExAdviseCookie = 0;
struct SMART_RENAME_MGR_EVENT struct RENAME_MGR_EVENT
{ {
IPowerRenameManagerEvents* pEvents; IPowerRenameManagerEvents* pEvents;
DWORD cookie; DWORD cookie;
@@ -108,8 +108,8 @@ protected:
CComPtr<IPowerRenameItemFactory> m_spItemFactory; CComPtr<IPowerRenameItemFactory> m_spItemFactory;
CComPtr<IPowerRenameRegEx> m_spRegEx; CComPtr<IPowerRenameRegEx> m_spRegEx;
_Guarded_by_(m_lockEvents) std::vector<SMART_RENAME_MGR_EVENT> m_PowerRenameManagerEvents; _Guarded_by_(m_lockEvents) std::vector<RENAME_MGR_EVENT> m_PowerRenameManagerEvents;
_Guarded_by_(m_lockItems) std::map<int, IPowerRenameItem*> m_smartRenameItems; _Guarded_by_(m_lockItems) std::map<int, IPowerRenameItem*> m_renameItems;
// Parent HWND used by IFileOperation // Parent HWND used by IFileOperation
HWND m_hwndParent = nullptr; HWND m_hwndParent = nullptr;

View File

@@ -37,11 +37,11 @@ IFACEMETHODIMP CPowerRenameRegEx::Advise(_In_ IPowerRenameRegExEvents* regExEven
{ {
CSRWExclusiveAutoLock lock(&m_lockEvents); CSRWExclusiveAutoLock lock(&m_lockEvents);
m_cookie++; m_cookie++;
SMART_RENAME_REGEX_EVENT srre; RENAME_REGEX_EVENT srre;
srre.cookie = m_cookie; srre.cookie = m_cookie;
srre.pEvents = regExEvents; srre.pEvents = regExEvents;
regExEvents->AddRef(); regExEvents->AddRef();
m_smartRenameRegExEvents.push_back(srre); m_renameRegExEvents.push_back(srre);
*cookie = m_cookie; *cookie = m_cookie;
@@ -53,7 +53,7 @@ IFACEMETHODIMP CPowerRenameRegEx::UnAdvise(_In_ DWORD cookie)
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
CSRWExclusiveAutoLock lock(&m_lockEvents); CSRWExclusiveAutoLock lock(&m_lockEvents);
for (auto it : m_smartRenameRegExEvents) for (auto it : m_renameRegExEvents)
{ {
if (it.cookie == cookie) if (it.cookie == cookie)
{ {
@@ -265,7 +265,7 @@ void CPowerRenameRegEx::_OnSearchTermChanged()
{ {
CSRWSharedAutoLock lock(&m_lockEvents); CSRWSharedAutoLock lock(&m_lockEvents);
for (auto it : m_smartRenameRegExEvents) for (auto it : m_renameRegExEvents)
{ {
if (it.pEvents) if (it.pEvents)
{ {
@@ -278,7 +278,7 @@ void CPowerRenameRegEx::_OnReplaceTermChanged()
{ {
CSRWSharedAutoLock lock(&m_lockEvents); CSRWSharedAutoLock lock(&m_lockEvents);
for (auto it : m_smartRenameRegExEvents) for (auto it : m_renameRegExEvents)
{ {
if (it.pEvents) if (it.pEvents)
{ {
@@ -291,7 +291,7 @@ void CPowerRenameRegEx::_OnFlagsChanged()
{ {
CSRWSharedAutoLock lock(&m_lockEvents); CSRWSharedAutoLock lock(&m_lockEvents);
for (auto it : m_smartRenameRegExEvents) for (auto it : m_renameRegExEvents)
{ {
if (it.pEvents) if (it.pEvents)
{ {

View File

@@ -46,13 +46,13 @@ protected:
DWORD m_cookie = 0; DWORD m_cookie = 0;
struct SMART_RENAME_REGEX_EVENT struct RENAME_REGEX_EVENT
{ {
IPowerRenameRegExEvents* pEvents; IPowerRenameRegExEvents* pEvents;
DWORD cookie; DWORD cookie;
}; };
_Guarded_by_(m_lockEvents) std::vector<SMART_RENAME_REGEX_EVENT> m_smartRenameRegExEvents; _Guarded_by_(m_lockEvents) std::vector<RENAME_REGEX_EVENT> m_renameRegExEvents;
long m_refCount = 0; long m_refCount = 0;
}; };

View File

@@ -0,0 +1,483 @@
#include "stdafx.h"
#include <commctrl.h>
#include "Settings.h"
const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\PowerRename";
const wchar_t c_mruSearchRegPath[] = L"SearchMRU";
const wchar_t c_mruReplaceRegPath[] = L"ReplaceMRU";
const wchar_t c_enabled[] = L"Enabled";
const wchar_t c_showIconOnMenu[] = L"ShowIcon";
const wchar_t c_extendedContextMenuOnly[] = L"ExtendedContextMenuOnly";
const wchar_t c_persistState[] = L"PersistState";
const wchar_t c_maxMRUSize[] = L"MaxMRUSize";
const wchar_t c_flags[] = L"Flags";
const wchar_t c_searchText[] = L"SearchText";
const wchar_t c_replaceText[] = L"ReplaceText";
const wchar_t c_mruEnabled[] = L"MRUEnabled";
const bool c_enabledDefault = true;
const bool c_showIconOnMenuDefault = true;
const bool c_extendedContextMenuOnlyDefaut = false;
const bool c_persistStateDefault = true;
const bool c_mruEnabledDefault = true;
const DWORD c_maxMRUSizeDefault = 10;
const DWORD c_flagsDefault = 0;
bool CSettings::GetEnabled()
{
return GetRegBoolValue(c_enabled, c_enabledDefault);
}
bool CSettings::SetEnabled(_In_ bool enabled)
{
return SetRegBoolValue(c_enabled, enabled);
}
bool CSettings::GetShowIconOnMenu()
{
return GetRegBoolValue(c_showIconOnMenu, c_showIconOnMenuDefault);
}
bool CSettings::SetShowIconOnMenu(_In_ bool show)
{
return SetRegBoolValue(c_showIconOnMenu, show);
}
bool CSettings::GetExtendedContextMenuOnly()
{
return GetRegBoolValue(c_extendedContextMenuOnly, c_extendedContextMenuOnlyDefaut);
}
bool CSettings::SetExtendedContextMenuOnly(_In_ bool extendedOnly)
{
return SetRegBoolValue(c_extendedContextMenuOnly, extendedOnly);
}
bool CSettings::GetPersistState()
{
return GetRegBoolValue(c_persistState, c_persistStateDefault);
}
bool CSettings::SetPersistState(_In_ bool persistState)
{
return SetRegBoolValue(c_persistState, persistState);
}
bool CSettings::GetMRUEnabled()
{
return GetRegBoolValue(c_mruEnabled, c_mruEnabledDefault);
}
bool CSettings::SetMRUEnabled(_In_ bool enabled)
{
return SetRegBoolValue(c_mruEnabled, enabled);
}
DWORD CSettings::GetMaxMRUSize()
{
return GetRegDWORDValue(c_maxMRUSize, c_maxMRUSizeDefault);
}
bool CSettings::SetMaxMRUSize(_In_ DWORD maxMRUSize)
{
return SetRegDWORDValue(c_maxMRUSize, maxMRUSize);
}
DWORD CSettings::GetFlags()
{
return GetRegDWORDValue(c_flags, c_flagsDefault);
}
bool CSettings::SetFlags(_In_ DWORD flags)
{
return SetRegDWORDValue(c_flags, flags);
}
bool CSettings::GetSearchText(__out_ecount(cchBuf) PWSTR text, DWORD cchBuf)
{
return GetRegStringValue(c_searchText, text, cchBuf);
}
bool CSettings::SetSearchText(_In_ PCWSTR text)
{
return SetRegStringValue(c_searchText, text);
}
bool CSettings::GetReplaceText(__out_ecount(cchBuf) PWSTR text, DWORD cchBuf)
{
return GetRegStringValue(c_replaceText, text, cchBuf);
}
bool CSettings::SetReplaceText(_In_ PCWSTR text)
{
return SetRegStringValue(c_replaceText, text);
}
bool CSettings::SetRegBoolValue(_In_ PCWSTR valueName, _In_ bool value)
{
DWORD dwValue = value ? 1 : 0;
return SetRegDWORDValue(valueName, dwValue);
}
bool CSettings::GetRegBoolValue(_In_ PCWSTR valueName, _In_ bool defaultValue)
{
DWORD value = GetRegDWORDValue(valueName, (defaultValue == 0) ? false : true);
return (value == 0) ? false : true;
}
bool CSettings::SetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD value)
{
return (SUCCEEDED(HRESULT_FROM_WIN32(SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, REG_DWORD, &value, sizeof(value)))));
}
DWORD CSettings::GetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD defaultValue)
{
DWORD retVal = defaultValue;
DWORD type = REG_DWORD;
DWORD dwEnabled = 0;
DWORD cb = sizeof(dwEnabled);
if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, &type, &dwEnabled, &cb) == ERROR_SUCCESS)
{
retVal = dwEnabled;
}
return retVal;
}
bool CSettings::SetRegStringValue(_In_ PCWSTR valueName, _In_ PCWSTR value)
{
ULONG cb = (DWORD)((wcslen(value) + 1) * sizeof(*value));
return (SUCCEEDED(HRESULT_FROM_WIN32(SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, REG_SZ, (const BYTE*)value, cb))));
}
bool CSettings::GetRegStringValue(_In_ PCWSTR valueName, __out_ecount(cchBuf) PWSTR value, DWORD cchBuf)
{
if (cchBuf > 0)
{
value[0] = L'\0';
}
DWORD type = REG_SZ;
ULONG cb = cchBuf * sizeof(*value);
return (SUCCEEDED(HRESULT_FROM_WIN32(SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName, &type, value, &cb) == ERROR_SUCCESS)));
}
typedef int (CALLBACK* MRUCMPPROC)(LPCWSTR, LPCWSTR);
typedef struct {
DWORD cbSize;
UINT uMax;
UINT fFlags;
HKEY hKey;
LPCTSTR lpszSubKey;
MRUCMPPROC lpfnCompare;
} MRUINFO;
typedef HANDLE (*CreateMRUListFn)(MRUINFO* pmi);
typedef int (*AddMRUStringFn)(HANDLE hMRU, LPCWSTR data);
typedef int (*EnumMRUListFn)(HANDLE hMRU, int nItem, void* lpData, UINT uLen);
typedef int (*FreeMRUListFn)(HANDLE hMRU);
class CRenameMRU :
public IEnumString,
public IPowerRenameMRU
{
public:
// IUnknown
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP_(ULONG) Release();
IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv);
// IEnumString
IFACEMETHODIMP Next(__in ULONG celt, __out_ecount_part(celt, *pceltFetched) LPOLESTR* rgelt, __out_opt ULONG* pceltFetched);
IFACEMETHODIMP Skip(__in ULONG celt) { return E_NOTIMPL; }
IFACEMETHODIMP Reset();
IFACEMETHODIMP Clone(__deref_out IEnumString** ppenum) { *ppenum = nullptr; return E_NOTIMPL; }
// IPowerRenameMRU
IFACEMETHODIMP AddMRUString(_In_ PCWSTR entry);
static HRESULT CreateInstance(_In_ PCWSTR regPathMRU, _In_ ULONG maxMRUSize, _Outptr_ IUnknown** ppUnk);
private:
CRenameMRU();
~CRenameMRU();
HRESULT _Initialize(_In_ PCWSTR regPathMRU, __in ULONG maxMRUSize);
HRESULT _CreateMRUList(_In_ MRUINFO* pmi);
int _AddMRUString(_In_ PCWSTR data);
int _EnumMRUList(_In_ int nItem, _Out_ void* lpData, _In_ UINT uLen);
void _FreeMRUList();
long m_refCount = 0;
HKEY m_hKey = NULL;
ULONG m_maxMRUSize = 0;
ULONG m_mruIndex = 0;
ULONG m_mruSize = 0;
HANDLE m_mruHandle = NULL;
HMODULE m_hComctl32Dll = NULL;
PWSTR m_regPath = nullptr;
};
CRenameMRU::CRenameMRU() :
m_refCount(1)
{}
CRenameMRU::~CRenameMRU()
{
if (m_hKey)
{
RegCloseKey(m_hKey);
}
_FreeMRUList();
if (m_hComctl32Dll)
{
FreeLibrary(m_hComctl32Dll);
}
CoTaskMemFree(m_regPath);
}
HRESULT CRenameMRU::CreateInstance(_In_ PCWSTR regPathMRU, _In_ ULONG maxMRUSize, _Outptr_ IUnknown** ppUnk)
{
*ppUnk = nullptr;
HRESULT hr = (regPathMRU && maxMRUSize > 0) ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
CRenameMRU* renameMRU = new CRenameMRU();
hr = renameMRU ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
hr = renameMRU->_Initialize(regPathMRU, maxMRUSize);
if (SUCCEEDED(hr))
{
hr = renameMRU->QueryInterface(IID_PPV_ARGS(ppUnk));
}
renameMRU->Release();
}
}
return hr;
}
// IUnknown
IFACEMETHODIMP_(ULONG) CRenameMRU::AddRef()
{
return InterlockedIncrement(&m_refCount);
}
IFACEMETHODIMP_(ULONG) CRenameMRU::Release()
{
long refCount = InterlockedDecrement(&m_refCount);
if (refCount == 0)
{
delete this;
}
return refCount;
}
IFACEMETHODIMP CRenameMRU::QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv)
{
static const QITAB qit[] = {
QITABENT(CRenameMRU, IEnumString),
QITABENT(CRenameMRU, IPowerRenameMRU),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
HRESULT CRenameMRU::_Initialize(_In_ PCWSTR regPathMRU, __in ULONG maxMRUSize)
{
m_maxMRUSize = maxMRUSize;
wchar_t regPath[MAX_PATH] = { 0 };
HRESULT hr = StringCchPrintf(regPath, ARRAYSIZE(regPath), L"%s\\%s", c_rootRegPath, regPathMRU);
if (SUCCEEDED(hr))
{
hr = SHStrDup(regPathMRU, &m_regPath);
if (SUCCEEDED(hr))
{
MRUINFO mi = {
sizeof(MRUINFO),
maxMRUSize,
0,
HKEY_CURRENT_USER,
regPath,
nullptr
};
hr = _CreateMRUList(&mi);
if (SUCCEEDED(hr))
{
m_mruSize = _EnumMRUList(-1, NULL, 0);
}
else
{
hr = E_FAIL;
}
}
}
return hr;
}
// IEnumString
IFACEMETHODIMP CRenameMRU::Reset()
{
m_mruIndex = 0;
return S_OK;
}
#define MAX_ENTRY_STRING 1024
IFACEMETHODIMP CRenameMRU::Next(__in ULONG celt, __out_ecount_part(celt, *pceltFetched) LPOLESTR* rgelt, __out_opt ULONG* pceltFetched)
{
HRESULT hr = S_OK;
WCHAR mruEntry[MAX_ENTRY_STRING];
mruEntry[0] = L'\0';
if (pceltFetched)
{
*pceltFetched = 0;
}
if (!celt)
{
return S_OK;
}
if (!rgelt)
{
return S_FALSE;
}
hr = S_FALSE;
if (m_mruIndex <= m_mruSize && _EnumMRUList(m_mruIndex++, (void*)mruEntry, ARRAYSIZE(mruEntry)) > 0)
{
hr = SHStrDup(mruEntry, rgelt);
if (SUCCEEDED(hr) && pceltFetched != nullptr)
{
*pceltFetched = 1;
}
}
return hr;
}
IFACEMETHODIMP CRenameMRU::AddMRUString(_In_ PCWSTR entry)
{
return (_AddMRUString(entry) < 0) ? E_FAIL : S_OK;
}
HRESULT CRenameMRU::_CreateMRUList(_In_ MRUINFO* pmi)
{
HRESULT hr = E_FAIL;
if (m_mruHandle != NULL)
{
_FreeMRUList();
}
if (m_hComctl32Dll == NULL)
{
m_hComctl32Dll = LoadLibraryEx(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
}
if (m_hComctl32Dll != nullptr)
{
CreateMRUListFn pfnCreateMRUList = reinterpret_cast<CreateMRUListFn>(GetProcAddress(m_hComctl32Dll, (LPCSTR)MAKEINTRESOURCE(400)));
if (pfnCreateMRUList != nullptr)
{
m_mruHandle = pfnCreateMRUList(pmi);
}
}
return (m_mruHandle != NULL) ? S_OK : E_FAIL;
}
int CRenameMRU::_AddMRUString(_In_ PCWSTR data)
{
int retVal = -1;
if (m_mruHandle != NULL)
{
if (m_hComctl32Dll == NULL)
{
m_hComctl32Dll = LoadLibraryEx(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
}
if (m_hComctl32Dll != nullptr)
{
AddMRUStringFn pfnAddMRUString = reinterpret_cast<AddMRUStringFn>(GetProcAddress(m_hComctl32Dll, (LPCSTR)MAKEINTRESOURCE(401)));
if (pfnAddMRUString != nullptr)
{
retVal = pfnAddMRUString(m_mruHandle, data);
}
}
}
return retVal;
}
int CRenameMRU::_EnumMRUList(_In_ int nItem, _Out_ void* lpData, _In_ UINT uLen)
{
int retVal = -1;
if (m_mruHandle != NULL)
{
if (m_hComctl32Dll == NULL)
{
m_hComctl32Dll = LoadLibraryEx(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
}
if (m_hComctl32Dll != nullptr)
{
EnumMRUListFn pfnEnumMRUList = reinterpret_cast<EnumMRUListFn>(GetProcAddress(m_hComctl32Dll, (LPCSTR)MAKEINTRESOURCE(403)));
if (pfnEnumMRUList != nullptr)
{
retVal = pfnEnumMRUList(m_mruHandle, nItem, lpData, uLen);
}
}
}
return retVal;
}
void CRenameMRU::_FreeMRUList()
{
if (m_mruHandle != NULL)
{
if (m_hComctl32Dll == NULL)
{
m_hComctl32Dll = LoadLibraryEx(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
}
if (m_hComctl32Dll != nullptr)
{
FreeMRUListFn pfnFreeMRUList = reinterpret_cast<FreeMRUListFn>(GetProcAddress(m_hComctl32Dll, (LPCSTR)MAKEINTRESOURCE(152)));
if (pfnFreeMRUList != nullptr)
{
pfnFreeMRUList(m_mruHandle);
}
}
m_mruHandle = NULL;
}
}
HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk)
{
return CRenameMRU::CreateInstance(c_mruSearchRegPath, CSettings::GetMaxMRUSize(), ppUnk);
}
HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk)
{
return CRenameMRU::CreateInstance(c_mruReplaceRegPath, CSettings::GetMaxMRUSize(), ppUnk);
}

View File

@@ -0,0 +1,43 @@
#pragma once
class CSettings
{
public:
static bool GetEnabled();
static bool SetEnabled(_In_ bool enabled);
static bool GetShowIconOnMenu();
static bool SetShowIconOnMenu(_In_ bool show);
static bool GetExtendedContextMenuOnly();
static bool SetExtendedContextMenuOnly(_In_ bool extendedOnly);
static bool GetPersistState();
static bool SetPersistState(_In_ bool extendedOnly);
static bool GetMRUEnabled();
static bool SetMRUEnabled(_In_ bool enabled);
static DWORD GetMaxMRUSize();
static bool SetMaxMRUSize(_In_ DWORD maxMRUSize);
static DWORD GetFlags();
static bool SetFlags(_In_ DWORD flags);
static bool GetSearchText(__out_ecount(cchBuf) PWSTR text, DWORD cchBuf);
static bool SetSearchText(_In_ PCWSTR text);
static bool GetReplaceText(__out_ecount(cchBuf) PWSTR text, DWORD cchBuf);
static bool SetReplaceText(_In_ PCWSTR text);
private:
static bool GetRegBoolValue(_In_ PCWSTR valueName, _In_ bool defaultValue);
static bool SetRegBoolValue(_In_ PCWSTR valueName, _In_ bool value);
static bool SetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD value);
static DWORD GetRegDWORDValue(_In_ PCWSTR valueName, _In_ DWORD defaultValue);
static bool SetRegStringValue(_In_ PCWSTR valueName, _In_ PCWSTR value);
static bool GetRegStringValue(_In_ PCWSTR valueName, __out_ecount(cchBuf) PWSTR value, DWORD cchBuf);
};
HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk);
HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk);

View File

@@ -16,6 +16,7 @@
#include <pathcch.h> #include <pathcch.h>
#include <shobjidl.h> #include <shobjidl.h>
#include <shellapi.h> #include <shellapi.h>
#include <shlwapi.h>
#include <ProjectTelemetry.h> #include <ProjectTelemetry.h>

View File

@@ -31,7 +31,7 @@ int APIENTRY wWinMain(
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// Create the smart rename manager // Create the rename manager
CComPtr<IPowerRenameManager> spsrm; CComPtr<IPowerRenameManager> spsrm;
if (SUCCEEDED(CPowerRenameManager::s_CreateInstance(&spsrm))) if (SUCCEEDED(CPowerRenameManager::s_CreateInstance(&spsrm)))
{ {
@@ -40,9 +40,9 @@ int APIENTRY wWinMain(
if (SUCCEEDED(CPowerRenameItem::s_CreateInstance(nullptr, IID_PPV_ARGS(&spsrif)))) if (SUCCEEDED(CPowerRenameItem::s_CreateInstance(nullptr, IID_PPV_ARGS(&spsrif))))
{ {
// Pass the factory to the manager // Pass the factory to the manager
if (SUCCEEDED(spsrm->put_smartRenameItemFactory(spsrif))) if (SUCCEEDED(spsrm->put_renameItemFactory(spsrif)))
{ {
// Create the smart rename UI instance and pass the manager // Create the rename UI instance and pass the manager
CComPtr<IPowerRenameUI> spsrui; CComPtr<IPowerRenameUI> spsrui;
if (SUCCEEDED(CPowerRenameUI::s_CreateInstance(spsrm, nullptr, true, &spsrui))) if (SUCCEEDED(CPowerRenameUI::s_CreateInstance(spsrm, nullptr, true, &spsrui)))
{ {

View File

@@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}} //{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file. // Microsoft Visual C++ generated include file.
// Used by SmartRenameTest.rc // Used by PowerRenameTest.rc
// //
#define IDD_POWERRENAMETEST_DIALOG 402 #define IDD_POWERRENAMETEST_DIALOG 402
#define IDR_MAINFRAME 428 #define IDR_MAINFRAME 428

View File

@@ -4,6 +4,7 @@
#include <commctrl.h> #include <commctrl.h>
#include <Shlobj.h> #include <Shlobj.h>
#include <helpers.h> #include <helpers.h>
#include <settings.h>
#include <windowsx.h> #include <windowsx.h>
extern HINSTANCE g_hInst; extern HINSTANCE g_hInst;
@@ -74,6 +75,8 @@ RepositionMap g_repositionMap[] =
inline int RECT_WIDTH(RECT& r) { return r.right - r.left; } inline int RECT_WIDTH(RECT& r) { return r.right - r.left; }
inline int RECT_HEIGHT(RECT& r) { return r.bottom - r.top; } inline int RECT_HEIGHT(RECT& r) { return r.bottom - r.top; }
#define MAX_INPUT_STRING_LEN 1024
// IUnknown // IUnknown
IFACEMETHODIMP CPowerRenameUI::QueryInterface(__in REFIID riid, __deref_out void** ppv) IFACEMETHODIMP CPowerRenameUI::QueryInterface(__in REFIID riid, __deref_out void** ppv)
{ {
@@ -261,8 +264,6 @@ IFACEMETHODIMP CPowerRenameUI::Drop(_In_ IDataObject* pdtobj, DWORD, POINTL pt,
m_spdth->Drop(pdtobj, &ptT, *pdwEffect); m_spdth->Drop(pdtobj, &ptT, *pdwEffect);
} }
_OnClear();
EnableWindow(GetDlgItem(m_hwnd, ID_RENAME), TRUE); EnableWindow(GetDlgItem(m_hwnd, ID_RENAME), TRUE);
EnableWindow(m_hwndLV, TRUE); EnableWindow(m_hwndLV, TRUE);
@@ -277,7 +278,7 @@ IFACEMETHODIMP CPowerRenameUI::Drop(_In_ IDataObject* pdtobj, DWORD, POINTL pt,
HRESULT CPowerRenameUI::_Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IDataObject* pdo, _In_ bool enableDragDrop) HRESULT CPowerRenameUI::_Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IDataObject* pdo, _In_ bool enableDragDrop)
{ {
// Cache the smart rename manager // Cache the rename manager
m_spsrm = psrm; m_spsrm = psrm;
// Cache the data object for enumeration later // Cache the data object for enumeration later
@@ -288,7 +289,7 @@ HRESULT CPowerRenameUI::_Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IDa
HRESULT hr = CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&m_spdth)); HRESULT hr = CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&m_spdth));
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// Subscribe to smart rename manager events // Subscribe to rename manager events
hr = m_spsrm->Advise(this, &m_cookie); hr = m_spsrm->Advise(this, &m_cookie);
} }
@@ -300,6 +301,46 @@ HRESULT CPowerRenameUI::_Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IDa
return hr; return hr;
} }
HRESULT CPowerRenameUI::_InitAutoComplete()
{
HRESULT hr = S_OK;
if (CSettings::GetMRUEnabled())
{
hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&m_spSearchAC));
if (SUCCEEDED(hr))
{
hr = CRenameMRUSearch_CreateInstance(&m_spSearchACL);
if (SUCCEEDED(hr))
{
hr = m_spSearchAC->Init(GetDlgItem(m_hwnd, IDC_EDIT_SEARCHFOR), m_spSearchACL, nullptr, nullptr);
if (SUCCEEDED(hr))
{
hr = m_spSearchAC->SetOptions(ACO_AUTOSUGGEST | ACO_AUTOAPPEND | ACO_UPDOWNKEYDROPSLIST);
}
}
}
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&m_spReplaceAC));
if (SUCCEEDED(hr))
{
hr = CRenameMRUReplace_CreateInstance(&m_spReplaceACL);
if (SUCCEEDED(hr))
{
hr = m_spReplaceAC->Init(GetDlgItem(m_hwnd, IDC_EDIT_REPLACEWITH), m_spReplaceACL, nullptr, nullptr);
if (SUCCEEDED(hr))
{
hr = m_spReplaceAC->SetOptions(ACO_AUTOSUGGEST | ACO_AUTOAPPEND | ACO_UPDOWNKEYDROPSLIST);
}
}
}
}
}
return hr;
}
void CPowerRenameUI::_Cleanup() void CPowerRenameUI::_Cleanup()
{ {
if (m_spsrm && m_cookie != 0) if (m_spsrm && m_cookie != 0)
@@ -335,26 +376,77 @@ void CPowerRenameUI::_EnumerateItems(_In_ IDataObject* pdtobj)
} }
} }
// TODO: persist settings made in the UI
HRESULT CPowerRenameUI::_ReadSettings() HRESULT CPowerRenameUI::_ReadSettings()
{ {
// Check if we should read flags from settings
// or the defaults from the manager.
DWORD flags = 0;
if (CSettings::GetPersistState())
{
flags = CSettings::GetFlags();
m_spsrm->put_flags(flags);
wchar_t buffer[MAX_INPUT_STRING_LEN];
buffer[0] = L'\0';
CSettings::GetSearchText(buffer, ARRAYSIZE(buffer));
SetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer);
buffer[0] = L'\0';
CSettings::GetReplaceText(buffer, ARRAYSIZE(buffer));
SetDlgItemText(m_hwnd, IDC_EDIT_REPLACEWITH, buffer);
}
else
{
m_spsrm->get_flags(&flags);
}
_SetCheckboxesFromFlags(flags);
return S_OK; return S_OK;
} }
HRESULT CPowerRenameUI::_WriteSettings() HRESULT CPowerRenameUI::_WriteSettings()
{ {
return S_OK; // Check if we should store our settings
} if (CSettings::GetPersistState())
{
DWORD flags = 0;
m_spsrm->get_flags(&flags);
CSettings::SetFlags(flags);
void CPowerRenameUI::_OnClear() wchar_t buffer[MAX_INPUT_STRING_LEN];
{ buffer[0] = L'\0';
GetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer, ARRAYSIZE(buffer));
CSettings::SetSearchText(buffer);
if (CSettings::GetMRUEnabled() && m_spSearchACL)
{
CComPtr<IPowerRenameMRU> spSearchMRU;
if (SUCCEEDED(m_spSearchACL->QueryInterface(IID_PPV_ARGS(&spSearchMRU))))
{
spSearchMRU->AddMRUString(buffer);
}
}
buffer[0] = L'\0';
GetDlgItemText(m_hwnd, IDC_EDIT_REPLACEWITH, buffer, ARRAYSIZE(buffer));
CSettings::SetReplaceText(buffer);
if (CSettings::GetMRUEnabled() && m_spReplaceACL)
{
CComPtr<IPowerRenameMRU> spReplaceMRU;
if (SUCCEEDED(m_spReplaceACL->QueryInterface(IID_PPV_ARGS(&spReplaceMRU))))
{
spReplaceMRU->AddMRUString(buffer);
}
}
}
return S_OK;
} }
void CPowerRenameUI::_OnCloseDlg() void CPowerRenameUI::_OnCloseDlg()
{ {
// Persist the current settings
_WriteSettings();
if (m_modeless) if (m_modeless)
{ {
DestroyWindow(m_hwnd); DestroyWindow(m_hwnd);
@@ -381,6 +473,11 @@ void CPowerRenameUI::_OnRename()
{ {
m_spsrm->Rename(m_hwnd); m_spsrm->Rename(m_hwnd);
} }
// Persist the current settings. We only do this when
// a rename is actually performed. Not when the user
// closes/cancels the dialog.
_WriteSettings();
} }
void CPowerRenameUI::_OnAbout() void CPowerRenameUI::_OnAbout()
@@ -486,8 +583,26 @@ void CPowerRenameUI::_OnInitDlg()
// Initialize checkboxes from flags // Initialize checkboxes from flags
if (m_spsrm) if (m_spsrm)
{ {
// Check if we should read flags from settings
// or the defaults from the manager.
DWORD flags = 0; DWORD flags = 0;
m_spsrm->get_flags(&flags); if (CSettings::GetPersistState())
{
flags = CSettings::GetFlags();
wchar_t buffer[MAX_INPUT_STRING_LEN];
buffer[0] = L'\0';
CSettings::GetSearchText(buffer, ARRAYSIZE(buffer));
SetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer);
buffer[0] = L'\0';
CSettings::GetReplaceText(buffer, ARRAYSIZE(buffer));
SetDlgItemText(m_hwnd, IDC_EDIT_REPLACEWITH, buffer);
}
else
{
m_spsrm->get_flags(&flags);
}
_SetCheckboxesFromFlags(flags); _SetCheckboxesFromFlags(flags);
} }
@@ -517,6 +632,8 @@ void CPowerRenameUI::_OnInitDlg()
m_lastWidth = m_initialWidth; m_lastWidth = m_initialWidth;
m_lastHeight = m_initialHeight; m_lastHeight = m_initialHeight;
_InitAutoComplete();
// Disable rename button by default. It will be enabled in _UpdateCounts if // Disable rename button by default. It will be enabled in _UpdateCounts if
// there are tiems to be renamed // there are tiems to be renamed
EnableWindow(GetDlgItem(m_hwnd, ID_RENAME), FALSE); EnableWindow(GetDlgItem(m_hwnd, ID_RENAME), FALSE);
@@ -719,9 +836,10 @@ void CPowerRenameUI::_OnSearchReplaceChanged()
{ {
// Pass updated search and replace terms to the IPowerRenameRegEx handler // Pass updated search and replace terms to the IPowerRenameRegEx handler
CComPtr<IPowerRenameRegEx> spRegEx; CComPtr<IPowerRenameRegEx> spRegEx;
if (m_spsrm && SUCCEEDED(m_spsrm->get_smartRenameRegEx(&spRegEx))) if (m_spsrm && SUCCEEDED(m_spsrm->get_renameRegEx(&spRegEx)))
{ {
wchar_t buffer[MAX_PATH] = { 0 }; wchar_t buffer[MAX_INPUT_STRING_LEN];
buffer[0] = L'\0';
GetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer, ARRAYSIZE(buffer)); GetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer, ARRAYSIZE(buffer));
spRegEx->put_searchTerm(buffer); spRegEx->put_searchTerm(buffer);
@@ -1088,14 +1206,15 @@ void CPowerRenameListView::_UpdateHeaderCheckState(_In_ bool check)
HWND hwndHeader = ListView_GetHeader(m_hwndLV); HWND hwndHeader = ListView_GetHeader(m_hwndLV);
if (hwndHeader) if (hwndHeader)
{ {
wchar_t szBuff[MAX_PATH] = { 0 }; wchar_t buffer[MAX_PATH] = { 0 };
buffer[0] = L'\0';
// Retrieve the existing header first so we // Retrieve the existing header first so we
// don't trash the text already there // don't trash the text already there
HDITEM hdi = { 0 }; HDITEM hdi = { 0 };
hdi.mask = HDI_FORMAT | HDI_TEXT; hdi.mask = HDI_FORMAT | HDI_TEXT;
hdi.pszText = szBuff; hdi.pszText = buffer;
hdi.cchTextMax = ARRAYSIZE(szBuff); hdi.cchTextMax = ARRAYSIZE(buffer);
Header_GetItem(hwndHeader, 0, &hdi); Header_GetItem(hwndHeader, 0, &hdi);

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <PowerRenameInterfaces.h> #include <PowerRenameInterfaces.h>
#include <shldisp.h>
class CPowerRenameListView class CPowerRenameListView
{ {
@@ -92,6 +93,7 @@ private:
} }
HRESULT _Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IDataObject* pdo, _In_ bool enableDragDrop); HRESULT _Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IDataObject* pdo, _In_ bool enableDragDrop);
HRESULT _InitAutoComplete();
void _Cleanup(); void _Cleanup();
INT_PTR _DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR _DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
@@ -104,7 +106,6 @@ private:
void _OnAbout(); void _OnAbout();
void _OnCloseDlg(); void _OnCloseDlg();
void _OnDestroyDlg(); void _OnDestroyDlg();
void _OnClear();
void _OnSearchReplaceChanged(); void _OnSearchReplaceChanged();
void _MoveControl(_In_ DWORD id, _In_ DWORD repositionFlags, _In_ int xDelta, _In_ int yDelta); void _MoveControl(_In_ DWORD id, _In_ DWORD repositionFlags, _In_ int xDelta, _In_ int yDelta);
@@ -137,5 +138,9 @@ private:
CComPtr<IPowerRenameManager> m_spsrm; CComPtr<IPowerRenameManager> m_spsrm;
CComPtr<IDataObject> m_spdo; CComPtr<IDataObject> m_spdo;
CComPtr<IDropTargetHelper> m_spdth; CComPtr<IDropTargetHelper> m_spdth;
CComPtr<IAutoComplete2> m_spSearchAC;
CComPtr<IUnknown> m_spSearchACL;
CComPtr<IAutoComplete2> m_spReplaceAC;
CComPtr<IUnknown> m_spReplaceACL;
CPowerRenameListView m_listview; CPowerRenameListView m_listview;
}; };

View File

@@ -79,7 +79,7 @@ namespace PowerRenameManagerTests
// TODO: Setup match and replace parameters // TODO: Setup match and replace parameters
CComPtr<IPowerRenameRegEx> renRegEx; CComPtr<IPowerRenameRegEx> renRegEx;
Assert::IsTrue(mgr->get_smartRenameRegEx(&renRegEx) == S_OK); Assert::IsTrue(mgr->get_renameRegEx(&renRegEx) == S_OK);
renRegEx->put_flags(flags); renRegEx->put_flags(flags);
renRegEx->put_searchTerm(searchTerm.c_str()); renRegEx->put_searchTerm(searchTerm.c_str());
renRegEx->put_replaceTerm(replaceTerm.c_str()); renRegEx->put_replaceTerm(replaceTerm.c_str());
@@ -125,7 +125,7 @@ namespace PowerRenameManagerTests
Assert::IsTrue(mgr->Shutdown() == S_OK); Assert::IsTrue(mgr->Shutdown() == S_OK);
} }
TEST_METHOD(VerifySmartManagerEvents) TEST_METHOD(VerifyRenameManagerEvents)
{ {
CComPtr<IPowerRenameManager> mgr; CComPtr<IPowerRenameManager> mgr;
Assert::IsTrue(CPowerRenameManager::s_CreateInstance(&mgr) == S_OK); Assert::IsTrue(CPowerRenameManager::s_CreateInstance(&mgr) == S_OK);