diff --git a/base/shell/explorer/precomp.h b/base/shell/explorer/precomp.h index df60ef3a6f5..f90ec62f1a8 100644 --- a/base/shell/explorer/precomp.h +++ b/base/shell/explorer/precomp.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -119,7 +120,7 @@ VOID InitRSHELL(VOID); HRESULT WINAPI _CStartMenu_CreateInstance(REFIID riid, void **ppv); HANDLE WINAPI _SHCreateDesktop(IShellDesktopTray *ShellDesk); BOOL WINAPI _SHDesktopMessageLoop(HANDLE hDesktop); -DWORD WINAPI _WinList_Init(void); +BOOL WINAPI _WinList_Init(void); void WINAPI _ShellDDEInit(BOOL bInit); HRESULT WINAPI _CBandSiteMenu_CreateInstance(REFIID riid, void **ppv); HRESULT WINAPI _CBandSite_CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv); diff --git a/base/shell/explorer/rshell.cpp b/base/shell/explorer/rshell.cpp index 9767c23504d..bdd5571ade6 100644 --- a/base/shell/explorer/rshell.cpp +++ b/base/shell/explorer/rshell.cpp @@ -105,9 +105,9 @@ BOOL WINAPI _SHDesktopMessageLoop(HANDLE hDesktop) return FALSE; } -typedef DWORD(WINAPI* PWINLIST_INIT)(void); +typedef BOOL (WINAPI *PWINLIST_INIT)(void); -DWORD WINAPI _WinList_Init(void) +BOOL WINAPI _WinList_Init(void) { HINSTANCE hFallback; @@ -131,7 +131,7 @@ DWORD WINAPI _WinList_Init(void) } } - return 0; + return FALSE; } typedef void (WINAPI *PSHELLDDEINIT)(BOOL bInit); diff --git a/base/shell/rshell/misc.cpp b/base/shell/rshell/misc.cpp index d0ed8c83e1b..8e0403f4cfd 100644 --- a/base/shell/rshell/misc.cpp +++ b/base/shell/rshell/misc.cpp @@ -52,12 +52,6 @@ extern "C" HRESULT WINAPI RSHELL_CMergedFolder_CreateInstance(REFIID riid, LPVOID *ppv); } -DWORD WINAPI WinList_Init(void) -{ - /* do something here (perhaps we may want to add our own implementation fo win8) */ - return 0; -} - class CRShellModule : public CComModule { public: diff --git a/dll/win32/shdocvw/CMakeLists.txt b/dll/win32/shdocvw/CMakeLists.txt index 119e8aaf882..6d178708672 100644 --- a/dll/win32/shdocvw/CMakeLists.txt +++ b/dll/win32/shdocvw/CMakeLists.txt @@ -37,7 +37,8 @@ add_library(shdocvw_sublib OBJECT CNSCBand.cpp mrulist.cpp objects.cpp - utility.cpp) + utility.cpp + winlist.cpp) target_link_libraries(shdocvw_sublib PRIVATE atl_classes) target_compile_definitions(shdocvw_sublib PRIVATE $) target_compile_options(shdocvw_sublib PRIVATE $) diff --git a/dll/win32/shdocvw/shdocvw.spec b/dll/win32/shdocvw/shdocvw.spec index 0a8bd10cd84..e0b72b28de3 100644 --- a/dll/win32/shdocvw/shdocvw.spec +++ b/dll/win32/shdocvw/shdocvw.spec @@ -8,7 +8,7 @@ @ stdcall -private DllGetClassObject(ptr ptr ptr) @ stdcall -private DllGetVersion(ptr) 110 stdcall -noname WinList_Init() -111 stub -noname WinList_Terminate +111 stdcall -noname WinList_Terminate() @ stdcall -private DllInstall(long wstr) @ stdcall -private DllRegisterServer() @ stub DllRegisterWindowClasses @@ -74,11 +74,11 @@ 174 stub -noname SHIsGlobalOffline 175 stub -noname DetectAndFixAssociations 176 stub -noname EnsureWebViewRegSettings -177 stub -noname WinList_NotifyNewLocation -178 stub -noname WinList_FindFolderWindow -179 stub -noname WinList_GetShellWindows -180 stub -noname WinList_RegisterPending -181 stub -noname WinList_Revoke +177 stdcall -noname WinList_NotifyNewLocation(ptr long ptr) +178 stdcall -noname WinList_FindFolderWindow(ptr long ptr ptr) +179 stdcall -noname WinList_GetShellWindows(long) +180 stdcall -noname WinList_RegisterPending(long ptr long ptr) +181 stdcall -noname WinList_Revoke(long) 182 stdcall SetQueryNetSessionCount(long) 183 stub -noname SHMapNbspToSp 184 stub SetShellOfflineState diff --git a/dll/win32/shdocvw/shdocvw_main.c b/dll/win32/shdocvw/shdocvw_main.c index c817bbb3c5f..65e3c733c79 100644 --- a/dll/win32/shdocvw/shdocvw_main.c +++ b/dll/win32/shdocvw/shdocvw_main.c @@ -236,6 +236,7 @@ static BOOL SHDOCVW_LoadShell32(void) return ((SHDOCVW_hshell32 = LoadLibraryA("shell32.dll")) != NULL); } +#ifndef __REACTOS__ /* See winlist.cpp */ /*********************************************************************** * @ (SHDOCVW.110) * @@ -247,6 +248,7 @@ DWORD WINAPI WinList_Init(void) FIXME("(), stub!\n"); return 0x0deadfeed; } +#endif /* ndef __REACTOS__ */ /*********************************************************************** * @ (SHDOCVW.118) diff --git a/dll/win32/shdocvw/winlist.cpp b/dll/win32/shdocvw/winlist.cpp new file mode 100644 index 00000000000..72562d77b42 --- /dev/null +++ b/dll/win32/shdocvw/winlist.cpp @@ -0,0 +1,255 @@ +/* + * PROJECT: ReactOS shdocvw + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: CLSID_ShellWindows and WinList_* functions + * COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ + */ + +#include "objects.h" + +#include +WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); + +static VARIANT s_vaEmpty = { VT_EMPTY }; + +static HRESULT +InitVariantFromBuffer( + _Out_ LPVARIANTARG pvarg, + _In_ LPCVOID pv, + _In_ SIZE_T cb) +{ + VariantInit(pvarg); + + LPSAFEARRAY pArray = SafeArrayCreateVector(VT_UI1, 0, cb); + if (!pArray) + { + ERR("!pArray\n"); + return E_OUTOFMEMORY; + } + + V_ARRAY(pvarg) = pArray; + V_VT(pvarg) = VT_ARRAY | VT_UI1; + CopyMemory(pArray->pvData, pv, cb); + return S_OK; +} + +static HRESULT +InitVariantFromIDList( + _Out_ LPVARIANTARG pvarg, + _In_ LPCITEMIDLIST pidl) +{ + return InitVariantFromBuffer(pvarg, pidl, ILGetSize(pidl)); +} + +static HRESULT +VariantClearLazy(_Inout_ LPVARIANTARG pvarg) +{ + switch (V_VT(pvarg)) + { + case VT_EMPTY: + case VT_BOOL: + case VT_I4: + case VT_UI4: + break; + case VT_UNKNOWN: + if (V_UNKNOWN(pvarg)) + V_UNKNOWN(pvarg)->Release(); + break; + case VT_DISPATCH: + if (V_DISPATCH(pvarg)) + V_DISPATCH(pvarg)->Release(); + break; + case VT_SAFEARRAY: + SafeArrayDestroy(V_ARRAY(pvarg)); + break; + default: + return VariantClear(pvarg); + } + V_VT(pvarg) = VT_EMPTY; + return S_OK; +} + +/************************************************************************* + * WinList_Init (SHDOCVW.110) + * + * Retired in NT 6.1. + */ +EXTERN_C +BOOL WINAPI +WinList_Init(VOID) +{ + FIXME("()\n"); + return FALSE; +} + +/************************************************************************* + * WinList_Terminate (SHDOCVW.111) + * + * NT 4.71 and higher. Retired in NT 6.1. + */ +EXTERN_C +VOID WINAPI +WinList_Terminate(VOID) +{ + FIXME("()\n"); +} + +/************************************************************************* + * WinList_GetShellWindows (SHDOCVW.179) + * + * NT 5.0 and higher. + * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nn-exdisp-ishellwindows + */ +EXTERN_C +IShellWindows* WINAPI +WinList_GetShellWindows( + _In_ BOOL bCreate) +{ + FIXME("(%d)\n", bCreate); + return NULL; +} + +/************************************************************************* + * WinList_NotifyNewLocation (SHDOCVW.177) + * + * NT 5.0 and higher. + * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nf-exdisp-ishellwindows-onnavigate + */ +EXTERN_C +HRESULT WINAPI +WinList_NotifyNewLocation( + _In_ IShellWindows *pShellWindows, + _In_ LONG lCookie, + _In_ LPCITEMIDLIST pidl) +{ + TRACE("(%p, %ld, %p)\n", pShellWindows, lCookie, pidl); + + if (!pidl) + { + ERR("!pidl\n"); + return E_UNEXPECTED; + } + + VARIANTARG varg; + HRESULT hr = InitVariantFromIDList(&varg, pidl); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = pShellWindows->OnNavigate(lCookie, &varg); + VariantClearLazy(&varg); + return hr; +} + +/************************************************************************* + * WinList_FindFolderWindow (SHDOCVW.178) + * + * NT 5.0 and higher. + * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nf-exdisp-ishellwindows-findwindowsw + */ +EXTERN_C +HRESULT WINAPI +WinList_FindFolderWindow( + _In_ LPCITEMIDLIST pidl, + _In_ DWORD dwUnused, + _Out_opt_ PLONG phwnd, // Stores a window handle but LONG type + _Out_opt_ IWebBrowserApp **ppWebBrowserApp) +{ + UNREFERENCED_PARAMETER(dwUnused); + + TRACE("(%p, %ld, %p, %p)\n", pidl, dwUnused, phwnd, ppWebBrowserApp); + + if (ppWebBrowserApp) + *ppWebBrowserApp = NULL; + + if (phwnd) + *phwnd = 0; + + if (!pidl) + { + ERR("!pidl\n"); + return E_UNEXPECTED; + } + + CComPtr pShellWindows(WinList_GetShellWindows(ppWebBrowserApp != NULL)); + if (!pShellWindows) + { + ERR("!pShellWindows\n"); + return E_UNEXPECTED; + } + + VARIANTARG varg; + HRESULT hr = InitVariantFromIDList(&varg, pidl); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + CComPtr pDispatch; + const INT options = SWFO_INCLUDEPENDING | (ppWebBrowserApp ? SWFO_NEEDDISPATCH : 0); + hr = pShellWindows->FindWindowSW(&varg, &s_vaEmpty, SWC_BROWSER, phwnd, options, &pDispatch); + if (pDispatch && ppWebBrowserApp) + hr = pDispatch->QueryInterface(IID_PPV_ARG(IWebBrowserApp, ppWebBrowserApp)); + + VariantClearLazy(&varg); + return hr; +} + +/************************************************************************* + * WinList_RegisterPending (SHDOCVW.180) + * + * NT 5.0 and higher. + * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nf-exdisp-ishellwindows-registerpending + */ +EXTERN_C +HRESULT WINAPI +WinList_RegisterPending( + _In_ DWORD dwThreadId, + _In_ LPCITEMIDLIST pidl, + _In_ DWORD dwUnused, + _Out_ PLONG plCookie) +{ + TRACE("(%ld, %p, %ld, %p)\n", dwThreadId, pidl, dwUnused, plCookie); + + if (!pidl) + { + ERR("!pidl\n"); + return E_UNEXPECTED; + } + + CComPtr pShellWindows(WinList_GetShellWindows(FALSE)); + if (!pShellWindows) + { + ERR("!pShellWindows\n"); + return E_UNEXPECTED; + } + + VARIANTARG varg; + HRESULT hr = InitVariantFromIDList(&varg, pidl); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = pShellWindows->RegisterPending(dwThreadId, &varg, &s_vaEmpty, SWC_BROWSER, plCookie); + VariantClearLazy(&varg); + return hr; +} + +/************************************************************************* + * WinList_Revoke (SHDOCVW.181) + * + * NT 5.0 and higher. + * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nf-exdisp-ishellwindows-revoke + */ +EXTERN_C +HRESULT WINAPI +WinList_Revoke( + _In_ LONG lCookie) +{ + TRACE("(%ld)\n", lCookie); + + CComPtr pShellWindows(WinList_GetShellWindows(TRUE)); + if (!pShellWindows) + { + ERR("!pShellWindows\n"); + return E_FAIL; + } + + return pShellWindows->Revoke(lCookie); +} diff --git a/sdk/include/reactos/shdocvw_undoc.h b/sdk/include/reactos/shdocvw_undoc.h index 57e3ee8b9d7..31be12fa29c 100644 --- a/sdk/include/reactos/shdocvw_undoc.h +++ b/sdk/include/reactos/shdocvw_undoc.h @@ -2,14 +2,16 @@ * PROJECT: ReactOS Headers * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * PURPOSE: shdocvw.dll undocumented APIs - * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + * COPYRIGHT: Copyright 2024-2025 Katayama Hirofumi MZ */ #pragma once +#include // For IShellWindows + #ifdef __cplusplus extern "C" { -#endif /* defined(__cplusplus) */ +#endif BOOL WINAPI IEILIsEqual( @@ -17,6 +19,31 @@ IEILIsEqual( _In_ LPCITEMIDLIST pidl2, _In_ BOOL bUnknown); +BOOL WINAPI WinList_Init(VOID); +VOID WINAPI WinList_Terminate(VOID); +HRESULT WINAPI WinList_Revoke(_In_ LONG lCookie); +IShellWindows* WINAPI WinList_GetShellWindows(_In_ BOOL bCreate); + +HRESULT WINAPI +WinList_NotifyNewLocation( + _In_ IShellWindows *pShellWindows, + _In_ LONG lCookie, + _In_ LPCITEMIDLIST pidl); + +HRESULT WINAPI +WinList_FindFolderWindow( + _In_ LPCITEMIDLIST pidl, + _In_ DWORD dwUnused, + _Out_opt_ PLONG phwnd, + _Out_opt_ IWebBrowserApp **ppWebBrowserApp); + +HRESULT WINAPI +WinList_RegisterPending( + _In_ DWORD dwThreadId, + _In_ LPCITEMIDLIST pidl, + _In_ DWORD dwUnused, + _Out_ PLONG plCookie); + #ifdef __cplusplus } /* extern "C" */ -#endif /* defined(__cplusplus) */ +#endif diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h index 187a74f4d44..52ef6f27f0b 100644 --- a/sdk/include/reactos/undocshell.h +++ b/sdk/include/reactos/undocshell.h @@ -928,7 +928,6 @@ BOOL WINAPI SHSettingsChanged(LPCVOID unused, LPCWSTR pszKey); #define TABDMC_LOADINPROC 2 void WINAPI ShellDDEInit(BOOL bInit); -DWORD WINAPI WinList_Init(void); IStream* WINAPI SHGetViewStream(LPCITEMIDLIST, DWORD, LPCTSTR, LPCTSTR, LPCTSTR);