1 /* 2 * PROJECT: ReactOS shdocvw 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: CLSID_ShellWindows and WinList_* functions 5 * COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #include "objects.h" 9 10 #include <wine/debug.h> 11 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); 12 13 static VARIANT s_vaEmpty = { VT_EMPTY }; 14 15 static HRESULT 16 InitVariantFromBuffer( 17 _Out_ LPVARIANTARG pvarg, 18 _In_ LPCVOID pv, 19 _In_ SIZE_T cb) 20 { 21 VariantInit(pvarg); 22 23 LPSAFEARRAY pArray = SafeArrayCreateVector(VT_UI1, 0, cb); 24 if (!pArray) 25 { 26 ERR("!pArray\n"); 27 return E_OUTOFMEMORY; 28 } 29 30 V_ARRAY(pvarg) = pArray; 31 V_VT(pvarg) = VT_ARRAY | VT_UI1; 32 CopyMemory(pArray->pvData, pv, cb); 33 return S_OK; 34 } 35 36 static HRESULT 37 InitVariantFromIDList( 38 _Out_ LPVARIANTARG pvarg, 39 _In_ LPCITEMIDLIST pidl) 40 { 41 return InitVariantFromBuffer(pvarg, pidl, ILGetSize(pidl)); 42 } 43 44 static HRESULT 45 VariantClearLazy(_Inout_ LPVARIANTARG pvarg) 46 { 47 switch (V_VT(pvarg)) 48 { 49 case VT_EMPTY: 50 case VT_BOOL: 51 case VT_I4: 52 case VT_UI4: 53 break; 54 case VT_UNKNOWN: 55 if (V_UNKNOWN(pvarg)) 56 V_UNKNOWN(pvarg)->Release(); 57 break; 58 case VT_DISPATCH: 59 if (V_DISPATCH(pvarg)) 60 V_DISPATCH(pvarg)->Release(); 61 break; 62 case VT_SAFEARRAY: 63 SafeArrayDestroy(V_ARRAY(pvarg)); 64 break; 65 default: 66 return VariantClear(pvarg); 67 } 68 V_VT(pvarg) = VT_EMPTY; 69 return S_OK; 70 } 71 72 /************************************************************************* 73 * WinList_Init (SHDOCVW.110) 74 * 75 * Retired in NT 6.1. 76 */ 77 EXTERN_C 78 BOOL WINAPI 79 WinList_Init(VOID) 80 { 81 FIXME("()\n"); 82 return FALSE; 83 } 84 85 /************************************************************************* 86 * WinList_Terminate (SHDOCVW.111) 87 * 88 * NT 4.71 and higher. Retired in NT 6.1. 89 */ 90 EXTERN_C 91 VOID WINAPI 92 WinList_Terminate(VOID) 93 { 94 FIXME("()\n"); 95 } 96 97 /************************************************************************* 98 * WinList_GetShellWindows (SHDOCVW.179) 99 * 100 * NT 5.0 and higher. 101 * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nn-exdisp-ishellwindows 102 */ 103 EXTERN_C 104 IShellWindows* WINAPI 105 WinList_GetShellWindows( 106 _In_ BOOL bCreate) 107 { 108 FIXME("(%d)\n", bCreate); 109 return NULL; 110 } 111 112 /************************************************************************* 113 * WinList_NotifyNewLocation (SHDOCVW.177) 114 * 115 * NT 5.0 and higher. 116 * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nf-exdisp-ishellwindows-onnavigate 117 */ 118 EXTERN_C 119 HRESULT WINAPI 120 WinList_NotifyNewLocation( 121 _In_ IShellWindows *pShellWindows, 122 _In_ LONG lCookie, 123 _In_ LPCITEMIDLIST pidl) 124 { 125 TRACE("(%p, %ld, %p)\n", pShellWindows, lCookie, pidl); 126 127 if (!pidl) 128 { 129 ERR("!pidl\n"); 130 return E_UNEXPECTED; 131 } 132 133 VARIANTARG varg; 134 HRESULT hr = InitVariantFromIDList(&varg, pidl); 135 if (FAILED_UNEXPECTEDLY(hr)) 136 return hr; 137 138 hr = pShellWindows->OnNavigate(lCookie, &varg); 139 VariantClearLazy(&varg); 140 return hr; 141 } 142 143 /************************************************************************* 144 * WinList_FindFolderWindow (SHDOCVW.178) 145 * 146 * NT 5.0 and higher. 147 * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nf-exdisp-ishellwindows-findwindowsw 148 */ 149 EXTERN_C 150 HRESULT WINAPI 151 WinList_FindFolderWindow( 152 _In_ LPCITEMIDLIST pidl, 153 _In_ DWORD dwUnused, 154 _Out_opt_ PLONG phwnd, // Stores a window handle but LONG type 155 _Out_opt_ IWebBrowserApp **ppWebBrowserApp) 156 { 157 UNREFERENCED_PARAMETER(dwUnused); 158 159 TRACE("(%p, %ld, %p, %p)\n", pidl, dwUnused, phwnd, ppWebBrowserApp); 160 161 if (ppWebBrowserApp) 162 *ppWebBrowserApp = NULL; 163 164 if (phwnd) 165 *phwnd = 0; 166 167 if (!pidl) 168 { 169 ERR("!pidl\n"); 170 return E_UNEXPECTED; 171 } 172 173 CComPtr<IShellWindows> pShellWindows(WinList_GetShellWindows(ppWebBrowserApp != NULL)); 174 if (!pShellWindows) 175 { 176 ERR("!pShellWindows\n"); 177 return E_UNEXPECTED; 178 } 179 180 VARIANTARG varg; 181 HRESULT hr = InitVariantFromIDList(&varg, pidl); 182 if (FAILED_UNEXPECTEDLY(hr)) 183 return hr; 184 185 CComPtr<IDispatch> pDispatch; 186 const INT options = SWFO_INCLUDEPENDING | (ppWebBrowserApp ? SWFO_NEEDDISPATCH : 0); 187 hr = pShellWindows->FindWindowSW(&varg, &s_vaEmpty, SWC_BROWSER, phwnd, options, &pDispatch); 188 if (pDispatch && ppWebBrowserApp) 189 hr = pDispatch->QueryInterface(IID_PPV_ARG(IWebBrowserApp, ppWebBrowserApp)); 190 191 VariantClearLazy(&varg); 192 return hr; 193 } 194 195 /************************************************************************* 196 * WinList_RegisterPending (SHDOCVW.180) 197 * 198 * NT 5.0 and higher. 199 * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nf-exdisp-ishellwindows-registerpending 200 */ 201 EXTERN_C 202 HRESULT WINAPI 203 WinList_RegisterPending( 204 _In_ DWORD dwThreadId, 205 _In_ LPCITEMIDLIST pidl, 206 _In_ DWORD dwUnused, 207 _Out_ PLONG plCookie) 208 { 209 TRACE("(%ld, %p, %ld, %p)\n", dwThreadId, pidl, dwUnused, plCookie); 210 211 if (!pidl) 212 { 213 ERR("!pidl\n"); 214 return E_UNEXPECTED; 215 } 216 217 CComPtr<IShellWindows> pShellWindows(WinList_GetShellWindows(FALSE)); 218 if (!pShellWindows) 219 { 220 ERR("!pShellWindows\n"); 221 return E_UNEXPECTED; 222 } 223 224 VARIANTARG varg; 225 HRESULT hr = InitVariantFromIDList(&varg, pidl); 226 if (FAILED_UNEXPECTEDLY(hr)) 227 return hr; 228 229 hr = pShellWindows->RegisterPending(dwThreadId, &varg, &s_vaEmpty, SWC_BROWSER, plCookie); 230 VariantClearLazy(&varg); 231 return hr; 232 } 233 234 /************************************************************************* 235 * WinList_Revoke (SHDOCVW.181) 236 * 237 * NT 5.0 and higher. 238 * @see https://learn.microsoft.com/en-us/windows/win32/api/exdisp/nf-exdisp-ishellwindows-revoke 239 */ 240 EXTERN_C 241 HRESULT WINAPI 242 WinList_Revoke( 243 _In_ LONG lCookie) 244 { 245 TRACE("(%ld)\n", lCookie); 246 247 CComPtr<IShellWindows> pShellWindows(WinList_GetShellWindows(TRUE)); 248 if (!pShellWindows) 249 { 250 ERR("!pShellWindows\n"); 251 return E_FAIL; 252 } 253 254 return pShellWindows->Revoke(lCookie); 255 } 256