xref: /reactos/dll/win32/shdocvw/winlist.cpp (revision 9c5efed7)
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