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