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 * Copyright 2018 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
12 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
15 CShellDispatch::CShellDispatch()
19 CShellDispatch::~CShellDispatch()
23 HRESULT
CShellDispatch::Initialize()
28 // *** IShellDispatch methods ***
29 HRESULT STDMETHODCALLTYPE
CShellDispatch::get_Application(IDispatch
**ppid
)
31 TRACE("(%p, %p)\n", this, ppid
);
42 HRESULT STDMETHODCALLTYPE
CShellDispatch::get_Parent(IDispatch
**ppid
)
44 TRACE("(%p, %p)\n", this, ppid
);
48 *ppid
= static_cast<IDispatch
*>(this);
55 HRESULT
VariantToIdlist(VARIANT
* var
, LPITEMIDLIST
* idlist
)
58 if(V_VT(var
) == VT_I4
)
60 hr
= SHGetSpecialFolderLocation(NULL
, V_I4(var
), idlist
);
62 else if(V_VT(var
) == VT_BSTR
)
64 hr
= SHILCreateFromPathW(V_BSTR(var
), idlist
, NULL
);
69 HRESULT STDMETHODCALLTYPE
CShellDispatch::NameSpace(VARIANT vDir
, Folder
**ppsdf
)
71 TRACE("(%p, %s, %p)\n", this, debugstr_variant(&vDir
), ppsdf
);
77 if (V_VT(&vDir
) == VT_I2
)
79 hr
= VariantChangeType(&vDir
, &vDir
, 0, VT_I4
);
80 if (FAILED_UNEXPECTEDLY(hr
))
84 CComHeapPtr
<ITEMIDLIST
> idlist
;
85 hr
= VariantToIdlist(&vDir
, &idlist
);
86 if (!SUCCEEDED(hr
) || !idlist
)
89 return ShellObjectCreatorInit
<CFolder
>(static_cast<LPITEMIDLIST
>(idlist
), IID_PPV_ARG(Folder
, ppsdf
));
92 static BOOL
is_optional_argument(const VARIANT
*arg
)
94 return V_VT(arg
) == VT_ERROR
&& V_ERROR(arg
) == DISP_E_PARAMNOTFOUND
;
97 HRESULT STDMETHODCALLTYPE
CShellDispatch::BrowseForFolder(LONG Hwnd
, BSTR Title
, LONG Options
, VARIANT RootFolder
, Folder
**ppsdf
)
99 TRACE("(%p, %lu, %ls, %lu, %s, %p)\n", this, Hwnd
, Title
, Options
, debugstr_variant(&RootFolder
), ppsdf
);
103 if (!is_optional_argument(&RootFolder
))
104 FIXME("root folder is ignored\n");
106 BROWSEINFOW bi
= { 0 };
107 bi
.hwndOwner
= reinterpret_cast<HWND
>(LongToHandle(Hwnd
));
108 bi
.lpszTitle
= Title
;
109 bi
.ulFlags
= Options
;
111 CComHeapPtr
<ITEMIDLIST
> selection
;
112 selection
.Attach(SHBrowseForFolderW(&bi
));
116 return ShellObjectCreatorInit
<CFolder
>(static_cast<LPITEMIDLIST
>(selection
), IID_PPV_ARG(Folder
, ppsdf
));
119 HRESULT STDMETHODCALLTYPE
CShellDispatch::Windows(IDispatch
**ppid
)
121 TRACE("(%p, %p)\n", this, ppid
);
128 HRESULT STDMETHODCALLTYPE
CShellDispatch::Open(VARIANT vDir
)
130 TRACE("(%p, %s)\n", this, debugstr_variant(&vDir
));
134 HRESULT STDMETHODCALLTYPE
CShellDispatch::Explore(VARIANT vDir
)
136 TRACE("(%p, %s)\n", this, debugstr_variant(&vDir
));
140 HRESULT STDMETHODCALLTYPE
CShellDispatch::MinimizeAll()
142 TRACE("(%p)\n", this);
146 HRESULT STDMETHODCALLTYPE
CShellDispatch::UndoMinimizeALL()
148 TRACE("(%p)\n", this);
152 HRESULT STDMETHODCALLTYPE
CShellDispatch::FileRun()
154 TRACE("(%p)\n", this);
158 HRESULT STDMETHODCALLTYPE
CShellDispatch::CascadeWindows()
160 TRACE("(%p)\n", this);
164 HRESULT STDMETHODCALLTYPE
CShellDispatch::TileVertically()
166 TRACE("(%p)\n", this);
170 HRESULT STDMETHODCALLTYPE
CShellDispatch::TileHorizontally()
172 TRACE("(%p)\n", this);
176 HRESULT STDMETHODCALLTYPE
CShellDispatch::ShutdownWindows()
178 ExitWindowsDialog(NULL
);
182 HRESULT STDMETHODCALLTYPE
CShellDispatch::Suspend()
184 TRACE("(%p)\n", this);
188 HRESULT STDMETHODCALLTYPE
CShellDispatch::EjectPC()
190 TRACE("(%p)\n", this);
194 HRESULT STDMETHODCALLTYPE
CShellDispatch::SetTime()
196 TRACE("(%p)\n", this);
200 HRESULT STDMETHODCALLTYPE
CShellDispatch::TrayProperties()
202 TRACE("(%p)\n", this);
206 HRESULT STDMETHODCALLTYPE
CShellDispatch::Help()
208 TRACE("(%p)\n", this);
212 HRESULT STDMETHODCALLTYPE
CShellDispatch::FindFiles()
214 TRACE("(%p)\n", this);
218 HRESULT STDMETHODCALLTYPE
CShellDispatch::FindComputer()
220 TRACE("(%p)\n", this);
224 HRESULT STDMETHODCALLTYPE
CShellDispatch::RefreshMenu()
226 TRACE("(%p)\n", this);
230 HRESULT STDMETHODCALLTYPE
CShellDispatch::ControlPanelItem(BSTR szDir
)
232 TRACE("(%p, %ls)\n", this, szDir
);
237 // *** IShellDispatch2 methods ***
238 HRESULT STDMETHODCALLTYPE
CShellDispatch::IsRestricted(BSTR group
, BSTR restriction
, LONG
*value
)
240 TRACE("(%p, %ls, %ls, %p)\n", this, group
, restriction
, value
);
244 HRESULT STDMETHODCALLTYPE
CShellDispatch::ShellExecute(BSTR file
, VARIANT v_args
, VARIANT v_dir
, VARIANT v_op
, VARIANT v_show
)
246 CComVariant args_str
, dir_str
, op_str
, show_int
;
247 WCHAR
*args
= NULL
, *dir
= NULL
, *op
= NULL
;
251 TRACE("(%s, %s, %s, %s, %s)\n", debugstr_w(file
), debugstr_variant(&v_args
),
252 debugstr_variant(&v_dir
), debugstr_variant(&v_op
), debugstr_variant(&v_show
));
254 args_str
.ChangeType(VT_BSTR
, &v_args
);
255 if (V_VT(&args_str
) == VT_BSTR
)
256 args
= V_BSTR(&args_str
);
258 dir_str
.ChangeType(VT_BSTR
, &v_dir
);
259 if (V_VT(&dir_str
) == VT_BSTR
)
260 dir
= V_BSTR(&dir_str
);
262 op_str
.ChangeType(VT_BSTR
, &v_op
);
263 if (V_VT(&op_str
) == VT_BSTR
)
264 op
= V_BSTR(&op_str
);
266 show_int
.ChangeType(VT_I4
, &v_show
);
267 if (V_VT(&show_int
) == VT_I4
)
268 show
= V_I4(&show_int
);
270 ret
= ShellExecuteW(NULL
, op
, file
, args
, dir
, show
);
272 return (ULONG_PTR
)ret
> 32 ? S_OK
: S_FALSE
;
275 HRESULT STDMETHODCALLTYPE
CShellDispatch::FindPrinter(BSTR name
, BSTR location
, BSTR model
)
277 TRACE("(%p, %ls, %ls, %ls)\n", this, name
, location
, model
);
281 HRESULT STDMETHODCALLTYPE
CShellDispatch::GetSystemInformation(BSTR name
, VARIANT
*ret
)
283 TRACE("(%p, %ls, %p)\n", this, name
, ret
);
287 HRESULT STDMETHODCALLTYPE
CShellDispatch::ServiceStart(BSTR service
, VARIANT persistent
, VARIANT
*ret
)
289 TRACE("(%p, %ls, %s, %p)\n", this, service
, wine_dbgstr_variant(&persistent
), ret
);
293 HRESULT STDMETHODCALLTYPE
CShellDispatch::ServiceStop(BSTR service
, VARIANT persistent
, VARIANT
*ret
)
295 TRACE("(%p, %ls, %s, %p)\n", this, service
, wine_dbgstr_variant(&persistent
), ret
);
299 HRESULT STDMETHODCALLTYPE
CShellDispatch::IsServiceRunning(BSTR name
, VARIANT
*running
)
301 SERVICE_STATUS_PROCESS status
;
302 SC_HANDLE scm
, service
;
305 TRACE("(%s, %p)\n", debugstr_w(name
), running
);
307 V_VT(running
) = VT_BOOL
;
308 V_BOOL(running
) = VARIANT_FALSE
;
310 scm
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
);
313 ERR("failed to connect to service manager\n");
317 service
= OpenServiceW(scm
, name
, SERVICE_QUERY_STATUS
);
320 ERR("Failed to open service %s (%u)\n", debugstr_w(name
), GetLastError());
321 CloseServiceHandle(scm
);
325 if (!QueryServiceStatusEx(service
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&status
,
326 sizeof(SERVICE_STATUS_PROCESS
), &dummy
))
328 TRACE("failed to query service status (%u)\n", GetLastError());
329 CloseServiceHandle(service
);
330 CloseServiceHandle(scm
);
334 if (status
.dwCurrentState
== SERVICE_RUNNING
)
335 V_BOOL(running
) = VARIANT_TRUE
;
337 CloseServiceHandle(service
);
338 CloseServiceHandle(scm
);
343 HRESULT STDMETHODCALLTYPE
CShellDispatch::CanStartStopService(BSTR service
, VARIANT
*ret
)
345 TRACE("(%p, %ls, %p)\n", this, service
, ret
);
349 HRESULT STDMETHODCALLTYPE
CShellDispatch::ShowBrowserBar(BSTR clsid
, VARIANT show
, VARIANT
*ret
)
351 TRACE("(%p, %ls, %s, %p)\n", this, clsid
, wine_dbgstr_variant(&show
), ret
);
356 // *** IShellDispatch3 methods ***
357 HRESULT STDMETHODCALLTYPE
CShellDispatch::AddToRecent(VARIANT file
, BSTR category
)
359 TRACE("(%p, %s, %ls)\n", this, wine_dbgstr_variant(&file
), category
);
364 // *** IShellDispatch4 methods ***
365 HRESULT STDMETHODCALLTYPE
CShellDispatch::WindowsSecurity()
367 TRACE("(%p)\n", this);
371 HRESULT STDMETHODCALLTYPE
CShellDispatch::ToggleDesktop()
373 TRACE("(%p)\n", this);
375 HWND hTrayWnd
= FindWindowW(L
"Shell_TrayWnd", NULL
);
376 PostMessageW(hTrayWnd
, WM_COMMAND
, TRAYCMD_TOGGLE_DESKTOP
, 0);
381 HRESULT STDMETHODCALLTYPE
CShellDispatch::ExplorerPolicy(BSTR policy
, VARIANT
*value
)
383 TRACE("(%p, %ls, %p)\n", this, policy
, value
);
387 HRESULT STDMETHODCALLTYPE
CShellDispatch::GetSetting(LONG setting
, VARIANT_BOOL
*result
)
389 TRACE("(%p, %lu, %p)\n", this, setting
, result
);
394 // *** IObjectSafety methods ***
395 HRESULT STDMETHODCALLTYPE
CShellDispatch::GetInterfaceSafetyOptions(REFIID riid
, DWORD
*pdwSupportedOptions
, DWORD
*pdwEnabledOptions
)
397 TRACE("(%p, %s, %p, %p)\n", this, wine_dbgstr_guid(&riid
), pdwSupportedOptions
, pdwEnabledOptions
);
401 HRESULT STDMETHODCALLTYPE
CShellDispatch::SetInterfaceSafetyOptions(REFIID riid
, DWORD dwOptionSetMask
, DWORD dwEnabledOptions
)
403 TRACE("(%p, %s, %lu, %lu)\n", this, wine_dbgstr_guid(&riid
), dwOptionSetMask
, dwEnabledOptions
);
408 // *** IObjectWithSite methods ***
409 HRESULT STDMETHODCALLTYPE
CShellDispatch::SetSite(IUnknown
*pUnkSite
)
411 TRACE("(%p, %p)\n", this, pUnkSite
);
415 HRESULT STDMETHODCALLTYPE
CShellDispatch::GetSite(REFIID riid
, PVOID
*ppvSite
)
417 TRACE("(%p, %s, %p)\n", this, wine_dbgstr_guid(&riid
), ppvSite
);
421 HRESULT WINAPI
CShellDispatch_Constructor(REFIID riid
, LPVOID
* ppvOut
)
423 return ShellObjectCreatorInit
<CShellDispatch
>(riid
, ppvOut
);