Skip to content

Commit

Permalink
[PowerRename] Using File Date Time Attributes Feature (#4722)
Browse files Browse the repository at this point in the history
* Add basic using file attributes functionality

* Correctly return result

* Refactor

* Move retrieving date attribute to get function

* Cover various milliseconds patterns, retrieve file attributes only when needed

* Correctly check if date/time pattern is used. Remove wstring cast

* Use correct flags on CreateFile call to handle directories

* rebase to master

* Perform transform operation at last to make it not mess with date/time variables

* Refactor, remove extra space
  • Loading branch information
muratakburak committed Jul 16, 2020
1 parent ebe70a5 commit a8153dd
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 15 deletions.
58 changes: 58 additions & 0 deletions src/modules/powerrename/lib/Helpers.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "pch.h"
#include "Helpers.h"
#include <regex>
#include <ShlGuid.h>
#include <cstring>
#include <filesystem>
Expand Down Expand Up @@ -168,6 +169,63 @@ HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR sour
return hr;
}

HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME LocalTime)
{
HRESULT hr = (source && wcslen(source) > 0) ? S_OK : E_INVALIDARG;
if (SUCCEEDED(hr))
{
std::wregex pattern(L"\\$YYYY");
std::wstring res(source);
wchar_t replaceTerm[MAX_PATH] = {0};
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%d"),LocalTime.wYear);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$SSS";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%03d"), LocalTime.wMilliseconds);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$MMM";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%03d"), LocalTime.wMilliseconds);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$mmm";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%03d"), LocalTime.wMilliseconds);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$fff";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%03d"), LocalTime.wMilliseconds);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$FFF";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%03d"), LocalTime.wMilliseconds);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$MM" ;
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%02d"), LocalTime.wMonth);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$DD";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%02d"), LocalTime.wDay);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$hh";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%02d"), LocalTime.wHour);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$mm";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%02d"), LocalTime.wMinute);
res = regex_replace(res, pattern, replaceTerm);

pattern = L"\\$ss";
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%02d"), LocalTime.wSecond);
res = regex_replace(res, pattern, replaceTerm);

hr = StringCchCopy(result, cchMax, res.c_str());
}

return hr;
}

HRESULT _ParseEnumItems(_In_ IEnumShellItems* pesi, _In_ IPowerRenameManager* psrm, _In_ int depth = 0)
{
HRESULT hr = E_INVALIDARG;
Expand Down
3 changes: 2 additions & 1 deletion src/modules/powerrename/lib/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

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);
HRESULT EnumerateDataObject(_In_ IUnknown* pdo, _In_ IPowerRenameManager* psrm);
BOOL GetEnumeratedFileName(
__out_ecount(cchMax) PWSTR pszUniqueName,
UINT cchMax,
__in PCWSTR pszTemplate,
__in_opt PCWSTR pszDir,
unsigned long ulMinLong,
__inout unsigned long* pulNumUsed);
__inout unsigned long* pulNumUsed);
1 change: 1 addition & 0 deletions src/modules/powerrename/lib/PowerRenameInterfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ interface __declspec(uuid("C7F59201-4DE1-4855-A3A2-26FC3279C8A5")) IPowerRenameI
{
public:
IFACEMETHOD(get_path)(_Outptr_ PWSTR* path) = 0;
IFACEMETHOD(get_date)(_Outptr_ SYSTEMTIME* date) = 0;
IFACEMETHOD(get_shellItem)(_Outptr_ IShellItem** ppsi) = 0;
IFACEMETHOD(get_originalName)(_Outptr_ PWSTR* originalName) = 0;
IFACEMETHOD(get_newName)(_Outptr_ PWSTR* newName) = 0;
Expand Down
30 changes: 30 additions & 0 deletions src/modules/powerrename/lib/PowerRenameItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,36 @@ IFACEMETHODIMP CPowerRenameItem::get_path(_Outptr_ PWSTR* path)
return hr;
}

IFACEMETHODIMP CPowerRenameItem::get_date(_Outptr_ SYSTEMTIME* date)
{
CSRWSharedAutoLock lock(&m_lock);
HRESULT hr = m_isDateParsed ? S_OK : E_FAIL ;
if (!m_isDateParsed)
{
HANDLE hFile = CreateFileW(m_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
FILETIME CreationTime;
if (GetFileTime(hFile, &CreationTime, NULL, NULL))
{
SYSTEMTIME SystemTime, LocalTime;
if (FileTimeToSystemTime(&CreationTime, &SystemTime))
{
if (SystemTimeToTzSpecificLocalTime(NULL, &SystemTime, &LocalTime))
{
m_date = LocalTime;
m_isDateParsed = true;
hr = S_OK;
}
}
}
}
CloseHandle(hFile);
}
*date = m_date;
return hr;
}

IFACEMETHODIMP CPowerRenameItem::get_shellItem(_Outptr_ IShellItem** ppsi)
{
return SHCreateItemFromParsingName(m_path, nullptr, IID_PPV_ARGS(ppsi));
Expand Down
27 changes: 15 additions & 12 deletions src/modules/powerrename/lib/PowerRenameItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class CPowerRenameItem :

// IPowerRenameItem
IFACEMETHODIMP get_path(_Outptr_ PWSTR* path);
IFACEMETHODIMP get_date(_Outptr_ SYSTEMTIME* date);
IFACEMETHODIMP get_shellItem(_Outptr_ IShellItem** ppsi);
IFACEMETHODIMP get_originalName(_Outptr_ PWSTR* originalName);
IFACEMETHODIMP put_newName(_In_opt_ PCWSTR newName);
Expand Down Expand Up @@ -46,15 +47,17 @@ class CPowerRenameItem :

HRESULT _Init(_In_ IShellItem* psi);

bool m_selected = true;
bool m_isFolder = false;
int m_id = -1;
int m_iconIndex = -1;
UINT m_depth = 0;
HRESULT m_error = S_OK;
PWSTR m_path = nullptr;
PWSTR m_originalName = nullptr;
PWSTR m_newName = nullptr;
CSRWLock m_lock;
long m_refCount = 0;
};
bool m_selected = true;
bool m_isFolder = false;
bool m_isDateParsed = false;
int m_id = -1;
int m_iconIndex = -1;
UINT m_depth = 0;
HRESULT m_error = S_OK;
PWSTR m_path = nullptr;
PWSTR m_originalName = nullptr;
PWSTR m_newName = nullptr;
SYSTEMTIME m_date;
CSRWLock m_lock;
long m_refCount = 0;
};
32 changes: 30 additions & 2 deletions src/modules/powerrename/lib/PowerRenameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,35 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
newNameToUse = trimmedName;
}


bool isDateAttributeUsed = false;
wchar_t datedName[MAX_PATH] = { 0 };
std::wstring patterns[] = { L"$YYYY", L"$SSS", L"$MMM", L"$mmm", L"$FFF", L"$fff",
L"$MM", L"$DD", L"$hh", L"$mm", L"$ss" };
size_t patternsLength = ARRAYSIZE(patterns);
SYSTEMTIME LocalTime;

if (newNameToUse != nullptr)
{
for (size_t i = 0; !isDateAttributeUsed && i < patternsLength; i++)
{
std::wstring source(newNameToUse);
if (source.find(patterns[i]) != std::string::npos)
{
isDateAttributeUsed = true;
}
}
if (isDateAttributeUsed)
{
if (SUCCEEDED(spItem->get_date(&LocalTime)))
{
if (SUCCEEDED(GetDatedFileName(datedName, ARRAYSIZE(datedName), newNameToUse, LocalTime)))
{
newNameToUse = datedName;
}
}
}
}

wchar_t transformedName[MAX_PATH] = { 0 };
if (newNameToUse != nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase))
{
Expand All @@ -822,7 +850,7 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
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)
Expand Down

0 comments on commit a8153dd

Please sign in to comment.