RunHistory.cpp
1 #include "pch.h" 2 #include "RunHistory.h" 3 #include "RunHistory.g.cpp" 4 5 6 using namespace winrt::Windows; 7 8 namespace winrt::Microsoft::Terminal::UI::implementation 9 { 10 // Run history 11 // Largely copied from the Run work circa 2022. 12 13 winrt::Windows::Foundation::Collections::IVector<hstring> RunHistory::CreateRunHistory() 14 { 15 // Load MRU history 16 std::vector<hstring> history; 17 18 wil::unique_hmodule _comctl; 19 HANDLE(WINAPI* _createMRUList)(MRUINFO* lpmi); 20 int(WINAPI* _enumMRUList)(HANDLE hMRU,int nItem,void* lpData,UINT uLen); 21 void(WINAPI *_freeMRUList)(HANDLE hMRU); 22 int(WINAPI *_addMRUString)(HANDLE hMRU, LPCWSTR szString); 23 24 // Lazy load comctl32.dll 25 // Theoretically, we could cache this into a magic static, but we shouldn't need to actually do this more than once in CmdPal 26 _comctl.reset(LoadLibraryExW(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); 27 28 _createMRUList = reinterpret_cast<decltype(_createMRUList)>(GetProcAddress(_comctl.get(), "CreateMRUListW")); 29 FAIL_FAST_LAST_ERROR_IF(!_createMRUList); 30 31 _enumMRUList = reinterpret_cast<decltype(_enumMRUList)>(GetProcAddress(_comctl.get(), "EnumMRUListW")); 32 FAIL_FAST_LAST_ERROR_IF(!_enumMRUList); 33 34 _freeMRUList = reinterpret_cast<decltype(_freeMRUList)>(GetProcAddress(_comctl.get(), "FreeMRUList")); 35 FAIL_FAST_LAST_ERROR_IF(!_freeMRUList); 36 37 _addMRUString = reinterpret_cast<decltype(_addMRUString)>(GetProcAddress(_comctl.get(), "AddMRUStringW")); 38 FAIL_FAST_LAST_ERROR_IF(!_addMRUString); 39 40 static const WCHAR c_szRunMRU[] = REGSTR_PATH_EXPLORER L"\\RunMRU"; 41 MRUINFO mi = { 42 sizeof(mi), 43 26, 44 MRU_CACHEWRITE, 45 HKEY_CURRENT_USER, 46 c_szRunMRU, 47 NULL // NOTE: use default string compare 48 // since this is a GLOBAL MRU 49 }; 50 51 if (const auto hMruList = _createMRUList(&mi)) 52 { 53 auto freeMRUList = wil::scope_exit([=]() { 54 _freeMRUList(hMruList); 55 }); 56 57 for (int nMax = _enumMRUList(hMruList, -1, NULL, 0), i = 0; i < nMax; ++i) 58 { 59 WCHAR szCommand[MAX_PATH + 2]; 60 61 const auto length = _enumMRUList(hMruList, i, szCommand, ARRAYSIZE(szCommand)); 62 if (length > 1) 63 { 64 // clip off the null-terminator 65 std::wstring_view text{ szCommand, wil::safe_cast<size_t>(length - 1) }; 66 //#pragma disable warning(C26493) 67 #pragma warning( push ) 68 #pragma warning( disable : 26493 ) 69 if (text.back() == L'\\') 70 { 71 // old MRU format has a slash at the end with the show cmd 72 text = { szCommand, wil::safe_cast<size_t>(length - 2) }; 73 #pragma warning( pop ) 74 if (text.empty()) 75 { 76 continue; 77 } 78 } 79 history.emplace_back(text); 80 } 81 } 82 } 83 84 // Update dropdown & initial value 85 return winrt::single_threaded_observable_vector<winrt::hstring>(std::move(history)); 86 } 87 }