/ src / modules / cmdpal / Microsoft.Terminal.UI / RunHistory.cpp
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  }