diff --git a/dll/win32/shlwapi/CMakeLists.txt b/dll/win32/shlwapi/CMakeLists.txt index 472eceb2014..6c425e78ceb 100644 --- a/dll/win32/shlwapi/CMakeLists.txt +++ b/dll/win32/shlwapi/CMakeLists.txt @@ -6,9 +6,13 @@ add_definitions(-D_WIN32_WINNT=0x600) add_definitions( -D__WINESRC__ - -D_SHLWAPI_) + -D_SHLWAPI_ + -D_ATL_NO_EXCEPTIONS) -include_directories(BEFORE ${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) +set_cpp(WITH_RUNTIME) +include_directories(BEFORE + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine + ${REACTOS_SOURCE_DIR}/sdk/lib/atl) spec2def(shlwapi.dll shlwapi.spec ADD_IMPORTLIB) list(APPEND SOURCE @@ -28,6 +32,7 @@ list(APPEND SOURCE url.c) list(APPEND PCH_SKIP_SOURCE + autocomp.cpp wsprintf.c ${CMAKE_CURRENT_BINARY_DIR}/shlwapi_stubs.c) @@ -37,7 +42,7 @@ add_library(shlwapi MODULE shlwapi.rc ${CMAKE_CURRENT_BINARY_DIR}/shlwapi.def) -set_module_type(shlwapi win32dll) +set_module_type(shlwapi win32dll UNICODE) target_link_libraries(shlwapi uuid wine) add_delay_importlibs(shlwapi userenv oleaut32 ole32 comdlg32 mpr mlang urlmon shell32 winmm version) add_importlibs(shlwapi user32 gdi32 advapi32 wininet msvcrt kernel32 ntdll) diff --git a/dll/win32/shlwapi/autocomp.cpp b/dll/win32/shlwapi/autocomp.cpp new file mode 100644 index 00000000000..bc2c3ca3f14 --- /dev/null +++ b/dll/win32/shlwapi/autocomp.cpp @@ -0,0 +1,226 @@ +/* + * PROJECT: ReactOS shlwapi + * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) + * PURPOSE: Implement SHAutoComplete + * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +static HRESULT +AutoComplete_AddMRU(CComPtr pManager, LPCWSTR pszKey) +{ + CComPtr pMRU; // Create an MRU list + HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_INPROC_SERVER, + IID_IACLCustomMRU, (LPVOID *)&pMRU); + if (FAILED(hr)) + { + ERR("CoCreateInstance(CLSID_ACLMRU) failed with 0x%08lX\n", hr); + return hr; + } + + hr = pMRU->Initialize(pszKey, 'z' - 'a' + 1); // Load the list from registry + if (FAILED(hr)) + { + ERR("pMRU->Initialize(%ls) failed with 0x%08lX\n", pszKey, hr); + return hr; + } + + hr = pManager->Append(pMRU); // Add to the manager + if (FAILED(hr)) + ERR("pManager->Append for '%ls' failed with 0x%08lX\n", pszKey, hr); + return hr; +} + +static HRESULT +IUnknown_SetOptions(CComPtr punk, DWORD dwACLO) +{ + CComPtr pList; + HRESULT hr = punk->QueryInterface(IID_IACList2, (LPVOID *)&pList); + if (FAILED(hr)) + { + ERR("punk->QueryInterface failed: 0x%08lX\n", hr); + return hr; + } + + hr = pList->SetOptions(dwACLO); + if (FAILED(hr)) + ERR("pList->SetOptions failed: 0x%08lX\n", hr); + return hr; +} + +static CComPtr +AutoComplete_LoadList(DWORD dwSHACF, DWORD dwACLO) +{ + // Create a multiple list (with IEnumString interface) + CComPtr pList; + HRESULT hr = CoCreateInstance(CLSID_ACLMulti, NULL, CLSCTX_INPROC_SERVER, + IID_IUnknown, (LPVOID *)&pList); + if (FAILED(hr)) // Failed to create the list + { + ERR("CoCreateInstance(CLSID_ACLMulti) failed with 0x%08lX\n", hr); + return NULL; + } + + CComPtr pManager; // This is the manager of the multiple list + hr = pList->QueryInterface(IID_IObjMgr, (LPVOID *)&pManager); + if (FAILED(hr)) // Failed to get interface + { + ERR("pList->QueryInterface failed: 0x%08lX\n", hr); + return NULL; + } + + if (dwSHACF & SHACF_URLMRU) + { + // The MRU (Most-Recently-Used) lists (with IEnumString interface) +#define RUN_MRU_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU" +#define TYPED_URLS_KEY L"Software\\Microsoft\\Internet Explorer\\TypedURLs" + AutoComplete_AddMRU(pManager, RUN_MRU_KEY); + AutoComplete_AddMRU(pManager, TYPED_URLS_KEY); + } + + if (dwSHACF & SHACF_URLHISTORY) + { + // The history list (with IEnumString interface) + CComPtr pHistory; + hr = CoCreateInstance(CLSID_ACLHistory, NULL, CLSCTX_INPROC_SERVER, + IID_IUnknown, (LPVOID *)&pHistory); + if (SUCCEEDED(hr)) + { + pManager->Append(pHistory); // Add to the manager + // Set ACLO_* options + IUnknown_SetOptions(pHistory, dwACLO | ACLO_CURRENTDIR | ACLO_MYCOMPUTER); + } + else + { + ERR("CLSID_ACLHistory hr:%08lX\n", hr); + } + } + + if (dwSHACF & (SHACF_FILESYSTEM | SHACF_FILESYS_ONLY | SHACF_FILESYS_DIRS)) + { + // The filesystem list (with IEnumString interface) + CComPtr pISF; + hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_INPROC_SERVER, + IID_IUnknown, (LPVOID *)&pISF); + if (SUCCEEDED(hr)) + { + pManager->Append(pISF); // Add to the manager + // Set ACLO_* options + IUnknown_SetOptions(pISF, dwACLO | ACLO_CURRENTDIR | ACLO_MYCOMPUTER); + } + else + { + ERR("CLSID_ACListISF hr:%08lX\n", hr); + } + } + + return pList; // The list +} + +static VOID +AutoComplete_AdaptFlags(IN HWND hwndEdit, + IN OUT LPDWORD pdwSHACF, + OUT LPDWORD pdwACO, + OUT LPDWORD pdwACLO) +{ +#define AUTOCOMPLETE_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete" + DWORD dwSHACF = *pdwSHACF, dwACO = 0, dwACLO = 0; + if (dwSHACF == SHACF_DEFAULT) + dwSHACF = SHACF_FILESYSTEM | SHACF_URLALL; + + if (!(dwSHACF & SHACF_AUTOAPPEND_FORCE_OFF) && + ((dwSHACF & SHACF_AUTOAPPEND_FORCE_ON) || + SHRegGetBoolUSValueW(AUTOCOMPLETE_KEY, L"Append Completion", FALSE, FALSE))) + { + dwACO |= ACO_AUTOAPPEND; + } + + if (!(dwSHACF & SHACF_AUTOSUGGEST_FORCE_OFF) && + ((dwSHACF & SHACF_AUTOSUGGEST_FORCE_ON) || + SHRegGetBoolUSValueW(AUTOCOMPLETE_KEY, L"AutoSuggest", FALSE, TRUE))) + { + dwACO |= ACO_AUTOSUGGEST; + } + + if (dwSHACF & SHACF_FILESYS_DIRS) + dwACLO |= ACLO_FILESYSDIRS; + if (dwSHACF & SHACF_FILESYS_ONLY) + dwACLO |= ACLO_FILESYSONLY; + + static BOOL s_bAlwaysUseTab = 99; + if (s_bAlwaysUseTab == 99) + s_bAlwaysUseTab = SHRegGetBoolUSValueW(AUTOCOMPLETE_KEY, L"Always Use Tab", FALSE, FALSE); + + if (s_bAlwaysUseTab || (dwSHACF & SHACF_USETAB)) + dwACO |= ACO_USETAB; + + if (GetWindowLongPtrW(hwndEdit, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) + dwACO |= ACO_RTLREADING; + + *pdwACO = dwACO; + *pdwSHACF = dwSHACF; + *pdwACLO = dwACLO; +} + +/************************************************************************* + * SHAutoComplete [SHLWAPI.@] + * + * Enable auto-completion for an edit control. + * + * PARAMS + * hwndEdit [I] Handle of control to enable auto-completion for + * dwFlags [I] SHACF_ flags from "shlwapi.h" + * + * RETURNS + * Success: S_OK. Auto-completion is enabled for the control. + * Failure: An HRESULT error code indicating the error. + */ +HRESULT WINAPI SHAutoComplete(HWND hwndEdit, DWORD dwFlags) +{ + TRACE("SHAutoComplete(%p, 0x%lX)\n", hwndEdit, dwFlags); + + DWORD dwACO = 0, dwACLO = 0, dwSHACF = dwFlags; + AutoComplete_AdaptFlags(hwndEdit, &dwACO, &dwACLO, &dwSHACF); + + // Load the list (with IEnumString interface) + CComPtr pList = AutoComplete_LoadList(dwSHACF, dwACLO); + if (!pList) + { + ERR("Out of memory\n"); + return E_OUTOFMEMORY; + } + + // Create an auto-completion (IAutoComplete2) + CComPtr pAC2; + HRESULT hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, + IID_IAutoComplete2, (LPVOID *)&pAC2); + if (FAILED(hr)) + { + ERR("CoCreateInstance(CLSID_AutoComplete) failed: 0x%lX\n", hr); + return hr; + } + + // Keep the DLLs of CLSID_ACListISF and CLSID_AutoComplete loaded + hr = E_FAIL; + if (SHPinDllOfCLSID(CLSID_ACListISF) && SHPinDllOfCLSID(CLSID_AutoComplete)) + { + // Initialize IAutoComplete2 for auto-completion + hr = pAC2->Init(hwndEdit, pList, NULL, NULL); + if (SUCCEEDED(hr)) + pAC2->SetOptions(dwACO); // Set ACO_* flags + else + ERR("IAutoComplete2::Init failed: 0x%lX\n", hr); + } + + return hr; +} diff --git a/dll/win32/shlwapi/url.c b/dll/win32/shlwapi/url.c index c858ebde695..0ac96a03b7c 100644 --- a/dll/win32/shlwapi/url.c +++ b/dll/win32/shlwapi/url.c @@ -2514,6 +2514,7 @@ HRESULT WINAPI UrlCreateFromPathW(LPCWSTR pszPath, LPWSTR pszUrl, LPDWORD pcchUr return ret; } +#ifndef __REACTOS__ /************************************************************************* * SHAutoComplete [SHLWAPI.@] * @@ -2532,6 +2533,7 @@ HRESULT WINAPI SHAutoComplete(HWND hwndEdit, DWORD dwFlags) FIXME("stub\n"); return S_FALSE; } +#endif /************************************************************************* * MLBuildResURLA [SHLWAPI.405] diff --git a/sdk/include/reactos/shlwapi_undoc.h b/sdk/include/reactos/shlwapi_undoc.h index 328bd511db6..c1f92559e55 100644 --- a/sdk/include/reactos/shlwapi_undoc.h +++ b/sdk/include/reactos/shlwapi_undoc.h @@ -33,6 +33,7 @@ BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen); #define SHAboutInfo SHAboutInfoA #endif +HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid); HRESULT WINAPI IUnknown_QueryStatus(IUnknown *lpUnknown, REFGUID pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText); HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn, VARIANT* pvaOut); LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags);