259b8919976db83f11542bffb5c41048ffd9abf9
[reactos.git] / dll / win32 / shell32 / CShellDispatch.cpp
1 /*
2 * PROJECT: shell32
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: IShellDispatch implementation
5 * COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include "precomp.h"
9 #include "winsvc.h"
10
11 WINE_DEFAULT_DEBUG_CHANNEL(shell);
12
13
14 CShellDispatch::CShellDispatch()
15 {
16 }
17
18 CShellDispatch::~CShellDispatch()
19 {
20 }
21
22 HRESULT CShellDispatch::Initialize()
23 {
24 return S_OK;
25 }
26
27 // *** IShellDispatch methods ***
28 HRESULT STDMETHODCALLTYPE CShellDispatch::get_Application(IDispatch **ppid)
29 {
30 TRACE("(%p, %p)\n", this, ppid);
31
32 if (!ppid)
33 return E_INVALIDARG;
34
35 *ppid = this;
36 AddRef();
37
38 return S_OK;
39 }
40
41 HRESULT STDMETHODCALLTYPE CShellDispatch::get_Parent(IDispatch **ppid)
42 {
43 TRACE("(%p, %p)\n", this, ppid);
44
45 if (ppid)
46 {
47 *ppid = static_cast<IDispatch*>(this);
48 AddRef();
49 }
50
51 return S_OK;
52 }
53
54 HRESULT VariantToIdlist(VARIANT* var, LPITEMIDLIST* idlist)
55 {
56 HRESULT hr = S_FALSE;
57 if(V_VT(var) == VT_I4)
58 {
59 hr = SHGetSpecialFolderLocation(NULL, V_I4(var), idlist);
60 }
61 else if(V_VT(var) == VT_BSTR)
62 {
63 hr = SHILCreateFromPathW(V_BSTR(var), idlist, NULL);
64 }
65 return hr;
66 }
67
68 HRESULT STDMETHODCALLTYPE CShellDispatch::NameSpace(VARIANT vDir, Folder **ppsdf)
69 {
70 TRACE("(%p, %s, %p)\n", this, debugstr_variant(&vDir), ppsdf);
71 if (!ppsdf)
72 return E_POINTER;
73 *ppsdf = NULL;
74 HRESULT hr;
75
76 if (V_VT(&vDir) == VT_I2)
77 {
78 hr = VariantChangeType(&vDir, &vDir, 0, VT_I4);
79 if (FAILED_UNEXPECTEDLY(hr))
80 return hr;
81 }
82
83 CComHeapPtr<ITEMIDLIST> idlist;
84 hr = VariantToIdlist(&vDir, &idlist);
85 if (!SUCCEEDED(hr) || !idlist)
86 return S_FALSE;
87
88 return ShellObjectCreatorInit<CFolder>(static_cast<LPITEMIDLIST>(idlist), IID_PPV_ARG(Folder, ppsdf));
89 }
90
91 static BOOL is_optional_argument(const VARIANT *arg)
92 {
93 return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND;
94 }
95
96 HRESULT STDMETHODCALLTYPE CShellDispatch::BrowseForFolder(LONG Hwnd, BSTR Title, LONG Options, VARIANT RootFolder, Folder **ppsdf)
97 {
98 TRACE("(%p, %lu, %ls, %lu, %s, %p)\n", this, Hwnd, Title, Options, debugstr_variant(&RootFolder), ppsdf);
99
100 *ppsdf = NULL;
101
102 if (!is_optional_argument(&RootFolder))
103 FIXME("root folder is ignored\n");
104
105 BROWSEINFOW bi = { 0 };
106 bi.hwndOwner = reinterpret_cast<HWND>(LongToHandle(Hwnd));
107 bi.lpszTitle = Title;
108 bi.ulFlags = Options;
109
110 CComHeapPtr<ITEMIDLIST> selection;
111 selection.Attach(SHBrowseForFolderW(&bi));
112 if (!selection)
113 return S_FALSE;
114
115 return ShellObjectCreatorInit<CFolder>(static_cast<LPITEMIDLIST>(selection), IID_PPV_ARG(Folder, ppsdf));
116 }
117
118 HRESULT STDMETHODCALLTYPE CShellDispatch::Windows(IDispatch **ppid)
119 {
120 TRACE("(%p, %p)\n", this, ppid);
121
122 *ppid = NULL;
123
124 return E_NOTIMPL;
125 }
126
127 HRESULT STDMETHODCALLTYPE CShellDispatch::Open(VARIANT vDir)
128 {
129 TRACE("(%p, %s)\n", this, debugstr_variant(&vDir));
130 return E_NOTIMPL;
131 }
132
133 HRESULT STDMETHODCALLTYPE CShellDispatch::Explore(VARIANT vDir)
134 {
135 TRACE("(%p, %s)\n", this, debugstr_variant(&vDir));
136 return E_NOTIMPL;
137 }
138
139 HRESULT STDMETHODCALLTYPE CShellDispatch::MinimizeAll()
140 {
141 TRACE("(%p)\n", this);
142 return E_NOTIMPL;
143 }
144
145 HRESULT STDMETHODCALLTYPE CShellDispatch::UndoMinimizeALL()
146 {
147 TRACE("(%p)\n", this);
148 return E_NOTIMPL;
149 }
150
151 HRESULT STDMETHODCALLTYPE CShellDispatch::FileRun()
152 {
153 TRACE("(%p)\n", this);
154 return E_NOTIMPL;
155 }
156
157 HRESULT STDMETHODCALLTYPE CShellDispatch::CascadeWindows()
158 {
159 TRACE("(%p)\n", this);
160 return E_NOTIMPL;
161 }
162
163 HRESULT STDMETHODCALLTYPE CShellDispatch::TileVertically()
164 {
165 TRACE("(%p)\n", this);
166 return E_NOTIMPL;
167 }
168
169 HRESULT STDMETHODCALLTYPE CShellDispatch::TileHorizontally()
170 {
171 TRACE("(%p)\n", this);
172 return E_NOTIMPL;
173 }
174
175 HRESULT STDMETHODCALLTYPE CShellDispatch::ShutdownWindows()
176 {
177 ExitWindowsDialog(NULL);
178 return S_OK;
179 }
180
181 HRESULT STDMETHODCALLTYPE CShellDispatch::Suspend()
182 {
183 TRACE("(%p)\n", this);
184 return E_NOTIMPL;
185 }
186
187 HRESULT STDMETHODCALLTYPE CShellDispatch::EjectPC()
188 {
189 TRACE("(%p)\n", this);
190 return E_NOTIMPL;
191 }
192
193 HRESULT STDMETHODCALLTYPE CShellDispatch::SetTime()
194 {
195 TRACE("(%p)\n", this);
196 return E_NOTIMPL;
197 }
198
199 HRESULT STDMETHODCALLTYPE CShellDispatch::TrayProperties()
200 {
201 TRACE("(%p)\n", this);
202 return E_NOTIMPL;
203 }
204
205 HRESULT STDMETHODCALLTYPE CShellDispatch::Help()
206 {
207 TRACE("(%p)\n", this);
208 return E_NOTIMPL;
209 }
210
211 HRESULT STDMETHODCALLTYPE CShellDispatch::FindFiles()
212 {
213 TRACE("(%p)\n", this);
214 return E_NOTIMPL;
215 }
216
217 HRESULT STDMETHODCALLTYPE CShellDispatch::FindComputer()
218 {
219 TRACE("(%p)\n", this);
220 return E_NOTIMPL;
221 }
222
223 HRESULT STDMETHODCALLTYPE CShellDispatch::RefreshMenu()
224 {
225 TRACE("(%p)\n", this);
226 return E_NOTIMPL;
227 }
228
229 HRESULT STDMETHODCALLTYPE CShellDispatch::ControlPanelItem(BSTR szDir)
230 {
231 TRACE("(%p, %ls)\n", this, szDir);
232 return E_NOTIMPL;
233 }
234
235
236 // *** IShellDispatch2 methods ***
237 HRESULT STDMETHODCALLTYPE CShellDispatch::IsRestricted(BSTR group, BSTR restriction, LONG *value)
238 {
239 TRACE("(%p, %ls, %ls, %p)\n", this, group, restriction, value);
240 return E_NOTIMPL;
241 }
242
243 HRESULT STDMETHODCALLTYPE CShellDispatch::ShellExecute(BSTR file, VARIANT v_args, VARIANT v_dir, VARIANT v_op, VARIANT v_show)
244 {
245 CComVariant args_str, dir_str, op_str, show_int;
246 WCHAR *args = NULL, *dir = NULL, *op = NULL;
247 INT show = 0;
248 HINSTANCE ret;
249
250 TRACE("(%s, %s, %s, %s, %s)\n", debugstr_w(file), debugstr_variant(&v_args),
251 debugstr_variant(&v_dir), debugstr_variant(&v_op), debugstr_variant(&v_show));
252
253 args_str.ChangeType(VT_BSTR, &v_args);
254 if (V_VT(&args_str) == VT_BSTR)
255 args = V_BSTR(&args_str);
256
257 dir_str.ChangeType(VT_BSTR, &v_dir);
258 if (V_VT(&dir_str) == VT_BSTR)
259 dir = V_BSTR(&dir_str);
260
261 op_str.ChangeType(VT_BSTR, &v_op);
262 if (V_VT(&op_str) == VT_BSTR)
263 op = V_BSTR(&op_str);
264
265 show_int.ChangeType(VT_I4, &v_show);
266 if (V_VT(&show_int) == VT_I4)
267 show = V_I4(&show_int);
268
269 ret = ShellExecuteW(NULL, op, file, args, dir, show);
270
271 return (ULONG_PTR)ret > 32 ? S_OK : S_FALSE;
272 }
273
274 HRESULT STDMETHODCALLTYPE CShellDispatch::FindPrinter(BSTR name, BSTR location, BSTR model)
275 {
276 TRACE("(%p, %ls, %ls, %ls)\n", this, name, location, model);
277 return E_NOTIMPL;
278 }
279
280 HRESULT STDMETHODCALLTYPE CShellDispatch::GetSystemInformation(BSTR name, VARIANT *ret)
281 {
282 TRACE("(%p, %ls, %p)\n", this, name, ret);
283 return E_NOTIMPL;
284 }
285
286 HRESULT STDMETHODCALLTYPE CShellDispatch::ServiceStart(BSTR service, VARIANT persistent, VARIANT *ret)
287 {
288 TRACE("(%p, %ls, %s, %p)\n", this, service, wine_dbgstr_variant(&persistent), ret);
289 return E_NOTIMPL;
290 }
291
292 HRESULT STDMETHODCALLTYPE CShellDispatch::ServiceStop(BSTR service, VARIANT persistent, VARIANT *ret)
293 {
294 TRACE("(%p, %ls, %s, %p)\n", this, service, wine_dbgstr_variant(&persistent), ret);
295 return E_NOTIMPL;
296 }
297
298 HRESULT STDMETHODCALLTYPE CShellDispatch::IsServiceRunning(BSTR name, VARIANT *running)
299 {
300 SERVICE_STATUS_PROCESS status;
301 SC_HANDLE scm, service;
302 DWORD dummy;
303
304 TRACE("(%s, %p)\n", debugstr_w(name), running);
305
306 V_VT(running) = VT_BOOL;
307 V_BOOL(running) = VARIANT_FALSE;
308
309 scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
310 if (!scm)
311 {
312 ERR("failed to connect to service manager\n");
313 return S_OK;
314 }
315
316 service = OpenServiceW(scm, name, SERVICE_QUERY_STATUS);
317 if (!service)
318 {
319 ERR("Failed to open service %s (%u)\n", debugstr_w(name), GetLastError());
320 CloseServiceHandle(scm);
321 return S_OK;
322 }
323
324 if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status,
325 sizeof(SERVICE_STATUS_PROCESS), &dummy))
326 {
327 TRACE("failed to query service status (%u)\n", GetLastError());
328 CloseServiceHandle(service);
329 CloseServiceHandle(scm);
330 return S_OK;
331 }
332
333 if (status.dwCurrentState == SERVICE_RUNNING)
334 V_BOOL(running) = VARIANT_TRUE;
335
336 CloseServiceHandle(service);
337 CloseServiceHandle(scm);
338
339 return S_OK;
340 }
341
342 HRESULT STDMETHODCALLTYPE CShellDispatch::CanStartStopService(BSTR service, VARIANT *ret)
343 {
344 TRACE("(%p, %ls, %p)\n", this, service, ret);
345 return E_NOTIMPL;
346 }
347
348 HRESULT STDMETHODCALLTYPE CShellDispatch::ShowBrowserBar(BSTR clsid, VARIANT show, VARIANT *ret)
349 {
350 TRACE("(%p, %ls, %s, %p)\n", this, clsid, wine_dbgstr_variant(&show), ret);
351 return E_NOTIMPL;
352 }
353
354
355 // *** IShellDispatch3 methods ***
356 HRESULT STDMETHODCALLTYPE CShellDispatch::AddToRecent(VARIANT file, BSTR category)
357 {
358 TRACE("(%p, %s, %ls)\n", this, wine_dbgstr_variant(&file), category);
359 return E_NOTIMPL;
360 }
361
362
363 // *** IShellDispatch4 methods ***
364 HRESULT STDMETHODCALLTYPE CShellDispatch::WindowsSecurity()
365 {
366 TRACE("(%p)\n", this);
367 return E_NOTIMPL;
368 }
369
370 HRESULT STDMETHODCALLTYPE CShellDispatch::ToggleDesktop()
371 {
372 TRACE("(%p)\n", this);
373 return E_NOTIMPL;
374 }
375
376 HRESULT STDMETHODCALLTYPE CShellDispatch::ExplorerPolicy(BSTR policy, VARIANT *value)
377 {
378 TRACE("(%p, %ls, %p)\n", this, policy, value);
379 return E_NOTIMPL;
380 }
381
382 HRESULT STDMETHODCALLTYPE CShellDispatch::GetSetting(LONG setting, VARIANT_BOOL *result)
383 {
384 TRACE("(%p, %lu, %p)\n", this, setting, result);
385 return E_NOTIMPL;
386 }
387
388
389 // *** IObjectSafety methods ***
390 HRESULT STDMETHODCALLTYPE CShellDispatch::GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
391 {
392 TRACE("(%p, %s, %p, %p)\n", this, wine_dbgstr_guid(&riid), pdwSupportedOptions, pdwEnabledOptions);
393 return E_NOTIMPL;
394 }
395
396 HRESULT STDMETHODCALLTYPE CShellDispatch::SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
397 {
398 TRACE("(%p, %s, %lu, %lu)\n", this, wine_dbgstr_guid(&riid), dwOptionSetMask, dwEnabledOptions);
399 return E_NOTIMPL;
400 }
401
402
403 // *** IObjectWithSite methods ***
404 HRESULT STDMETHODCALLTYPE CShellDispatch::SetSite(IUnknown *pUnkSite)
405 {
406 TRACE("(%p, %p)\n", this, pUnkSite);
407 return E_NOTIMPL;
408 }
409
410 HRESULT STDMETHODCALLTYPE CShellDispatch::GetSite(REFIID riid, PVOID *ppvSite)
411 {
412 TRACE("(%p, %s, %p)\n", this, wine_dbgstr_guid(&riid), ppvSite);
413 return E_NOTIMPL;
414 }
415
416 HRESULT WINAPI CShellDispatch_Constructor(REFIID riid, LPVOID * ppvOut)
417 {
418 return ShellObjectCreatorInit<CShellDispatch>(riid, ppvOut);
419 }
420