diff --git a/src/modules/powerrename/dll/PowerRenameExt.cpp b/src/modules/powerrename/dll/PowerRenameExt.cpp index 4e9c7ea4c9..8097f793dd 100644 --- a/src/modules/powerrename/dll/PowerRenameExt.cpp +++ b/src/modules/powerrename/dll/PowerRenameExt.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "resource.h" extern HINSTANCE g_hInst; @@ -88,23 +89,24 @@ HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirs HRESULT CPowerRenameMenu::InvokeCommand(_In_ LPCMINVOKECOMMANDINFO pici) { - // Check if we have disabled ourselves - if (!IsEnabled()) - return E_FAIL; - HRESULT hr = E_FAIL; - if ((IS_INTRESOURCE(pici->lpVerb)) && + if (IsEnabled() & + (IS_INTRESOURCE(pici->lpVerb)) && (LOWORD(pici->lpVerb) == 0)) { + Trace::Invoked(); IStream* pstrm = nullptr; - if (SUCCEEDED(CoMarshalInterThreadInterfaceInStream(__uuidof(m_spdo), m_spdo, &pstrm))) + hr = CoMarshalInterThreadInterfaceInStream(__uuidof(m_spdo), m_spdo, &pstrm); + if (SUCCEEDED(hr)) { if (!SHCreateThread(s_PowerRenameUIThreadProc, pstrm, CTF_COINIT | CTF_PROCESS_REF, nullptr)) { pstrm->Release(); // if we failed to create the thread, then we must release the stream + hr = E_FAIL; } } + Trace::InvokedRet(hr); } return hr; @@ -114,22 +116,27 @@ DWORD WINAPI CPowerRenameMenu::s_PowerRenameUIThreadProc(_In_ void* pData) { IStream* pstrm = static_cast(pData); CComPtr spdo; - if (SUCCEEDED(CoGetInterfaceAndReleaseStream(pstrm, IID_PPV_ARGS(&spdo)))) + HRESULT hr = CoGetInterfaceAndReleaseStream(pstrm, IID_PPV_ARGS(&spdo)); + if (SUCCEEDED(hr)) { // Create the smart rename manager CComPtr spsrm; - if (SUCCEEDED(CPowerRenameManager::s_CreateInstance(&spsrm))) + hr = CPowerRenameManager::s_CreateInstance(&spsrm); + if (SUCCEEDED(hr)) { // Create the factory for our items CComPtr spsrif; - if (SUCCEEDED(CPowerRenameItem::s_CreateInstance(nullptr, IID_PPV_ARGS(&spsrif)))) + hr = CPowerRenameItem::s_CreateInstance(nullptr, IID_PPV_ARGS(&spsrif)); + if (SUCCEEDED(hr)) { // Pass the factory to the manager - if (SUCCEEDED(spsrm->put_smartRenameItemFactory(spsrif))) + hr = spsrm->put_smartRenameItemFactory(spsrif); + if (SUCCEEDED(hr)) { // Create the smart rename UI instance and pass the smart rename manager CComPtr spsrui; - if (SUCCEEDED(CPowerRenameUI::s_CreateInstance(spsrm, spdo, false, &spsrui))) + hr = CPowerRenameUI::s_CreateInstance(spsrm, spdo, false, &spsrui); + if (SUCCEEDED(hr)) { // Call blocks until we are done spsrui->Show(); @@ -143,5 +150,7 @@ DWORD WINAPI CPowerRenameMenu::s_PowerRenameUIThreadProc(_In_ void* pData) } } + Trace::UIShownRet(hr); + return 0; } diff --git a/src/modules/powerrename/dll/dllmain.cpp b/src/modules/powerrename/dll/dllmain.cpp index 61d02a525c..254213e3cb 100644 --- a/src/modules/powerrename/dll/dllmain.cpp +++ b/src/modules/powerrename/dll/dllmain.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "PowerRenameExt.h" #include +#include #include DWORD g_dwModuleRefCount = 0; @@ -96,9 +97,11 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, void*) { case DLL_PROCESS_ATTACH: g_hInst = hInstance; + Trace::RegisterProvider(); break; case DLL_PROCESS_DETACH: + Trace::RegisterProvider(); break; } return TRUE; @@ -233,11 +236,13 @@ public: void init_settings() { m_enabled = CPowerRenameMenu::IsEnabled(); + Trace::EnablePowerRename(m_enabled); } void save_settings() { CPowerRenameMenu::SetEnabled(m_enabled); + Trace::EnablePowerRename(m_enabled); } PowerRenameModule() diff --git a/src/modules/powerrename/lib/PowerRenameLib.vcxproj b/src/modules/powerrename/lib/PowerRenameLib.vcxproj index 6c61aa9f26..800c6af015 100644 --- a/src/modules/powerrename/lib/PowerRenameLib.vcxproj +++ b/src/modules/powerrename/lib/PowerRenameLib.vcxproj @@ -98,6 +98,7 @@ true stdcpp17 MultiThreadedDebug + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ Windows @@ -132,6 +133,7 @@ true stdcpp17 MultiThreaded + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ Windows @@ -148,6 +150,7 @@ + @@ -160,6 +163,7 @@ Create Create + diff --git a/src/modules/powerrename/lib/PowerRenameManager.cpp b/src/modules/powerrename/lib/PowerRenameManager.cpp index 69cd8c4001..ba79ca25dd 100644 --- a/src/modules/powerrename/lib/PowerRenameManager.cpp +++ b/src/modules/powerrename/lib/PowerRenameManager.cpp @@ -5,6 +5,8 @@ #include #include "helpers.h" #include +#include "trace.h" + namespace fs = std::filesystem; extern HINSTANCE g_hInst; @@ -407,6 +409,57 @@ LRESULT CPowerRenameManager::_WndProc(_In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM return lRes; } +void CPowerRenameManager::_LogOperationTelemetry() +{ + UINT renameItemCount = 0; + UINT selectedItemCount = 0; + UINT totalItemCount = 0; + DWORD flags = 0; + + GetItemCount(&totalItemCount); + GetSelectedItemCount(&selectedItemCount); + GetRenameItemCount(&renameItemCount); + get_flags(&flags); + + + // Enumerate extensions used into a map + std::map extensionsMap; + for (UINT i = 0; i < totalItemCount; i++) + { + CComPtr spItem; + if (SUCCEEDED(GetItemByIndex(i, &spItem))) + { + PWSTR originalName; + if (SUCCEEDED(spItem->get_originalName(&originalName))) + { + std::wstring extension = fs::path(originalName).extension().wstring(); + std::map::iterator it = extensionsMap.find(extension); + if (it == extensionsMap.end()) + { + extensionsMap.insert({ extension, 1 }); + } + else + { + it->second++; + } + + CoTaskMemFree(originalName); + } + } + } + + std::wstring extensionList = L""; + for (auto elem : extensionsMap) + { + extensionList.append(elem.first); + extensionList.append(L":"); + extensionList.append(std::to_wstring(elem.second)); + extensionList.append(L","); + } + + Trace::RenameOperation(totalItemCount, selectedItemCount, renameItemCount, flags, extensionList.c_str()); +} + HRESULT CPowerRenameManager::_PerformFileOperation() { // Do we have items to rename? @@ -416,6 +469,8 @@ HRESULT CPowerRenameManager::_PerformFileOperation() return E_FAIL; } + _LogOperationTelemetry(); + // Wait for existing regex thread to finish _WaitForRegExWorkerThread(); diff --git a/src/modules/powerrename/lib/PowerRenameManager.h b/src/modules/powerrename/lib/PowerRenameManager.h index 0179e3b4fe..08ca87abb9 100644 --- a/src/modules/powerrename/lib/PowerRenameManager.h +++ b/src/modules/powerrename/lib/PowerRenameManager.h @@ -82,6 +82,8 @@ protected: static LRESULT CALLBACK s_msgWndProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam); LRESULT _WndProc(_In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wParam, _In_ LPARAM lParam); + void _LogOperationTelemetry(); + HANDLE m_regExWorkerThreadHandle = nullptr; HANDLE m_startRegExWorkerEvent = nullptr; HANDLE m_cancelRegExWorkerEvent = nullptr; diff --git a/src/modules/powerrename/lib/stdafx.h b/src/modules/powerrename/lib/stdafx.h index c15286029b..befa9aea75 100644 --- a/src/modules/powerrename/lib/stdafx.h +++ b/src/modules/powerrename/lib/stdafx.h @@ -17,4 +17,6 @@ #include #include +#include + #include "PowerRenameInterfaces.h" \ No newline at end of file diff --git a/src/modules/powerrename/lib/trace.cpp b/src/modules/powerrename/lib/trace.cpp new file mode 100644 index 0000000000..811e9a26ff --- /dev/null +++ b/src/modules/powerrename/lib/trace.cpp @@ -0,0 +1,73 @@ +#include "stdafx.h" +#include "trace.h" + +TRACELOGGING_DEFINE_PROVIDER( + g_hProvider, + "Microsoft.PowerToys", + // {38e8889b-9731-53f5-e901-e8a7c1753074} + (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74), + TraceLoggingOptionProjectTelemetry()); + +void Trace::RegisterProvider() noexcept +{ + TraceLoggingRegister(g_hProvider); +} + +void Trace::UnregisterProvider() noexcept +{ + TraceLoggingUnregister(g_hProvider); +} + +void Trace::Invoked() noexcept +{ + TraceLoggingWrite( + g_hProvider, + "PowerRename_Invoked", + ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), + TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); +} + +void Trace::InvokedRet(_In_ HRESULT hr) noexcept +{ + TraceLoggingWrite( + g_hProvider, + "PowerRename_InvokedRet", + ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), + TraceLoggingHResult(hr), + TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); +} + +void Trace::EnablePowerRename(_In_ bool enabled) noexcept +{ + TraceLoggingWrite( + g_hProvider, + "PowerRename_EnablePowerRename", + ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), + TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE), + TraceLoggingBoolean(enabled, "Enabled")); +} + +void Trace::UIShownRet(_In_ HRESULT hr) noexcept +{ + TraceLoggingWrite( + g_hProvider, + "PowerRename_UIShownRet", + ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), + TraceLoggingHResult(hr), + TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); +} + +void Trace::RenameOperation(_In_ UINT totalItemCount, _In_ UINT selectedItemCount, _In_ UINT renameItemCount, _In_ DWORD flags, _In_ PCWSTR extensionList) noexcept +{ + TraceLoggingWrite( + g_hProvider, + "PowerRename_RenameOperation", + ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), + TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE), + TraceLoggingUInt32(totalItemCount, "TotalItemCount"), + TraceLoggingUInt32(selectedItemCount, "SelectedItemCount"), + TraceLoggingUInt32(renameItemCount, "RenameItemCount"), + TraceLoggingInt32(flags, "Flags"), + TraceLoggingWideString(extensionList, "ExtensionList")); +} + diff --git a/src/modules/powerrename/lib/trace.h b/src/modules/powerrename/lib/trace.h new file mode 100644 index 0000000000..4f5533bf7b --- /dev/null +++ b/src/modules/powerrename/lib/trace.h @@ -0,0 +1,17 @@ +#pragma once + +class Trace { +public: + static void RegisterProvider() noexcept; + static void UnregisterProvider() noexcept; + static void Invoked() noexcept; + static void InvokedRet(_In_ HRESULT hr) noexcept; + static void EnablePowerRename(_In_ bool enabled) noexcept; + static void UIShownRet(_In_ HRESULT hr) noexcept; + static void RenameOperation( + _In_ UINT totalItemCount, + _In_ UINT selectedItemCount, + _In_ UINT renameItemCount, + _In_ DWORD flags, + _In_ PCWSTR extensionList) noexcept; +}; diff --git a/src/modules/powerrename/testapp/PowerRenameTest.vcxproj b/src/modules/powerrename/testapp/PowerRenameTest.vcxproj index 62a34eb08e..b9595afbd7 100644 --- a/src/modules/powerrename/testapp/PowerRenameTest.vcxproj +++ b/src/modules/powerrename/testapp/PowerRenameTest.vcxproj @@ -115,6 +115,7 @@ true stdcpp17 MultiThreadedDebug + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ Windows @@ -155,6 +156,7 @@ true stdcpp17 MultiThreaded + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ Windows diff --git a/src/modules/powerrename/ui/PowerRename.ico b/src/modules/powerrename/ui/PowerRename.ico new file mode 100644 index 0000000000..5070d82e29 Binary files /dev/null and b/src/modules/powerrename/ui/PowerRename.ico differ diff --git a/src/modules/powerrename/ui/PowerRenameUI.rc b/src/modules/powerrename/ui/PowerRenameUI.rc index 19531cf993..1db823711f 100644 Binary files a/src/modules/powerrename/ui/PowerRenameUI.rc and b/src/modules/powerrename/ui/PowerRenameUI.rc differ diff --git a/src/modules/powerrename/ui/PowerRenameUI.vcxproj b/src/modules/powerrename/ui/PowerRenameUI.vcxproj index 4ee7ffa188..17a66340fc 100644 --- a/src/modules/powerrename/ui/PowerRenameUI.vcxproj +++ b/src/modules/powerrename/ui/PowerRenameUI.vcxproj @@ -115,6 +115,7 @@ true stdcpp17 MultiThreadedDebug + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ Windows @@ -152,6 +153,7 @@ true stdcpp17 MultiThreaded + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\ Windows diff --git a/src/modules/powerrename/ui/Rename.ico b/src/modules/powerrename/ui/Rename.ico deleted file mode 100644 index d96be9175d..0000000000 Binary files a/src/modules/powerrename/ui/Rename.ico and /dev/null differ diff --git a/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj b/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj index 0e938a5406..009ceecd4e 100644 --- a/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj +++ b/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj @@ -116,7 +116,7 @@ Use Level3 Disabled - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) _DEBUG;%(PreprocessorDefinitions) true stdcpp17 @@ -156,7 +156,7 @@ MaxSpeed true true - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) NDEBUG;%(PreprocessorDefinitions) true stdcpp17