ReactOS  0.4.15-dev-2720-g5ee0925
autocomp.cpp
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS shlwapi
3  * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE: Implement SHAutoComplete
5  * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6  */
7 #include <windef.h>
8 #include <shlobj.h>
9 #include <shlwapi.h>
10 #include <browseui_undoc.h>
11 #include <shlwapi_undoc.h>
12 #include <shlguid_undoc.h>
13 #include <atlbase.h>
14 #include <atlcom.h>
15 #include <wine/debug.h>
16 
18 
19 static HRESULT
20 AutoComplete_AddMRU(CComPtr<IObjMgr> pManager, LPCWSTR pszKey)
21 {
22  CComPtr<IACLCustomMRU> pMRU; // Create an MRU list
23  HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_INPROC_SERVER,
24  IID_IACLCustomMRU, (LPVOID *)&pMRU);
25  if (FAILED(hr))
26  {
27  ERR("CoCreateInstance(CLSID_ACLMRU) failed with 0x%08lX\n", hr);
28  return hr;
29  }
30 
31  hr = pMRU->Initialize(pszKey, 'z' - 'a' + 1); // Load the list from registry
32  if (FAILED(hr))
33  {
34  ERR("pMRU->Initialize(%ls) failed with 0x%08lX\n", pszKey, hr);
35  return hr;
36  }
37 
38  hr = pManager->Append(pMRU); // Add to the manager
39  if (FAILED(hr))
40  ERR("pManager->Append for '%ls' failed with 0x%08lX\n", pszKey, hr);
41  return hr;
42 }
43 
44 static HRESULT
45 IUnknown_AddOptions(CComPtr<IUnknown> punk, DWORD dwACLO)
46 {
47  CComPtr<IACList2> pList;
48  HRESULT hr = punk->QueryInterface(IID_IACList2, (LPVOID *)&pList);
49  if (FAILED(hr))
50  {
51  ERR("punk->QueryInterface failed: 0x%08lX\n", hr);
52  return hr;
53  }
54 
55  DWORD dwOptions = 0;
56  pList->GetOptions(&dwOptions);
57  dwOptions |= dwACLO;
58  hr = pList->SetOptions(dwOptions);
59  if (FAILED(hr))
60  ERR("pList->SetOptions failed: 0x%08lX\n", hr);
61  return hr;
62 }
63 
64 static CComPtr<IUnknown>
66 {
67  // Create a multiple list (with IEnumString interface)
68  CComPtr<IUnknown> pList;
69  HRESULT hr = CoCreateInstance(CLSID_ACLMulti, NULL, CLSCTX_INPROC_SERVER,
71  if (FAILED(hr)) // Failed to create the list
72  {
73  ERR("CoCreateInstance(CLSID_ACLMulti) failed with 0x%08lX\n", hr);
74  return NULL;
75  }
76 
77  CComPtr<IObjMgr> pManager; // This is the manager of the multiple list
78  hr = pList->QueryInterface(IID_IObjMgr, (LPVOID *)&pManager);
79  if (FAILED(hr)) // Failed to get interface
80  {
81  ERR("pList->QueryInterface failed: 0x%08lX\n", hr);
82  return NULL;
83  }
84 
85  if (dwSHACF & SHACF_URLMRU)
86  {
87  // The MRU (Most-Recently-Used) lists (with IEnumString interface)
88 #define RUN_MRU_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU"
89 #define TYPED_URLS_KEY L"Software\\Microsoft\\Internet Explorer\\TypedURLs"
92  }
93 
94  if (dwSHACF & SHACF_URLHISTORY)
95  {
96  // The history list (with IEnumString interface)
97  CComPtr<IUnknown> pHistory;
98  hr = CoCreateInstance(CLSID_ACLHistory, NULL, CLSCTX_INPROC_SERVER,
99  IID_IUnknown, (LPVOID *)&pHistory);
100  if (SUCCEEDED(hr))
101  {
102  pManager->Append(pHistory); // Add to the manager
103  // Add ACLO_* options
104  IUnknown_AddOptions(pHistory, dwACLO);
105  }
106  else
107  {
108  ERR("CLSID_ACLHistory hr:%08lX\n", hr);
109  }
110  }
111 
113  {
114  // The filesystem list (with IEnumString interface)
115  CComPtr<IUnknown> pISF;
116  hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_INPROC_SERVER,
117  IID_IUnknown, (LPVOID *)&pISF);
118  if (SUCCEEDED(hr))
119  {
120  pManager->Append(pISF); // Add to the manager
121  // Add ACLO_* options
122  IUnknown_AddOptions(pISF, dwACLO);
123  }
124  else
125  {
126  ERR("CLSID_ACListISF hr:%08lX\n", hr);
127  }
128  }
129 
130  return pList; // The list
131 }
132 
133 static VOID
135  IN OUT LPDWORD pdwSHACF,
136  OUT LPDWORD pdwACO,
137  OUT LPDWORD pdwACLO)
138 {
139 #define AUTOCOMPLETE_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete"
140  DWORD dwSHACF = *pdwSHACF, dwACO = 0, dwACLO = 0;
141  if (dwSHACF == SHACF_DEFAULT)
142  dwSHACF = SHACF_FILESYSTEM | SHACF_URLALL;
143 
144  if (!(dwSHACF & SHACF_AUTOAPPEND_FORCE_OFF) &&
145  ((dwSHACF & SHACF_AUTOAPPEND_FORCE_ON) ||
146  SHRegGetBoolUSValueW(AUTOCOMPLETE_KEY, L"Append Completion", FALSE, FALSE)))
147  {
148  dwACO |= ACO_AUTOAPPEND;
149  }
150 
151  if (!(dwSHACF & SHACF_AUTOSUGGEST_FORCE_OFF) &&
152  ((dwSHACF & SHACF_AUTOSUGGEST_FORCE_ON) ||
154  {
155  dwACO |= ACO_AUTOSUGGEST;
156  }
157 
158  if (dwSHACF & SHACF_FILESYS_DIRS)
159  dwACLO |= ACLO_FILESYSDIRS;
160  if (dwSHACF & SHACF_FILESYS_ONLY)
161  dwACLO |= ACLO_FILESYSONLY;
162 
163  static BOOL s_bAlwaysUseTab = 99;
164  if (s_bAlwaysUseTab == 99)
165  s_bAlwaysUseTab = SHRegGetBoolUSValueW(AUTOCOMPLETE_KEY, L"Always Use Tab", FALSE, FALSE);
166 
167  if (s_bAlwaysUseTab || (dwSHACF & SHACF_USETAB))
168  dwACO |= ACO_USETAB;
169 
171  dwACO |= ACO_RTLREADING;
172 
173  *pdwSHACF = dwSHACF;
174  *pdwACO = dwACO;
175  *pdwACLO = dwACLO;
176 }
177 
178 /*************************************************************************
179  * SHAutoComplete [SHLWAPI.@]
180  *
181  * Enable auto-completion for an edit control.
182  *
183  * PARAMS
184  * hwndEdit [I] Handle of control to enable auto-completion for
185  * dwFlags [I] SHACF_ flags from "shlwapi.h"
186  *
187  * RETURNS
188  * Success: S_OK. Auto-completion is enabled for the control.
189  * Failure: An HRESULT error code indicating the error.
190  */
192 {
193  TRACE("SHAutoComplete(%p, 0x%lX)\n", hwndEdit, dwFlags);
194 
195  DWORD dwSHACF = dwFlags, dwACO = 0, dwACLO = 0;
196  AutoComplete_AdaptFlags(hwndEdit, &dwSHACF, &dwACO, &dwACLO);
197 
198  // Load the list (with IEnumString interface)
199  CComPtr<IUnknown> pList = AutoComplete_LoadList(dwSHACF, dwACLO);
200  if (!pList)
201  {
202  ERR("Out of memory\n");
203  return E_OUTOFMEMORY;
204  }
205 
206  // Create an auto-completion (IAutoComplete2)
207  CComPtr<IAutoComplete2> pAC2;
208  HRESULT hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER,
209  IID_IAutoComplete2, (LPVOID *)&pAC2);
210  if (FAILED(hr))
211  {
212  ERR("CoCreateInstance(CLSID_AutoComplete) failed: 0x%lX\n", hr);
213  return hr;
214  }
215 
216  // Keep the DLLs of CLSID_ACListISF and CLSID_AutoComplete loaded
217  hr = E_FAIL;
218  if (SHPinDllOfCLSID(CLSID_ACListISF) && SHPinDllOfCLSID(CLSID_AutoComplete))
219  {
220  // Initialize IAutoComplete2 for auto-completion
221  hr = pAC2->Init(hwndEdit, pList, NULL, NULL);
222  if (SUCCEEDED(hr))
223  pAC2->SetOptions(dwACO); // Set ACO_* flags
224  else
225  ERR("IAutoComplete2::Init failed: 0x%lX\n", hr);
226  }
227 
228  return hr;
229 }
#define SHACF_URLALL
Definition: shlwapi.h:1915
DWORD dwOptions
Definition: solitaire.cpp:24
#define ACLO_FILESYSONLY
Definition: shlobj.h:744
#define IN
Definition: typedefs.h:39
static HRESULT AutoComplete_AddMRU(CComPtr< IObjMgr > pManager, LPCWSTR pszKey)
Definition: autocomp.cpp:20
HRESULT hr
Definition: shlfolder.c:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define TRUE
Definition: types.h:120
HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
Definition: ordinal.c:2488
BOOL WINAPI SHRegGetBoolUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, BOOL fIgnoreHKCU, BOOL fDefault)
Definition: reg.c:770
#define ACLO_FILESYSDIRS
Definition: shlobj.h:745
#define WS_EX_LAYOUTRTL
Definition: winuser.h:390
#define GWL_EXSTYLE
Definition: winuser.h:845
#define GetWindowLongPtrW
Definition: winuser.h:4804
static CComPtr< IUnknown > AutoComplete_LoadList(DWORD dwSHACF, DWORD dwACLO)
Definition: autocomp.cpp:65
#define E_FAIL
Definition: ddrawi.h:102
#define SHACF_AUTOAPPEND_FORCE_ON
Definition: shlwapi.h:1921
#define SHACF_URLMRU
Definition: shlwapi.h:1914
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
FxChildList * pList
if SUCCEEDED(hr)
#define SHACF_FILESYSTEM
Definition: shlwapi.h:1912
#define RUN_MRU_KEY
static HRESULT IUnknown_AddOptions(CComPtr< IUnknown > punk, DWORD dwACLO)
Definition: autocomp.cpp:45
#define SHACF_AUTOSUGGEST_FORCE_ON
Definition: shlwapi.h:1919
HRESULT WINAPI SHAutoComplete(HWND hwndEdit, DWORD dwFlags)
Definition: autocomp.cpp:191
#define SHACF_AUTOSUGGEST_FORCE_OFF
Definition: shlwapi.h:1920
#define TRACE(s)
Definition: solgame.cpp:4
#define TYPED_URLS_KEY
WINE_DEFAULT_DEBUG_CHANNEL(commdlg)
LONG HRESULT
Definition: typedefs.h:79
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
static VOID AutoComplete_AdaptFlags(IN HWND hwndEdit, IN OUT LPDWORD pdwSHACF, OUT LPDWORD pdwACO, OUT LPDWORD pdwACLO)
Definition: autocomp.cpp:134
static const WCHAR L[]
Definition: oid.c:1250
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
#define ERR(fmt,...)
Definition: debug.h:110
HWND hwndEdit
Definition: combotst.c:65
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define SHACF_USETAB
Definition: shlwapi.h:1916
#define NULL
Definition: types.h:112
#define SHACF_AUTOAPPEND_FORCE_OFF
Definition: shlwapi.h:1922
#define OUT
Definition: typedefs.h:40
#define SHACF_DEFAULT
Definition: shlwapi.h:1911
uint32_t * LPDWORD
Definition: typedefs.h:59
#define SHACF_FILESYS_ONLY
Definition: shlwapi.h:1917
virtual _Must_inspect_result_ NTSTATUS QueryInterface(__in FxQueryInterfaceParams *Params)
Definition: fxobject.cpp:255
#define SHACF_URLHISTORY
Definition: shlwapi.h:1913
#define SHACF_FILESYS_DIRS
Definition: shlwapi.h:1918
#define AUTOCOMPLETE_KEY