mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 01:08:18 +08:00
[PowerRename] Fix tests inconsistency, improve test performance (#8129)
* Move retrieveing file attibutes to PowerRenameRegex Move file attributes unit tests to PowerRenameRegexTests Add file time field to MockPowerRenameItem * Add file attributes unittests to PowerRenameManagerTests * Change variable name * Rearrange function arguments * Check if file attributes are used only once * Change variable name LocalTime -> fileTime, date -> time * Set fileTime as a member of PowerRenameRegEx rather than passing as an argument * Change function name isFileAttributesUsed() -> isFileTimeUsed() Check before resetting fileTime * Fix small bugs * Fix typos * Refactor for readability, move free calls to reachable places * Fix search for area empty bug searchTerm being empty is not an invalid argument rather it must return OK without any operation Tests must check if Replace() returns S_OK becuase later it checks its result * Check return values of method calls in PowerRenameManager Remove received argments checks from some methods because argument being null or empty string doesnt mean it is invalid or method fails * Fix formatting. Remove overlooked comment. Fix error message. * Change HRESULT declarations according to coding style * Fix unhandled case. Refactor.
This commit is contained in:
parent
4403876320
commit
da22e21a0e
2
.github/actions/spell-check/expect.txt
vendored
2
.github/actions/spell-check/expect.txt
vendored
@ -2126,6 +2126,7 @@ tif
|
||||
TILEDWINDOW
|
||||
timeinfo
|
||||
Timeline
|
||||
timeunion
|
||||
timeutil
|
||||
titlecase
|
||||
tlb
|
||||
@ -2191,6 +2192,7 @@ uint
|
||||
UIPI
|
||||
UIs
|
||||
ul
|
||||
ULARGE
|
||||
ULLONG
|
||||
ulong
|
||||
unchecks
|
||||
|
@ -123,8 +123,8 @@ HRESULT CPowerRenameMenu::InvokeCommand(_In_ LPCMINVOKECOMMANDINFO pici)
|
||||
{
|
||||
Trace::Invoked();
|
||||
InvokeStruct* pInvokeData = new (std::nothrow) InvokeStruct;
|
||||
hr = pInvokeData ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
hr = E_OUTOFMEMORY;
|
||||
if (pInvokeData)
|
||||
{
|
||||
pInvokeData->hwndParent = pici->hwnd;
|
||||
hr = CoMarshalInterThreadInterfaceInStream(__uuidof(m_spdo), m_spdo, &(pInvokeData->pstrm));
|
||||
@ -248,8 +248,8 @@ HRESULT __stdcall CPowerRenameMenu::Invoke(IShellItemArray* psiItemArray, IBindC
|
||||
#endif
|
||||
Trace::Invoked();
|
||||
InvokeStruct* pInvokeData = new (std::nothrow) InvokeStruct;
|
||||
HRESULT hr = pInvokeData ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (pInvokeData)
|
||||
{
|
||||
pInvokeData->hwndParent = nullptr;
|
||||
hr = CoMarshalInterThreadInterfaceInStream(__uuidof(psiItemArray), psiItemArray, &(pInvokeData->pstrm));
|
||||
|
@ -123,9 +123,10 @@ STDAPI DllCanUnloadNow(void)
|
||||
//
|
||||
STDAPI DllGetClassObject(_In_ REFCLSID clsid, _In_ REFIID riid, _Outptr_ void** ppv)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
*ppv = NULL;
|
||||
CPowerRenameClassFactory* pClassFactory = new CPowerRenameClassFactory(clsid);
|
||||
HRESULT hr = pClassFactory->QueryInterface(riid, ppv);
|
||||
hr = pClassFactory->QueryInterface(riid, ppv);
|
||||
pClassFactory->Release();
|
||||
return hr;
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ namespace fs = std::filesystem;
|
||||
|
||||
HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source)
|
||||
{
|
||||
HRESULT hr = (source && wcslen(source) > 0) ? S_OK : E_INVALIDARG;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
if (source)
|
||||
{
|
||||
PWSTR newName = nullptr;
|
||||
hr = SHStrDup(source, &newName);
|
||||
@ -38,8 +38,8 @@ HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source)
|
||||
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags)
|
||||
{
|
||||
std::locale::global(std::locale(""));
|
||||
HRESULT hr = (source && wcslen(source) > 0 && flags) ? S_OK : E_INVALIDARG;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
if (source && flags)
|
||||
{
|
||||
if (flags & Uppercase)
|
||||
{
|
||||
@ -169,7 +169,7 @@ HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR sour
|
||||
return hr;
|
||||
}
|
||||
|
||||
bool isFileAttributesUsed(_In_ PCWSTR source)
|
||||
bool isFileTimeUsed(_In_ PCWSTR source)
|
||||
{
|
||||
bool used = false;
|
||||
std::wstring patterns[] = { L"(([^\\$]|^)(\\$\\$)*)\\$Y", L"(([^\\$]|^)(\\$\\$)*)\\$M", L"(([^\\$]|^)(\\$\\$)*)\\$D",
|
||||
@ -185,11 +185,11 @@ bool isFileAttributesUsed(_In_ PCWSTR source)
|
||||
return used;
|
||||
}
|
||||
|
||||
HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME LocalTime)
|
||||
HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME fileTime)
|
||||
{
|
||||
std::locale::global(std::locale(""));
|
||||
HRESULT hr = (source && wcslen(source) > 0) ? S_OK : E_INVALIDARG;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
if (source && wcslen(source) > 0)
|
||||
{
|
||||
std::wstring res(source);
|
||||
wchar_t replaceTerm[MAX_PATH] = { 0 };
|
||||
@ -201,72 +201,72 @@ HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SY
|
||||
StringCchCopy(localeName, LOCALE_NAME_MAX_LENGTH, L"en_US");
|
||||
}
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%04d"), L"$01", LocalTime.wYear);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%04d"), L"$01", fileTime.wYear);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$YYYY"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", (LocalTime.wYear % 100));
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", (fileTime.wYear % 100));
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$YY"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", (LocalTime.wYear % 10));
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", (fileTime.wYear % 10));
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$Y"), replaceTerm);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &LocalTime, L"MMMM", formattedDate, MAX_PATH, NULL);
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"MMMM", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", formattedDate);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$MMMM"), replaceTerm);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &LocalTime, L"MMM", formattedDate, MAX_PATH, NULL);
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"MMM", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", formattedDate);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$MMM"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", LocalTime.wMonth);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wMonth);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$MM"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", LocalTime.wMonth);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wMonth);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$M"), replaceTerm);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &LocalTime, L"dddd", formattedDate, MAX_PATH, NULL);
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"dddd", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", formattedDate);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$DDDD"), replaceTerm);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &LocalTime, L"ddd", formattedDate, MAX_PATH, NULL);
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"ddd", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", formattedDate);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$DDD"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", LocalTime.wDay);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wDay);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$DD"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", LocalTime.wDay);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wDay);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$D"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", LocalTime.wHour);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wHour);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$hh"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", LocalTime.wHour);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wHour);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$h"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", LocalTime.wMinute);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wMinute);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$mm"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", LocalTime.wMinute);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wMinute);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$m"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", LocalTime.wSecond);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wSecond);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$ss"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", LocalTime.wSecond);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wSecond);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$s"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%03d"), L"$01", LocalTime.wMilliseconds);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%03d"), L"$01", fileTime.wMilliseconds);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$fff"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", LocalTime.wMilliseconds/10);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wMilliseconds/10);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$ff"), replaceTerm);
|
||||
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", LocalTime.wMilliseconds/100);
|
||||
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wMilliseconds/100);
|
||||
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$f"), replaceTerm);
|
||||
|
||||
hr = StringCchCopy(result, cchMax, res.c_str());
|
||||
@ -346,12 +346,11 @@ HRESULT _ParseEnumItems(_In_ IEnumShellItems* pesi, _In_ IPowerRenameManager* ps
|
||||
HRESULT EnumerateDataObject(_In_ IUnknown* dataSource, _In_ IPowerRenameManager* psrm)
|
||||
{
|
||||
CComPtr<IShellItemArray> spsia;
|
||||
HRESULT hr = _GetShellItemArrayFromDataOject(dataSource, &spsia);
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_FAIL;
|
||||
if (SUCCEEDED(_GetShellItemArrayFromDataOject(dataSource, &spsia)))
|
||||
{
|
||||
CComPtr<IEnumShellItems> spesi;
|
||||
hr = spsia->EnumItems(&spesi);
|
||||
if (SUCCEEDED(hr))
|
||||
if (SUCCEEDED(spsia->EnumItems(&spesi)))
|
||||
{
|
||||
hr = _ParseEnumItems(spesi, psrm);
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source);
|
||||
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags);
|
||||
HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME LocalTime);
|
||||
bool isFileAttributesUsed(_In_ PCWSTR source);
|
||||
HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME fileTime);
|
||||
bool isFileTimeUsed(_In_ PCWSTR source);
|
||||
bool DataObjectContainsRenamableItem(_In_ IUnknown* dataSource);
|
||||
HRESULT EnumerateDataObject(_In_ IUnknown* pdo, _In_ IPowerRenameManager* psrm);
|
||||
BOOL GetEnumeratedFileName(
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
IFACEMETHOD(OnSearchTermChanged)(_In_ PCWSTR searchTerm) = 0;
|
||||
IFACEMETHOD(OnReplaceTermChanged)(_In_ PCWSTR replaceTerm) = 0;
|
||||
IFACEMETHOD(OnFlagsChanged)(_In_ DWORD flags) = 0;
|
||||
IFACEMETHOD(OnFileTimeChanged)(_In_ SYSTEMTIME fileTime) = 0;
|
||||
};
|
||||
|
||||
interface __declspec(uuid("E3ED45B5-9CE0-47E2-A595-67EB950B9B72")) IPowerRenameRegEx : public IUnknown
|
||||
@ -44,6 +45,8 @@ public:
|
||||
IFACEMETHOD(PutReplaceTerm)(_In_ PCWSTR replaceTerm) = 0;
|
||||
IFACEMETHOD(GetFlags)(_Out_ DWORD* flags) = 0;
|
||||
IFACEMETHOD(PutFlags)(_In_ DWORD flags) = 0;
|
||||
IFACEMETHOD(PutFileTime)(_In_ SYSTEMTIME fileTime) = 0;
|
||||
IFACEMETHOD(ResetFileTime)() = 0;
|
||||
IFACEMETHOD(Replace)(_In_ PCWSTR source, _Outptr_ PWSTR* result) = 0;
|
||||
};
|
||||
|
||||
@ -51,7 +54,7 @@ interface __declspec(uuid("C7F59201-4DE1-4855-A3A2-26FC3279C8A5")) IPowerRenameI
|
||||
{
|
||||
public:
|
||||
IFACEMETHOD(GetPath)(_Outptr_ PWSTR* path) = 0;
|
||||
IFACEMETHOD(GetDate)(_Outptr_ SYSTEMTIME* date) = 0;
|
||||
IFACEMETHOD(GetTime)(_Outptr_ SYSTEMTIME* time) = 0;
|
||||
IFACEMETHOD(GetShellItem)(_Outptr_ IShellItem** ppsi) = 0;
|
||||
IFACEMETHOD(GetOriginalName)(_Outptr_ PWSTR* originalName) = 0;
|
||||
IFACEMETHOD(GetNewName)(_Outptr_ PWSTR* newName) = 0;
|
||||
|
@ -34,19 +34,24 @@ IFACEMETHODIMP CPowerRenameItem::GetPath(_Outptr_ PWSTR* path)
|
||||
{
|
||||
*path = nullptr;
|
||||
CSRWSharedAutoLock lock(&m_lock);
|
||||
HRESULT hr = m_path ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_FAIL;
|
||||
if (m_path)
|
||||
{
|
||||
hr = SHStrDup(m_path, path);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP CPowerRenameItem::GetDate(_Outptr_ SYSTEMTIME* date)
|
||||
IFACEMETHODIMP CPowerRenameItem::GetTime(_Outptr_ SYSTEMTIME* time)
|
||||
{
|
||||
CSRWSharedAutoLock lock(&m_lock);
|
||||
HRESULT hr = m_isDateParsed ? S_OK : E_FAIL ;
|
||||
if (!m_isDateParsed)
|
||||
HRESULT hr = E_FAIL ;
|
||||
|
||||
if (m_isTimeParsed)
|
||||
{
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE hFile = CreateFileW(m_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
@ -59,8 +64,8 @@ IFACEMETHODIMP CPowerRenameItem::GetDate(_Outptr_ SYSTEMTIME* date)
|
||||
{
|
||||
if (SystemTimeToTzSpecificLocalTime(NULL, &SystemTime, &LocalTime))
|
||||
{
|
||||
m_date = LocalTime;
|
||||
m_isDateParsed = true;
|
||||
m_time = LocalTime;
|
||||
m_isTimeParsed = true;
|
||||
hr = S_OK;
|
||||
}
|
||||
}
|
||||
@ -68,7 +73,7 @@ IFACEMETHODIMP CPowerRenameItem::GetDate(_Outptr_ SYSTEMTIME* date)
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
*date = m_date;
|
||||
*time = m_time;
|
||||
return hr;
|
||||
}
|
||||
|
||||
@ -80,8 +85,8 @@ IFACEMETHODIMP CPowerRenameItem::GetShellItem(_Outptr_ IShellItem** ppsi)
|
||||
IFACEMETHODIMP CPowerRenameItem::GetOriginalName(_Outptr_ PWSTR* originalName)
|
||||
{
|
||||
CSRWSharedAutoLock lock(&m_lock);
|
||||
HRESULT hr = m_originalName ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_FAIL;
|
||||
if (m_originalName)
|
||||
{
|
||||
hr = SHStrDup(m_originalName, originalName);
|
||||
}
|
||||
@ -104,8 +109,8 @@ IFACEMETHODIMP CPowerRenameItem::PutNewName(_In_opt_ PCWSTR newName)
|
||||
IFACEMETHODIMP CPowerRenameItem::GetNewName(_Outptr_ PWSTR* newName)
|
||||
{
|
||||
CSRWSharedAutoLock lock(&m_lock);
|
||||
HRESULT hr = m_newName ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = S_OK;
|
||||
if (m_newName)
|
||||
{
|
||||
hr = SHStrDup(m_newName, newName);
|
||||
}
|
||||
@ -217,9 +222,10 @@ HRESULT CPowerRenameItem::s_CreateInstance(_In_opt_ IShellItem* psi, _In_ REFIID
|
||||
*resultInterface = nullptr;
|
||||
|
||||
CPowerRenameItem *newRenameItem = new CPowerRenameItem();
|
||||
HRESULT hr = newRenameItem ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (newRenameItem)
|
||||
{
|
||||
hr = S_OK ;
|
||||
if (psi != nullptr)
|
||||
{
|
||||
hr = newRenameItem->_Init(psi);
|
||||
|
@ -15,7 +15,7 @@ public:
|
||||
|
||||
// IPowerRenameItem
|
||||
IFACEMETHODIMP GetPath(_Outptr_ PWSTR* path);
|
||||
IFACEMETHODIMP GetDate(_Outptr_ SYSTEMTIME* date);
|
||||
IFACEMETHODIMP GetTime(_Outptr_ SYSTEMTIME* time);
|
||||
IFACEMETHODIMP GetShellItem(_Outptr_ IShellItem** ppsi);
|
||||
IFACEMETHODIMP GetOriginalName(_Outptr_ PWSTR* originalName);
|
||||
IFACEMETHODIMP PutNewName(_In_opt_ PCWSTR newName);
|
||||
@ -50,7 +50,7 @@ protected:
|
||||
|
||||
bool m_selected = true;
|
||||
bool m_isFolder = false;
|
||||
bool m_isDateParsed = false;
|
||||
bool m_isTimeParsed = false;
|
||||
bool m_canRename = true;
|
||||
int m_id = -1;
|
||||
int m_iconIndex = -1;
|
||||
@ -59,7 +59,7 @@ protected:
|
||||
PWSTR m_path = nullptr;
|
||||
PWSTR m_originalName = nullptr;
|
||||
PWSTR m_newName = nullptr;
|
||||
SYSTEMTIME m_date;
|
||||
SYSTEMTIME m_time = {0};
|
||||
CSRWLock m_lock;
|
||||
long m_refCount = 0;
|
||||
};
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "window_helpers.h"
|
||||
#include <filesystem>
|
||||
#include "trace.h"
|
||||
#include <winrt/base.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@ -415,12 +416,18 @@ IFACEMETHODIMP CPowerRenameManager::OnFlagsChanged(_In_ DWORD flags)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP CPowerRenameManager::OnFileTimeChanged(_In_ SYSTEMTIME /*fileTime*/)
|
||||
{
|
||||
_PerformRegExRename();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CPowerRenameManager::s_CreateInstance(_Outptr_ IPowerRenameManager** ppsrm)
|
||||
{
|
||||
*ppsrm = nullptr;
|
||||
CPowerRenameManager *psrm = new CPowerRenameManager();
|
||||
HRESULT hr = psrm ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (psrm)
|
||||
{
|
||||
hr = psrm->_Init();
|
||||
if (SUCCEEDED(hr))
|
||||
@ -645,16 +652,20 @@ HRESULT CPowerRenameManager::_PerformFileOperation()
|
||||
HRESULT CPowerRenameManager::_CreateFileOpWorkerThread()
|
||||
{
|
||||
WorkerThreadData* pwtd = new WorkerThreadData;
|
||||
HRESULT hr = pwtd ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (pwtd)
|
||||
{
|
||||
pwtd->hwndManager = m_hwndMessage;
|
||||
pwtd->startEvent = m_startRegExWorkerEvent;
|
||||
pwtd->cancelEvent = nullptr;
|
||||
pwtd->spsrm = this;
|
||||
m_fileOpWorkerThreadHandle = CreateThread(nullptr, 0, s_fileOpWorkerThread, pwtd, 0, nullptr);
|
||||
hr = (m_fileOpWorkerThreadHandle) ? S_OK : E_FAIL;
|
||||
if (FAILED(hr))
|
||||
hr = E_FAIL;
|
||||
if (m_fileOpWorkerThreadHandle)
|
||||
{
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pwtd;
|
||||
}
|
||||
@ -791,8 +802,8 @@ HRESULT CPowerRenameManager::_PerformRegExRename()
|
||||
HRESULT CPowerRenameManager::_CreateRegExWorkerThread()
|
||||
{
|
||||
WorkerThreadData* pwtd = new WorkerThreadData;
|
||||
HRESULT hr = pwtd ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (pwtd)
|
||||
{
|
||||
pwtd->hwndManager = m_hwndMessage;
|
||||
pwtd->startEvent = m_startRegExWorkerEvent;
|
||||
@ -800,8 +811,12 @@ HRESULT CPowerRenameManager::_CreateRegExWorkerThread()
|
||||
pwtd->hwndParent = m_hwndParent;
|
||||
pwtd->spsrm = this;
|
||||
m_regExWorkerThreadHandle = CreateThread(nullptr, 0, s_regexWorkerThread, pwtd, 0, nullptr);
|
||||
hr = (m_regExWorkerThreadHandle) ? S_OK : E_FAIL;
|
||||
if (FAILED(hr))
|
||||
hr = E_FAIL;
|
||||
if (m_regExWorkerThreadHandle)
|
||||
{
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pwtd;
|
||||
}
|
||||
@ -812,8 +827,9 @@ HRESULT CPowerRenameManager::_CreateRegExWorkerThread()
|
||||
|
||||
DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
|
||||
{
|
||||
if (SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)))
|
||||
try
|
||||
{
|
||||
winrt::check_hresult(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
|
||||
WorkerThreadData* pwtd = reinterpret_cast<WorkerThreadData*>(pv);
|
||||
if (pwtd)
|
||||
{
|
||||
@ -823,192 +839,201 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
|
||||
if (WaitForSingleObject(pwtd->startEvent, INFINITE) == WAIT_OBJECT_0)
|
||||
{
|
||||
CComPtr<IPowerRenameRegEx> spRenameRegEx;
|
||||
if (SUCCEEDED(pwtd->spsrm->GetRenameRegEx(&spRenameRegEx)))
|
||||
|
||||
winrt::check_hresult(pwtd->spsrm->GetRenameRegEx(&spRenameRegEx));
|
||||
|
||||
DWORD flags = 0;
|
||||
winrt::check_hresult(spRenameRegEx->GetFlags(&flags));
|
||||
|
||||
PWSTR replaceTerm = nullptr;
|
||||
bool useFileTime = false;
|
||||
|
||||
winrt::check_hresult(spRenameRegEx->GetReplaceTerm(&replaceTerm));
|
||||
|
||||
if (isFileTimeUsed(replaceTerm))
|
||||
{
|
||||
DWORD flags = 0;
|
||||
spRenameRegEx->GetFlags(&flags);
|
||||
useFileTime = true;
|
||||
}
|
||||
|
||||
UINT itemCount = 0;
|
||||
unsigned long itemEnumIndex = 1;
|
||||
pwtd->spsrm->GetItemCount(&itemCount);
|
||||
for (UINT u = 0; u <= itemCount; u++)
|
||||
UINT itemCount = 0;
|
||||
unsigned long itemEnumIndex = 1;
|
||||
winrt::check_hresult(pwtd->spsrm->GetItemCount(&itemCount));
|
||||
for (UINT u = 0; u < itemCount; u++)
|
||||
{
|
||||
// Check if cancel event is signaled
|
||||
if (WaitForSingleObject(pwtd->cancelEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
// Check if cancel event is signaled
|
||||
if (WaitForSingleObject(pwtd->cancelEvent, 0) == WAIT_OBJECT_0)
|
||||
// Canceled from manager
|
||||
// Send the manager thread the canceled message
|
||||
PostMessage(pwtd->hwndManager, SRM_REGEX_CANCELED, GetCurrentThreadId(), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
CComPtr<IPowerRenameItem> spItem;
|
||||
winrt::check_hresult(pwtd->spsrm->GetItemByIndex(u, &spItem));
|
||||
|
||||
int id = -1;
|
||||
winrt::check_hresult(spItem->GetId(&id));
|
||||
|
||||
bool isFolder = false;
|
||||
bool isSubFolderContent = false;
|
||||
winrt::check_hresult(spItem->GetIsFolder(&isFolder));
|
||||
winrt::check_hresult(spItem->GetIsSubFolderContent(&isSubFolderContent));
|
||||
if ((isFolder && (flags & PowerRenameFlags::ExcludeFolders)) ||
|
||||
(!isFolder && (flags & PowerRenameFlags::ExcludeFiles)) ||
|
||||
(isSubFolderContent && (flags & PowerRenameFlags::ExcludeSubfolders)))
|
||||
{
|
||||
// Exclude this item from renaming. Ensure new name is cleared.
|
||||
winrt::check_hresult(spItem->PutNewName(nullptr));
|
||||
|
||||
// Send the manager thread the item processed message
|
||||
PostMessage(pwtd->hwndManager, SRM_REGEX_ITEM_UPDATED, GetCurrentThreadId(), id);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
PWSTR originalName = nullptr;
|
||||
winrt::check_hresult(spItem->GetOriginalName(&originalName));
|
||||
|
||||
|
||||
PWSTR currentNewName = nullptr;
|
||||
winrt::check_hresult(spItem->GetNewName(¤tNewName));
|
||||
|
||||
wchar_t sourceName[MAX_PATH] = { 0 };
|
||||
if (flags & NameOnly)
|
||||
{
|
||||
StringCchCopy(sourceName, ARRAYSIZE(sourceName), fs::path(originalName).stem().c_str());
|
||||
}
|
||||
else if (flags & ExtensionOnly)
|
||||
{
|
||||
std::wstring extension = fs::path(originalName).extension().wstring();
|
||||
if (!extension.empty() && extension.front() == '.')
|
||||
{
|
||||
// Canceled from manager
|
||||
// Send the manager thread the canceled message
|
||||
PostMessage(pwtd->hwndManager, SRM_REGEX_CANCELED, GetCurrentThreadId(), 0);
|
||||
break;
|
||||
extension = extension.erase(0, 1);
|
||||
}
|
||||
StringCchCopy(sourceName, ARRAYSIZE(sourceName), extension.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchCopy(sourceName, ARRAYSIZE(sourceName), originalName);
|
||||
}
|
||||
|
||||
CComPtr<IPowerRenameItem> spItem;
|
||||
if (SUCCEEDED(pwtd->spsrm->GetItemByIndex(u, &spItem)))
|
||||
SYSTEMTIME fileTime = { 0 };
|
||||
|
||||
if (useFileTime)
|
||||
{
|
||||
winrt::check_hresult(spItem->GetTime(&fileTime));
|
||||
winrt::check_hresult(spRenameRegEx->PutFileTime(fileTime));
|
||||
}
|
||||
|
||||
PWSTR newName = nullptr;
|
||||
|
||||
// Failure here means we didn't match anything or had nothing to match
|
||||
// Call put_newName with null in that case to reset it
|
||||
winrt::check_hresult(spRenameRegEx->Replace(sourceName, &newName));
|
||||
|
||||
if (useFileTime)
|
||||
{
|
||||
winrt::check_hresult(spRenameRegEx->ResetFileTime());
|
||||
}
|
||||
|
||||
wchar_t resultName[MAX_PATH] = { 0 };
|
||||
|
||||
PWSTR newNameToUse = nullptr;
|
||||
|
||||
// newName == nullptr likely means we have an empty search string. We should leave newNameToUse
|
||||
// as nullptr so we clear the renamed column
|
||||
// Except string transformation is selected.
|
||||
|
||||
if (newName == nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase))
|
||||
{
|
||||
SHStrDup(sourceName, &newName);
|
||||
}
|
||||
|
||||
if (newName != nullptr)
|
||||
{
|
||||
newNameToUse = resultName;
|
||||
if (flags & NameOnly)
|
||||
{
|
||||
int id = -1;
|
||||
spItem->GetId(&id);
|
||||
|
||||
bool isFolder = false;
|
||||
bool isSubFolderContent = false;
|
||||
spItem->GetIsFolder(&isFolder);
|
||||
spItem->GetIsSubFolderContent(&isSubFolderContent);
|
||||
if ((isFolder && (flags & PowerRenameFlags::ExcludeFolders)) ||
|
||||
(!isFolder && (flags & PowerRenameFlags::ExcludeFiles)) ||
|
||||
(isSubFolderContent && (flags & PowerRenameFlags::ExcludeSubfolders)))
|
||||
StringCchPrintf(resultName, ARRAYSIZE(resultName), L"%s%s", newName, fs::path(originalName).extension().c_str());
|
||||
}
|
||||
else if (flags & ExtensionOnly)
|
||||
{
|
||||
std::wstring extension = fs::path(originalName).extension().wstring();
|
||||
if (!extension.empty())
|
||||
{
|
||||
// Exclude this item from renaming. Ensure new name is cleared.
|
||||
spItem->PutNewName(nullptr);
|
||||
|
||||
// Send the manager thread the item processed message
|
||||
PostMessage(pwtd->hwndManager, SRM_REGEX_ITEM_UPDATED, GetCurrentThreadId(), id);
|
||||
|
||||
continue;
|
||||
StringCchPrintf(resultName, ARRAYSIZE(resultName), L"%s.%s", fs::path(originalName).stem().c_str(), newName);
|
||||
}
|
||||
|
||||
PWSTR originalName = nullptr;
|
||||
if (SUCCEEDED(spItem->GetOriginalName(&originalName)))
|
||||
else
|
||||
{
|
||||
PWSTR currentNewName = nullptr;
|
||||
spItem->GetNewName(¤tNewName);
|
||||
|
||||
wchar_t sourceName[MAX_PATH] = { 0 };
|
||||
if (flags & NameOnly)
|
||||
{
|
||||
StringCchCopy(sourceName, ARRAYSIZE(sourceName), fs::path(originalName).stem().c_str());
|
||||
}
|
||||
else if (flags & ExtensionOnly)
|
||||
{
|
||||
std::wstring extension = fs::path(originalName).extension().wstring();
|
||||
if (!extension.empty() && extension.front() == '.')
|
||||
{
|
||||
extension = extension.erase(0, 1);
|
||||
}
|
||||
StringCchCopy(sourceName, ARRAYSIZE(sourceName), extension.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchCopy(sourceName, ARRAYSIZE(sourceName), originalName);
|
||||
}
|
||||
|
||||
wchar_t newReplaceTerm[MAX_PATH] = { 0 };
|
||||
PWSTR replaceTerm = nullptr;
|
||||
SYSTEMTIME LocalTime;
|
||||
|
||||
if (SUCCEEDED(spRenameRegEx->GetReplaceTerm(&replaceTerm)) && isFileAttributesUsed(replaceTerm))
|
||||
{
|
||||
if (SUCCEEDED(spItem->GetDate(&LocalTime)))
|
||||
{
|
||||
if (SUCCEEDED(GetDatedFileName(newReplaceTerm, ARRAYSIZE(newReplaceTerm), replaceTerm, LocalTime)))
|
||||
{
|
||||
spRenameRegEx->PutReplaceTerm(newReplaceTerm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PWSTR newName = nullptr;
|
||||
// Failure here means we didn't match anything or had nothing to match
|
||||
// Call put_newName with null in that case to reset it
|
||||
spRenameRegEx->Replace(sourceName, &newName);
|
||||
|
||||
spRenameRegEx->PutReplaceTerm(replaceTerm);
|
||||
|
||||
wchar_t resultName[MAX_PATH] = { 0 };
|
||||
|
||||
PWSTR newNameToUse = nullptr;
|
||||
|
||||
// newName == nullptr likely means we have an empty search string. We should leave newNameToUse
|
||||
// as nullptr so we clear the renamed column
|
||||
// Except string transformation is selected.
|
||||
|
||||
if (newName == nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase))
|
||||
{
|
||||
SHStrDup(sourceName, &newName);
|
||||
}
|
||||
|
||||
if (newName != nullptr)
|
||||
{
|
||||
newNameToUse = resultName;
|
||||
if (flags & NameOnly)
|
||||
{
|
||||
StringCchPrintf(resultName, ARRAYSIZE(resultName), L"%s%s", newName, fs::path(originalName).extension().c_str());
|
||||
}
|
||||
else if (flags & ExtensionOnly)
|
||||
{
|
||||
std::wstring extension = fs::path(originalName).extension().wstring();
|
||||
if (!extension.empty())
|
||||
{
|
||||
StringCchPrintf(resultName, ARRAYSIZE(resultName), L"%s.%s", fs::path(originalName).stem().c_str(), newName);
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchCopy(resultName, ARRAYSIZE(resultName), originalName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchCopy(resultName, ARRAYSIZE(resultName), newName);
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t trimmedName[MAX_PATH] = { 0 };
|
||||
if (newNameToUse != nullptr && SUCCEEDED(GetTrimmedFileName(trimmedName, ARRAYSIZE(trimmedName), newNameToUse)))
|
||||
{
|
||||
newNameToUse = trimmedName;
|
||||
}
|
||||
|
||||
wchar_t transformedName[MAX_PATH] = { 0 };
|
||||
if (newNameToUse != nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase))
|
||||
{
|
||||
if (SUCCEEDED(GetTransformedFileName(transformedName, ARRAYSIZE(transformedName), newNameToUse, flags)))
|
||||
{
|
||||
newNameToUse = transformedName;
|
||||
}
|
||||
}
|
||||
|
||||
// No change from originalName so set newName to
|
||||
// null so we clear it from our UI as well.
|
||||
if (lstrcmp(originalName, newNameToUse) == 0)
|
||||
{
|
||||
newNameToUse = nullptr;
|
||||
}
|
||||
|
||||
wchar_t uniqueName[MAX_PATH] = { 0 };
|
||||
if (newNameToUse != nullptr && (flags & EnumerateItems))
|
||||
{
|
||||
unsigned long countUsed = 0;
|
||||
if (GetEnumeratedFileName(uniqueName, ARRAYSIZE(uniqueName), newNameToUse, nullptr, itemEnumIndex, &countUsed))
|
||||
{
|
||||
newNameToUse = uniqueName;
|
||||
}
|
||||
itemEnumIndex++;
|
||||
}
|
||||
|
||||
spItem->PutNewName(newNameToUse);
|
||||
|
||||
// Was there a change?
|
||||
if (lstrcmp(currentNewName, newNameToUse) != 0)
|
||||
{
|
||||
// Send the manager thread the item processed message
|
||||
PostMessage(pwtd->hwndManager, SRM_REGEX_ITEM_UPDATED, GetCurrentThreadId(), id);
|
||||
}
|
||||
|
||||
CoTaskMemFree(newName);
|
||||
CoTaskMemFree(replaceTerm);
|
||||
CoTaskMemFree(currentNewName);
|
||||
CoTaskMemFree(originalName);
|
||||
StringCchCopy(resultName, ARRAYSIZE(resultName), originalName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchCopy(resultName, ARRAYSIZE(resultName), newName);
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t trimmedName[MAX_PATH] = { 0 };
|
||||
if (newNameToUse != nullptr)
|
||||
{
|
||||
winrt::check_hresult(GetTrimmedFileName(trimmedName, ARRAYSIZE(trimmedName), newNameToUse));
|
||||
newNameToUse = trimmedName;
|
||||
}
|
||||
|
||||
wchar_t transformedName[MAX_PATH] = { 0 };
|
||||
if (newNameToUse != nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase))
|
||||
{
|
||||
winrt::check_hresult(GetTransformedFileName(transformedName, ARRAYSIZE(transformedName), newNameToUse, flags));
|
||||
newNameToUse = transformedName;
|
||||
}
|
||||
|
||||
// No change from originalName so set newName to
|
||||
// null so we clear it from our UI as well.
|
||||
if (lstrcmp(originalName, newNameToUse) == 0)
|
||||
{
|
||||
newNameToUse = nullptr;
|
||||
}
|
||||
|
||||
wchar_t uniqueName[MAX_PATH] = { 0 };
|
||||
if (newNameToUse != nullptr && (flags & EnumerateItems))
|
||||
{
|
||||
unsigned long countUsed = 0;
|
||||
if (GetEnumeratedFileName(uniqueName, ARRAYSIZE(uniqueName), newNameToUse, nullptr, itemEnumIndex, &countUsed))
|
||||
{
|
||||
newNameToUse = uniqueName;
|
||||
}
|
||||
itemEnumIndex++;
|
||||
}
|
||||
|
||||
winrt::check_hresult(spItem->PutNewName(newNameToUse));
|
||||
|
||||
// Was there a change?
|
||||
if (lstrcmp(currentNewName, newNameToUse) != 0)
|
||||
{
|
||||
// Send the manager thread the item processed message
|
||||
PostMessage(pwtd->hwndManager, SRM_REGEX_ITEM_UPDATED, GetCurrentThreadId(), id);
|
||||
}
|
||||
CoTaskMemFree(newName);
|
||||
CoTaskMemFree(currentNewName);
|
||||
CoTaskMemFree(originalName);
|
||||
}
|
||||
CoTaskMemFree(replaceTerm);
|
||||
}
|
||||
|
||||
// Send the manager thread the completion message
|
||||
PostMessage(pwtd->hwndManager, SRM_REGEX_COMPLETE, GetCurrentThreadId(), 0);
|
||||
|
||||
delete pwtd;
|
||||
|
||||
}
|
||||
CoUninitialize();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
MessageBox(NULL, L"RegexWorkerThread failed to execute.\nPlease report the bug to https://aka.ms/powerToysReportBug", L"PowerRename Error", MB_OK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ public:
|
||||
IFACEMETHODIMP OnSearchTermChanged(_In_ PCWSTR searchTerm);
|
||||
IFACEMETHODIMP OnReplaceTermChanged(_In_ PCWSTR replaceTerm);
|
||||
IFACEMETHODIMP OnFlagsChanged(_In_ DWORD flags);
|
||||
IFACEMETHODIMP OnFileTimeChanged(_In_ SYSTEMTIME fileTime);
|
||||
|
||||
static HRESULT s_CreateInstance(_Outptr_ IPowerRenameManager** ppsrm);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <helpers.cpp>
|
||||
|
||||
using namespace std;
|
||||
using std::regex_error;
|
||||
@ -76,8 +76,8 @@ IFACEMETHODIMP CPowerRenameRegEx::UnAdvise(_In_ DWORD cookie)
|
||||
IFACEMETHODIMP CPowerRenameRegEx::GetSearchTerm(_Outptr_ PWSTR* searchTerm)
|
||||
{
|
||||
*searchTerm = nullptr;
|
||||
HRESULT hr = m_searchTerm ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = S_OK;
|
||||
if (m_searchTerm)
|
||||
{
|
||||
CSRWSharedAutoLock lock(&m_lock);
|
||||
hr = SHStrDup(m_searchTerm, searchTerm);
|
||||
@ -88,8 +88,8 @@ IFACEMETHODIMP CPowerRenameRegEx::GetSearchTerm(_Outptr_ PWSTR* searchTerm)
|
||||
IFACEMETHODIMP CPowerRenameRegEx::PutSearchTerm(_In_ PCWSTR searchTerm)
|
||||
{
|
||||
bool changed = false;
|
||||
HRESULT hr = searchTerm ? S_OK : E_INVALIDARG;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = S_OK;
|
||||
if (searchTerm)
|
||||
{
|
||||
CSRWExclusiveAutoLock lock(&m_lock);
|
||||
if (m_searchTerm == nullptr || lstrcmp(searchTerm, m_searchTerm) != 0)
|
||||
@ -111,8 +111,8 @@ IFACEMETHODIMP CPowerRenameRegEx::PutSearchTerm(_In_ PCWSTR searchTerm)
|
||||
IFACEMETHODIMP CPowerRenameRegEx::GetReplaceTerm(_Outptr_ PWSTR* replaceTerm)
|
||||
{
|
||||
*replaceTerm = nullptr;
|
||||
HRESULT hr = m_replaceTerm ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = S_OK;
|
||||
if (m_replaceTerm)
|
||||
{
|
||||
CSRWSharedAutoLock lock(&m_lock);
|
||||
hr = SHStrDup(m_replaceTerm, replaceTerm);
|
||||
@ -123,8 +123,8 @@ IFACEMETHODIMP CPowerRenameRegEx::GetReplaceTerm(_Outptr_ PWSTR* replaceTerm)
|
||||
IFACEMETHODIMP CPowerRenameRegEx::PutReplaceTerm(_In_ PCWSTR replaceTerm)
|
||||
{
|
||||
bool changed = false;
|
||||
HRESULT hr = replaceTerm ? S_OK : E_INVALIDARG;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = S_OK;
|
||||
if (replaceTerm)
|
||||
{
|
||||
CSRWExclusiveAutoLock lock(&m_lock);
|
||||
if (m_replaceTerm == nullptr || lstrcmp(replaceTerm, m_replaceTerm) != 0)
|
||||
@ -159,13 +159,45 @@ IFACEMETHODIMP CPowerRenameRegEx::PutFlags(_In_ DWORD flags)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP CPowerRenameRegEx::PutFileTime(_In_ SYSTEMTIME fileTime)
|
||||
{
|
||||
union timeunion
|
||||
{
|
||||
FILETIME fileTime;
|
||||
ULARGE_INTEGER ul;
|
||||
};
|
||||
|
||||
timeunion ft1;
|
||||
timeunion ft2;
|
||||
|
||||
SystemTimeToFileTime(&m_fileTime, &ft1.fileTime);
|
||||
SystemTimeToFileTime(&fileTime, &ft2.fileTime);
|
||||
|
||||
if (ft2.ul.QuadPart != ft1.ul.QuadPart)
|
||||
{
|
||||
m_fileTime = fileTime;
|
||||
m_useFileTime = true;
|
||||
_OnFileTimeChanged();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP CPowerRenameRegEx::ResetFileTime()
|
||||
{
|
||||
SYSTEMTIME ZERO = { 0 };
|
||||
m_fileTime = ZERO;
|
||||
m_useFileTime = false;
|
||||
_OnFileTimeChanged();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CPowerRenameRegEx::s_CreateInstance(_Outptr_ IPowerRenameRegEx** renameRegEx)
|
||||
{
|
||||
*renameRegEx = nullptr;
|
||||
|
||||
CPowerRenameRegEx *newRenameRegEx = new CPowerRenameRegEx();
|
||||
HRESULT hr = newRenameRegEx ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (newRenameRegEx)
|
||||
{
|
||||
hr = newRenameRegEx->QueryInterface(IID_PPV_ARGS(renameRegEx));
|
||||
newRenameRegEx->Release();
|
||||
@ -194,73 +226,90 @@ HRESULT CPowerRenameRegEx::Replace(_In_ PCWSTR source, _Outptr_ PWSTR* result)
|
||||
*result = nullptr;
|
||||
|
||||
CSRWSharedAutoLock lock(&m_lock);
|
||||
HRESULT hr = (source && wcslen(source) > 0 && m_searchTerm && wcslen(m_searchTerm) > 0) ? S_OK : E_INVALIDARG;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = S_OK;
|
||||
if (!(m_searchTerm && wcslen(m_searchTerm) > 0 && source && wcslen(source) > 0))
|
||||
{
|
||||
wstring res = source;
|
||||
try
|
||||
return hr;
|
||||
}
|
||||
wstring res = source;
|
||||
try
|
||||
{
|
||||
// TODO: creating the regex could be costly. May want to cache this.
|
||||
wchar_t newReplaceTerm[MAX_PATH] = { 0 };
|
||||
bool fileTimeErrorOccurred = false;
|
||||
if (m_useFileTime)
|
||||
{
|
||||
// TODO: creating the regex could be costly. May want to cache this.
|
||||
std::wstring sourceToUse(source);
|
||||
std::wstring searchTerm(m_searchTerm);
|
||||
std::wstring replaceTerm(m_replaceTerm ? wstring(m_replaceTerm) : wstring(L""));
|
||||
if (FAILED(GetDatedFileName(newReplaceTerm, ARRAYSIZE(newReplaceTerm), m_replaceTerm, m_fileTime)))
|
||||
fileTimeErrorOccurred = true;
|
||||
}
|
||||
|
||||
replaceTerm = regex_replace(replaceTerm, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$[0]"), L"$1$$$0");
|
||||
replaceTerm = regex_replace(replaceTerm, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$([1-9])"), L"$1$0$4");
|
||||
std::wstring sourceToUse(source);
|
||||
std::wstring searchTerm(m_searchTerm);
|
||||
std::wstring replaceTerm(L"");
|
||||
if (m_useFileTime && !fileTimeErrorOccurred)
|
||||
{
|
||||
replaceTerm = wstring(newReplaceTerm);
|
||||
}
|
||||
else if (m_replaceTerm)
|
||||
{
|
||||
replaceTerm = wstring(m_replaceTerm);
|
||||
}
|
||||
|
||||
if (m_flags & UseRegularExpressions)
|
||||
replaceTerm = regex_replace(replaceTerm, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$[0]"), L"$1$$$0");
|
||||
replaceTerm = regex_replace(replaceTerm, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$([1-9])"), L"$1$0$4");
|
||||
|
||||
if (m_flags & UseRegularExpressions)
|
||||
{
|
||||
if (_useBoostLib)
|
||||
{
|
||||
if (_useBoostLib)
|
||||
boost::wregex pattern(m_searchTerm, (!(m_flags & CaseSensitive)) ? boost::regex::icase | boost::regex::ECMAScript : boost::regex::ECMAScript);
|
||||
if (m_flags & MatchAllOccurences)
|
||||
{
|
||||
boost::wregex pattern(m_searchTerm, (!(m_flags & CaseSensitive)) ? boost::regex::icase | boost::regex::ECMAScript : boost::regex::ECMAScript);
|
||||
if (m_flags & MatchAllOccurences)
|
||||
{
|
||||
res = boost::regex_replace(wstring(source), pattern, replaceTerm);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = boost::regex_replace(wstring(source), pattern, replaceTerm, boost::regex_constants::format_first_only);
|
||||
}
|
||||
res = boost::regex_replace(wstring(source), pattern, replaceTerm);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wregex pattern(m_searchTerm, (!(m_flags & CaseSensitive)) ? regex_constants::icase | regex_constants::ECMAScript : regex_constants::ECMAScript);
|
||||
if (m_flags & MatchAllOccurences)
|
||||
{
|
||||
res = regex_replace(wstring(source), pattern, replaceTerm);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = regex_replace(wstring(source), pattern, replaceTerm, regex_constants::format_first_only);
|
||||
}
|
||||
res = boost::regex_replace(wstring(source), pattern, replaceTerm, boost::regex_constants::format_first_only);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple search and replace
|
||||
size_t pos = 0;
|
||||
do
|
||||
std::wregex pattern(m_searchTerm, (!(m_flags & CaseSensitive)) ? regex_constants::icase | regex_constants::ECMAScript : regex_constants::ECMAScript);
|
||||
if (m_flags & MatchAllOccurences)
|
||||
{
|
||||
pos = _Find(sourceToUse, searchTerm, (!(m_flags & CaseSensitive)), pos);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
res = sourceToUse.replace(pos, searchTerm.length(), replaceTerm);
|
||||
pos += replaceTerm.length();
|
||||
}
|
||||
|
||||
if (!(m_flags & MatchAllOccurences))
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (pos != std::string::npos);
|
||||
res = regex_replace(wstring(source), pattern, replaceTerm);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = regex_replace(wstring(source), pattern, replaceTerm, regex_constants::format_first_only);
|
||||
}
|
||||
}
|
||||
|
||||
hr = SHStrDup(res.c_str(), result);
|
||||
}
|
||||
catch (regex_error e)
|
||||
else
|
||||
{
|
||||
hr = E_FAIL;
|
||||
// Simple search and replace
|
||||
size_t pos = 0;
|
||||
do
|
||||
{
|
||||
pos = _Find(sourceToUse, searchTerm, (!(m_flags & CaseSensitive)), pos);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
res = sourceToUse.replace(pos, searchTerm.length(), replaceTerm);
|
||||
pos += replaceTerm.length();
|
||||
}
|
||||
|
||||
if (!(m_flags & MatchAllOccurences))
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (pos != std::string::npos);
|
||||
}
|
||||
|
||||
hr = SHStrDup(res.c_str(), result);
|
||||
}
|
||||
catch (regex_error e)
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
@ -316,3 +365,16 @@ void CPowerRenameRegEx::_OnFlagsChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPowerRenameRegEx::_OnFileTimeChanged()
|
||||
{
|
||||
CSRWSharedAutoLock lock(&m_lockEvents);
|
||||
|
||||
for (auto it : m_renameRegExEvents)
|
||||
{
|
||||
if (it.pEvents)
|
||||
{
|
||||
it.pEvents->OnFileTimeChanged(m_fileTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ public:
|
||||
IFACEMETHODIMP PutReplaceTerm(_In_ PCWSTR replaceTerm);
|
||||
IFACEMETHODIMP GetFlags(_Out_ DWORD* flags);
|
||||
IFACEMETHODIMP PutFlags(_In_ DWORD flags);
|
||||
IFACEMETHODIMP PutFileTime(_In_ SYSTEMTIME fileTime);
|
||||
IFACEMETHODIMP ResetFileTime();
|
||||
IFACEMETHODIMP Replace(_In_ PCWSTR source, _Outptr_ PWSTR* result);
|
||||
|
||||
static HRESULT s_CreateInstance(_Outptr_ IPowerRenameRegEx **renameRegEx);
|
||||
@ -36,6 +38,7 @@ protected:
|
||||
void _OnSearchTermChanged();
|
||||
void _OnReplaceTermChanged();
|
||||
void _OnFlagsChanged();
|
||||
void _OnFileTimeChanged();
|
||||
|
||||
size_t _Find(std::wstring data, std::wstring toSearch, bool caseInsensitive, size_t pos);
|
||||
|
||||
@ -44,6 +47,9 @@ protected:
|
||||
PWSTR m_searchTerm = nullptr;
|
||||
PWSTR m_replaceTerm = nullptr;
|
||||
|
||||
SYSTEMTIME m_fileTime = {0};
|
||||
bool m_useFileTime = false;
|
||||
|
||||
CSRWLock m_lock;
|
||||
CSRWLock m_lockEvents;
|
||||
|
||||
|
@ -312,15 +312,16 @@ HRESULT CRenameMRU::CreateInstance(_In_ const std::wstring& filePath, _In_ const
|
||||
{
|
||||
*ppUnk = nullptr;
|
||||
unsigned int maxMRUSize = CSettingsInstance().GetMaxMRUSize();
|
||||
HRESULT hr = maxMRUSize > 0 ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_FAIL;
|
||||
if (maxMRUSize > 0)
|
||||
{
|
||||
CRenameMRU* renameMRU = new CRenameMRU(maxMRUSize, filePath, regPath);
|
||||
hr = renameMRU ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
hr = E_OUTOFMEMORY;
|
||||
if (renameMRU)
|
||||
{
|
||||
renameMRU->QueryInterface(IID_PPV_ARGS(ppUnk));
|
||||
renameMRU->Release();
|
||||
hr = S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,8 +120,8 @@ HRESULT CPowerRenameUI::s_CreateInstance(_In_ IPowerRenameManager* psrm, _In_opt
|
||||
{
|
||||
*ppsrui = nullptr;
|
||||
CPowerRenameUI* prui = new CPowerRenameUI();
|
||||
HRESULT hr = prui ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (prui)
|
||||
{
|
||||
// Pass the IPowerRenameManager to the IPowerRenameUI so it can subscribe to events
|
||||
hr = prui->_Initialize(psrm, dataSource, enableDragDrop);
|
||||
|
@ -1,14 +1,14 @@
|
||||
#include "pch.h"
|
||||
#include "MockPowerRenameItem.h"
|
||||
|
||||
HRESULT CMockPowerRenameItem::CreateInstance(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder, _Outptr_ IPowerRenameItem** ppItem)
|
||||
HRESULT CMockPowerRenameItem::CreateInstance(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder, _In_ SYSTEMTIME time, _Outptr_ IPowerRenameItem** ppItem)
|
||||
{
|
||||
*ppItem = nullptr;
|
||||
CMockPowerRenameItem* newItem = new CMockPowerRenameItem();
|
||||
HRESULT hr = newItem ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (newItem)
|
||||
{
|
||||
newItem->Init(path, originalName, depth, isFolder);
|
||||
newItem->Init(path, originalName, depth, isFolder, time);
|
||||
hr = newItem->QueryInterface(IID_PPV_ARGS(ppItem));
|
||||
newItem->Release();
|
||||
}
|
||||
@ -16,7 +16,7 @@ HRESULT CMockPowerRenameItem::CreateInstance(_In_opt_ PCWSTR path, _In_opt_ PCWS
|
||||
return hr;
|
||||
}
|
||||
|
||||
void CMockPowerRenameItem::Init(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder)
|
||||
void CMockPowerRenameItem::Init(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder, _In_ SYSTEMTIME time)
|
||||
{
|
||||
if (path != nullptr)
|
||||
{
|
||||
@ -30,4 +30,6 @@ void CMockPowerRenameItem::Init(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalNa
|
||||
|
||||
m_depth = depth;
|
||||
m_isFolder = isFolder;
|
||||
m_time = time;
|
||||
m_isTimeParsed = true;
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ class CMockPowerRenameItem :
|
||||
public CPowerRenameItem
|
||||
{
|
||||
public:
|
||||
static HRESULT CreateInstance(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder, _Outptr_ IPowerRenameItem** ppItem);
|
||||
void Init(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder);
|
||||
};
|
||||
static HRESULT CreateInstance(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder, _In_ SYSTEMTIME time, _Outptr_ IPowerRenameItem** ppItem);
|
||||
void Init(_In_opt_ PCWSTR path, _In_opt_ PCWSTR originalName, _In_ UINT depth, _In_ bool isFolder, _In_ SYSTEMTIME time);
|
||||
};
|
||||
|
@ -81,8 +81,8 @@ HRESULT CMockPowerRenameManagerEvents::s_CreateInstance(_In_ IPowerRenameManager
|
||||
{
|
||||
*ppsrui = nullptr;
|
||||
CMockPowerRenameManagerEvents* events = new CMockPowerRenameManagerEvents();
|
||||
HRESULT hr = events != nullptr ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (events != nullptr)
|
||||
{
|
||||
hr = events->QueryInterface(IID_PPV_ARGS(ppsrui));
|
||||
events->Release();
|
||||
|
@ -56,12 +56,18 @@ IFACEMETHODIMP CMockPowerRenameRegExEvents::OnFlagsChanged(_In_ DWORD flags)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP CMockPowerRenameRegExEvents::OnFileTimeChanged(_In_ SYSTEMTIME fileTime)
|
||||
{
|
||||
m_fileTime = fileTime;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CMockPowerRenameRegExEvents::s_CreateInstance(_Outptr_ IPowerRenameRegExEvents** ppsrree)
|
||||
{
|
||||
*ppsrree = nullptr;
|
||||
CMockPowerRenameRegExEvents* psrree = new CMockPowerRenameRegExEvents();
|
||||
HRESULT hr = psrree ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr))
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (psrree)
|
||||
{
|
||||
hr = psrree->QueryInterface(IID_PPV_ARGS(ppsrree));
|
||||
psrree->Release();
|
||||
|
@ -18,6 +18,7 @@ public:
|
||||
IFACEMETHODIMP OnSearchTermChanged(_In_ PCWSTR searchTerm);
|
||||
IFACEMETHODIMP OnReplaceTermChanged(_In_ PCWSTR replaceTerm);
|
||||
IFACEMETHODIMP OnFlagsChanged(_In_ DWORD flags);
|
||||
IFACEMETHODIMP OnFileTimeChanged(_In_ SYSTEMTIME fileTime);
|
||||
|
||||
static HRESULT s_CreateInstance(_Outptr_ IPowerRenameRegExEvents** ppsrree);
|
||||
|
||||
@ -35,5 +36,6 @@ public:
|
||||
PWSTR m_searchTerm = nullptr;
|
||||
PWSTR m_replaceTerm = nullptr;
|
||||
DWORD m_flags = 0;
|
||||
SYSTEMTIME m_fileTime = { 0 };
|
||||
long m_refCount;
|
||||
};
|
||||
|
@ -32,7 +32,7 @@ namespace PowerRenameManagerTests
|
||||
int depth;
|
||||
};
|
||||
|
||||
void RenameHelper(_In_ rename_pairs * renamePairs, _In_ int numPairs, _In_ std::wstring searchTerm, _In_ std::wstring replaceTerm, SYSTEMTIME LocalTime, _In_ DWORD flags)
|
||||
void RenameHelper(_In_ rename_pairs * renamePairs, _In_ int numPairs, _In_ std::wstring searchTerm, _In_ std::wstring replaceTerm, SYSTEMTIME fileTime, _In_ DWORD flags)
|
||||
{
|
||||
// Create a single item (in a temp directory) and verify rename works as expected
|
||||
CTestFileHelper testFileHelper;
|
||||
@ -59,12 +59,11 @@ namespace PowerRenameManagerTests
|
||||
for (int i = 0; i < numPairs; i++)
|
||||
{
|
||||
CComPtr<IPowerRenameItem> item;
|
||||
CMockPowerRenameItem::CreateInstance(testFileHelper.GetFullPath(
|
||||
renamePairs[i].originalName)
|
||||
.c_str(),
|
||||
CMockPowerRenameItem::CreateInstance(testFileHelper.GetFullPath(renamePairs[i].originalName).c_str(),
|
||||
renamePairs[i].originalName.c_str(),
|
||||
renamePairs[i].depth,
|
||||
!renamePairs[i].isFile,
|
||||
fileTime,
|
||||
&item);
|
||||
|
||||
int itemId = 0;
|
||||
@ -84,20 +83,21 @@ namespace PowerRenameManagerTests
|
||||
Assert::IsTrue(mgr->GetRenameRegEx(&renRegEx) == S_OK);
|
||||
renRegEx->PutFlags(flags);
|
||||
renRegEx->PutSearchTerm(searchTerm.c_str());
|
||||
if (isFileAttributesUsed(replaceTerm.c_str()) && SUCCEEDED(GetDatedFileName(newReplaceTerm, ARRAYSIZE(newReplaceTerm), replaceTerm.c_str(), LocalTime)))
|
||||
{
|
||||
renRegEx->PutReplaceTerm(newReplaceTerm);
|
||||
}
|
||||
else
|
||||
{
|
||||
renRegEx->PutReplaceTerm(replaceTerm.c_str());
|
||||
}
|
||||
Sleep(1000);
|
||||
renRegEx->PutReplaceTerm(replaceTerm.c_str());
|
||||
|
||||
// Perform the rename
|
||||
Assert::IsTrue(mgr->Rename(0) == S_OK);
|
||||
bool replaceSuccess = false;
|
||||
for (int step = 0; step < 20; step++)
|
||||
{
|
||||
replaceSuccess = mgr->Rename(0) == S_OK;
|
||||
if (replaceSuccess)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
Assert::IsTrue(replaceSuccess);
|
||||
|
||||
// Verify the rename occurred
|
||||
for (int i = 0; i < numPairs; i++)
|
||||
@ -128,7 +128,7 @@ namespace PowerRenameManagerTests
|
||||
CComPtr<IPowerRenameManager> mgr;
|
||||
Assert::IsTrue(CPowerRenameManager::s_CreateInstance(&mgr) == S_OK);
|
||||
CComPtr<IPowerRenameItem> item;
|
||||
CMockPowerRenameItem::CreateInstance(L"foo", L"foo", 0, false, &item);
|
||||
CMockPowerRenameItem::CreateInstance(L"foo", L"foo", 0, false, SYSTEMTIME{0}, &item);
|
||||
mgr->AddItem(item);
|
||||
Assert::IsTrue(mgr->Shutdown() == S_OK);
|
||||
}
|
||||
@ -143,7 +143,7 @@ namespace PowerRenameManagerTests
|
||||
DWORD cookie = 0;
|
||||
Assert::IsTrue(mgr->Advise(mgrEvents, &cookie) == S_OK);
|
||||
CComPtr<IPowerRenameItem> item;
|
||||
CMockPowerRenameItem::CreateInstance(L"foo", L"foo", 0, false, &item);
|
||||
CMockPowerRenameItem::CreateInstance(L"foo", L"foo", 0, false, SYSTEMTIME{0}, &item);
|
||||
int itemId = 0;
|
||||
Assert::IsTrue(item->GetId(&itemId) == S_OK);
|
||||
mgr->AddItem(item);
|
||||
@ -290,6 +290,7 @@ namespace PowerRenameManagerTests
|
||||
RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Lowercase | ExtensionOnly);
|
||||
}
|
||||
|
||||
|
||||
TEST_METHOD (VerifyFileAttributesNoPadding)
|
||||
{
|
||||
rename_pairs renamePairs[] = {
|
||||
@ -311,26 +312,26 @@ namespace PowerRenameManagerTests
|
||||
TEST_METHOD (VerifyFileAttributesMonthandDayNames)
|
||||
{
|
||||
std::locale::global(std::locale(""));
|
||||
SYSTEMTIME LocalTime = { 2020, 1, 3, 1, 15, 6, 42, 453 };
|
||||
SYSTEMTIME fileTime = { 2020, 1, 3, 1, 15, 6, 42, 453 };
|
||||
wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
|
||||
wchar_t result[MAX_PATH] = L"bar";
|
||||
wchar_t formattedDate[MAX_PATH];
|
||||
if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) == 0)
|
||||
StringCchCopy(localeName, LOCALE_NAME_MAX_LENGTH, L"en_US");
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &LocalTime, L"MMM", formattedDate, MAX_PATH, NULL);
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"MMM", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(result, MAX_PATH, TEXT("%s%s"), result, formattedDate);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &LocalTime, L"MMMM", formattedDate, MAX_PATH, NULL);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"MMMM", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &LocalTime, L"ddd", formattedDate, MAX_PATH, NULL);
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"ddd", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &LocalTime, L"dddd", formattedDate, MAX_PATH, NULL);
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"dddd", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate);
|
||||
|
||||
|
@ -59,7 +59,7 @@ TEST_METHOD(ReplaceNoSearchOrReplaceTerm)
|
||||
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||
PWSTR result = nullptr;
|
||||
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result) != S_OK);
|
||||
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result) == S_OK);
|
||||
Assert::IsTrue(result == nullptr);
|
||||
CoTaskMemFree(result);
|
||||
}
|
||||
@ -427,6 +427,8 @@ TEST_METHOD(VerifyEventsFire)
|
||||
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutSearchTerm(L"FOO") == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"BAR") == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutFileTime(SYSTEMTIME{0}) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->ResetFileTime() == S_OK);
|
||||
Assert::IsTrue(lstrcmpi(L"FOO", mockEvents->m_searchTerm) == 0);
|
||||
Assert::IsTrue(lstrcmpi(L"BAR", mockEvents->m_replaceTerm) == 0);
|
||||
Assert::IsTrue(flags == mockEvents->m_flags);
|
||||
|
@ -53,7 +53,7 @@ TEST_METHOD(ReplaceNoSearchOrReplaceTerm)
|
||||
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||
PWSTR result = nullptr;
|
||||
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result) != S_OK);
|
||||
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result) == S_OK);
|
||||
Assert::IsTrue(result == nullptr);
|
||||
CoTaskMemFree(result);
|
||||
}
|
||||
@ -369,6 +369,103 @@ TEST_METHOD(VerifyHandleCapturingGroups)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD (VerifyFileAttributesNoPadding)
|
||||
{
|
||||
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||
DWORD flags = MatchAllOccurences | UseRegularExpressions ;
|
||||
SYSTEMTIME fileTime = SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 };
|
||||
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||
|
||||
SearchReplaceExpected sreTable[] = {
|
||||
//search, replace, test, result
|
||||
{ L"foo", L"bar$YY-$M-$D-$h-$m-$s-$f", L"foo", L"bar20-7-22-15-6-42-4" },
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(sreTable); i++)
|
||||
{
|
||||
PWSTR result = nullptr;
|
||||
Assert::IsTrue(renameRegEx->PutSearchTerm(sreTable[i].search) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutReplaceTerm(sreTable[i].replace) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutFileTime(fileTime) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->Replace(sreTable[i].test, &result) == S_OK);
|
||||
Assert::IsTrue(wcscmp(result, sreTable[i].expected) == 0);
|
||||
CoTaskMemFree(result);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD (VerifyFileAttributesPadding)
|
||||
{
|
||||
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||
DWORD flags = MatchAllOccurences | UseRegularExpressions;
|
||||
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||
SYSTEMTIME fileTime = SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 };
|
||||
SearchReplaceExpected sreTable[] = {
|
||||
//search, replace, test, result
|
||||
{ L"foo", L"bar$YYYY-$MM-$DD-$hh-$mm-$ss-$fff", L"foo", L"bar2020-07-22-15-06-42-453" },
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(sreTable); i++)
|
||||
{
|
||||
PWSTR result = nullptr;
|
||||
Assert::IsTrue(renameRegEx->PutSearchTerm(sreTable[i].search) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutReplaceTerm(sreTable[i].replace) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutFileTime(fileTime) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->Replace(sreTable[i].test, &result) == S_OK);
|
||||
Assert::IsTrue(wcscmp(result, sreTable[i].expected) == 0);
|
||||
CoTaskMemFree(result);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD (VerifyFileAttributesMonthandDayNames)
|
||||
{
|
||||
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||
DWORD flags = MatchAllOccurences | UseRegularExpressions;
|
||||
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||
|
||||
std::locale::global(std::locale(""));
|
||||
SYSTEMTIME fileTime = { 2020, 1, 3, 1, 15, 6, 42, 453 };
|
||||
wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
|
||||
wchar_t result[MAX_PATH] = L"bar";
|
||||
wchar_t formattedDate[MAX_PATH];
|
||||
if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) == 0)
|
||||
StringCchCopy(localeName, LOCALE_NAME_MAX_LENGTH, L"en_US");
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"MMM", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(result, MAX_PATH, TEXT("%s%s"), result, formattedDate);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"MMMM", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"ddd", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate);
|
||||
|
||||
GetDateFormatEx(localeName, NULL, &fileTime, L"dddd", formattedDate, MAX_PATH, NULL);
|
||||
formattedDate[0] = towupper(formattedDate[0]);
|
||||
StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate);
|
||||
|
||||
SearchReplaceExpected sreTable[] = {
|
||||
//search, replace, test, result
|
||||
{ L"foo", L"bar$MMM-$MMMM-$DDD-$DDDD", L"foo", result },
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(sreTable); i++)
|
||||
{
|
||||
PWSTR result = nullptr;
|
||||
Assert::IsTrue(renameRegEx->PutSearchTerm(sreTable[i].search) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutReplaceTerm(sreTable[i].replace) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutFileTime(fileTime) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->Replace(sreTable[i].test, &result) == S_OK);
|
||||
Assert::IsTrue(wcscmp(result, sreTable[i].expected) == 0);
|
||||
CoTaskMemFree(result);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(VerifyLookbehindFails)
|
||||
{
|
||||
// Standard Library Regex Engine does not support lookbehind, thus test should fail.
|
||||
@ -406,6 +503,8 @@ TEST_METHOD(VerifyEventsFire)
|
||||
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutSearchTerm(L"FOO") == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"BAR") == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutFileTime(SYSTEMTIME{ 0 }) == S_OK);
|
||||
Assert::IsTrue(renameRegEx->ResetFileTime() == S_OK);
|
||||
Assert::IsTrue(lstrcmpi(L"FOO", mockEvents->m_searchTerm) == 0);
|
||||
Assert::IsTrue(lstrcmpi(L"BAR", mockEvents->m_replaceTerm) == 0);
|
||||
Assert::IsTrue(flags == mockEvents->m_flags);
|
||||
|
Loading…
Reference in New Issue
Block a user