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)
11 #include <traycmd.h> // tray commands
13 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
16 CShellDispatch::CShellDispatch()
20 CShellDispatch::~CShellDispatch()
24 HRESULT
CShellDispatch::Initialize()
29 // *** IShellDispatch methods ***
30 HRESULT STDMETHODCALLTYPE
CShellDispatch::get_Application(IDispatch
**ppid
)
32 TRACE("(%p, %p)\n", this, ppid
);
43 HRESULT STDMETHODCALLTYPE
CShellDispatch::get_Parent(IDispatch
**ppid
)
45 TRACE("(%p, %p)\n", this, ppid
);
49 *ppid
= static_cast<IDispatch
*>(this);
56 HRESULT
VariantToIdlist(VARIANT
* var
, LPITEMIDLIST
* idlist
)
59 if(V_VT(var
) == VT_I4
)
61 hr
= SHGetSpecialFolderLocation(NULL
, V_I4(var
), idlist
);
63 else if(V_VT(var
) == VT_BSTR
)
65 hr
= SHILCreateFromPathW(V_BSTR(var
), idlist
, NULL
);
70 HRESULT STDMETHODCALLTYPE
CShellDispatch::NameSpace(VARIANT vDir
, Folder
**ppsdf
)
72 TRACE("(%p, %s, %p)\n", this, debugstr_variant(&vDir
), ppsdf
);
78 if (V_VT(&vDir
) == VT_I2
)
80 hr
= VariantChangeType(&vDir
, &vDir
, 0, VT_I4
);
81 if (FAILED_UNEXPECTEDLY(hr
))
85 CComHeapPtr
<ITEMIDLIST
> idlist
;
86 hr
= VariantToIdlist(&vDir
, &idlist
);
87 if (!SUCCEEDED(hr
) || !idlist
)
90 return ShellObjectCreatorInit
<CFolder
>(static_cast<LPITEMIDLIST
>(idlist
), IID_PPV_ARG(Folder
, ppsdf
));
93 static BOOL
is_optional_argument(const VARIANT
*arg
)
95 return V_VT(arg
) == VT_ERROR
&& V_ERROR(arg
) == DISP_E_PARAMNOTFOUND
;
98 HRESULT STDMETHODCALLTYPE
CShellDispatch::BrowseForFolder(LONG Hwnd
, BSTR Title
, LONG Options
, VARIANT RootFolder
, Folder
**ppsdf
)
100 TRACE("(%p, %lu, %ls, %lu, %s, %p)\n", this, Hwnd
, Title
, Options
, debugstr_variant(&RootFolder
), ppsdf
);
104 if (!is_optional_argument(&RootFolder
))
105 FIXME("root folder is ignored\n");
107 BROWSEINFOW bi
= { 0 };
108 bi
.hwndOwner
= reinterpret_cast<HWND
>(LongToHandle(Hwnd
));
109 bi
.lpszTitle
= Title
;
110 bi
.ulFlags
= Options
;
112 CComHeapPtr
<ITEMIDLIST
> selection
;
113 selection
.Attach(SHBrowseForFolderW(&bi
));
117 return ShellObjectCreatorInit
<CFolder
>(static_cast<LPITEMIDLIST
>(selection
), IID_PPV_ARG(Folder
, ppsdf
));
120 HRESULT STDMETHODCALLTYPE
CShellDispatch::Windows(IDispatch
**ppid
)
122 TRACE("(%p, %p)\n", this, ppid
);
129 HRESULT STDMETHODCALLTYPE
CShellDispatch::Open(VARIANT vDir
)
131 TRACE("(%p, %s)\n", this, debugstr_variant(&vDir
));
135 HRESULT STDMETHODCALLTYPE
CShellDispatch::Explore(VARIANT vDir
)
137 TRACE("(%p, %s)\n", this, debugstr_variant(&vDir
));
141 HRESULT STDMETHODCALLTYPE
CShellDispatch::MinimizeAll()
143 TRACE("(%p)\n", this);
147 HRESULT STDMETHODCALLTYPE
CShellDispatch::UndoMinimizeALL()
149 TRACE("(%p)\n", this);
153 HRESULT STDMETHODCALLTYPE
CShellDispatch::FileRun()
155 TRACE("(%p)\n", this);
159 HRESULT STDMETHODCALLTYPE
CShellDispatch::CascadeWindows()
161 TRACE("(%p)\n", this);
165 HRESULT STDMETHODCALLTYPE
CShellDispatch::TileVertically()
167 TRACE("(%p)\n", this);
171 HRESULT STDMETHODCALLTYPE
CShellDispatch::TileHorizontally()
173 TRACE("(%p)\n", this);
177 HRESULT STDMETHODCALLTYPE
CShellDispatch::ShutdownWindows()
179 ExitWindowsDialog(NULL
);
183 HRESULT STDMETHODCALLTYPE
CShellDispatch::Suspend()
185 TRACE("(%p)\n", this);
189 HRESULT STDMETHODCALLTYPE
CShellDispatch::EjectPC()
191 TRACE("(%p)\n", this);
195 HRESULT STDMETHODCALLTYPE
CShellDispatch::SetTime()
197 TRACE("(%p)\n", this);
201 HRESULT STDMETHODCALLTYPE
CShellDispatch::TrayProperties()
203 TRACE("(%p)\n", this);
207 HRESULT STDMETHODCALLTYPE
CShellDispatch::Help()
209 TRACE("(%p)\n", this);
213 HRESULT STDMETHODCALLTYPE
CShellDispatch::FindFiles()
215 TRACE("(%p)\n", this);
219 HRESULT STDMETHODCALLTYPE
CShellDispatch::FindComputer()
221 TRACE("(%p)\n", this);
225 HRESULT STDMETHODCALLTYPE
CShellDispatch::RefreshMenu()
227 TRACE("(%p)\n", this);
231 HRESULT STDMETHODCALLTYPE
CShellDispatch::ControlPanelItem(BSTR szDir
)
233 TRACE("(%p, %ls)\n", this, szDir
);
238 // *** IShellDispatch2 methods ***
239 HRESULT STDMETHODCALLTYPE
CShellDispatch::IsRestricted(BSTR group
, BSTR restriction
, LONG
*value
)
241 TRACE("(%p, %ls, %ls, %p)\n", this, group
, restriction
, value
);
245 HRESULT STDMETHODCALLTYPE
CShellDispatch::ShellExecute(BSTR file
, VARIANT v_args
, VARIANT v_dir
, VARIANT v_op
, VARIANT v_show
)
247 CComVariant args_str
, dir_str
, op_str
, show_int
;
248 WCHAR
*args
= NULL
, *dir
= NULL
, *op
= NULL
;
252 TRACE("(%s, %s, %s, %s, %s)\n", debugstr_w(file
), debugstr_variant(&v_args
),
253 debugstr_variant(&v_dir
), debugstr_variant(&v_op
), debugstr_variant(&v_show
));
255 args_str
.ChangeType(VT_BSTR
, &v_args
);
256 if (V_VT(&args_str
) == VT_BSTR
)
257 args
= V_BSTR(&args_str
);
259 dir_str
.ChangeType(VT_BSTR
, &v_dir
);
260 if (V_VT(&dir_str
) == VT_BSTR
)
261 dir
= V_BSTR(&dir_str
);
263 op_str
.ChangeType(VT_BSTR
, &v_op
);
264 if (V_VT(&op_str
) == VT_BSTR
)
265 op
= V_BSTR(&op_str
);
267 show_int
.ChangeType(VT_I4
, &v_show
);
268 if (V_VT(&show_int
) == VT_I4
)
269 show
= V_I4(&show_int
);
271 ret
= ShellExecuteW(NULL
, op
, file
, args
, dir
, show
);
273 return (ULONG_PTR
)ret
> 32 ? S_OK
: S_FALSE
;
276 HRESULT STDMETHODCALLTYPE
CShellDispatch::FindPrinter(BSTR name
, BSTR location
, BSTR model
)
278 TRACE("(%p, %ls, %ls, %ls)\n", this, name
, location
, model
);
282 HRESULT STDMETHODCALLTYPE
CShellDispatch::GetSystemInformation(BSTR name
, VARIANT
*ret
)
284 TRACE("(%p, %ls, %p)\n", this, name
, ret
);
288 HRESULT STDMETHODCALLTYPE
CShellDispatch::ServiceStart(BSTR service
, VARIANT persistent
, VARIANT
*ret
)
290 TRACE("(%p, %ls, %s, %p)\n", this, service
, wine_dbgstr_variant(&persistent
), ret
);
294 HRESULT STDMETHODCALLTYPE
CShellDispatch::ServiceStop(BSTR service
, VARIANT persistent
, VARIANT
*ret
)
296 TRACE("(%p, %ls, %s, %p)\n", this, service
, wine_dbgstr_variant(&persistent
), ret
);
300 HRESULT STDMETHODCALLTYPE
CShellDispatch::IsServiceRunning(BSTR name
, VARIANT
*running
)
302 SERVICE_STATUS_PROCESS status
;
303 SC_HANDLE scm
, service
;
306 TRACE("(%s, %p)\n", debugstr_w(name
), running
);
308 V_VT(running
) = VT_BOOL
;
309 V_BOOL(running
) = VARIANT_FALSE
;
311 scm
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
);
314 ERR("failed to connect to service manager\n");
318 service
= OpenServiceW(scm
, name
, SERVICE_QUERY_STATUS
);
321 ERR("Failed to open service %s (%u)\n", debugstr_w(name
), GetLastError());
322 CloseServiceHandle(scm
);
326 if (!QueryServiceStatusEx(service
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&status
,
327 sizeof(SERVICE_STATUS_PROCESS
), &dummy
))
329 TRACE("failed to query service status (%u)\n", GetLastError());
330 CloseServiceHandle(service
);
331 CloseServiceHandle(scm
);
335 if (status
.dwCurrentState
== SERVICE_RUNNING
)
336 V_BOOL(running
) = VARIANT_TRUE
;
338 CloseServiceHandle(service
);
339 CloseServiceHandle(scm
);
344 HRESULT STDMETHODCALLTYPE
CShellDispatch::CanStartStopService(BSTR service
, VARIANT
*ret
)
346 TRACE("(%p, %ls, %p)\n", this, service
, ret
);
350 HRESULT STDMETHODCALLTYPE
CShellDispatch::ShowBrowserBar(BSTR clsid
, VARIANT show
, VARIANT
*ret
)
352 TRACE("(%p, %ls, %s, %p)\n", this, clsid
, wine_dbgstr_variant(&show
), ret
);
357 // *** IShellDispatch3 methods ***
358 HRESULT STDMETHODCALLTYPE
CShellDispatch::AddToRecent(VARIANT file
, BSTR category
)
360 TRACE("(%p, %s, %ls)\n", this, wine_dbgstr_variant(&file
), category
);
365 // *** IShellDispatch4 methods ***
366 HRESULT STDMETHODCALLTYPE
CShellDispatch::WindowsSecurity()
368 TRACE("(%p)\n", this);
372 HRESULT STDMETHODCALLTYPE
CShellDispatch::ToggleDesktop()
374 TRACE("(%p)\n", this);
376 HWND hTrayWnd
= FindWindowW(L
"Shell_TrayWnd", NULL
);
377 PostMessageW(hTrayWnd
, WM_COMMAND
, TRAYCMD_TOGGLE_DESKTOP
, 0);
382 HRESULT STDMETHODCALLTYPE
CShellDispatch::ExplorerPolicy(BSTR policy
, VARIANT
*value
)
384 TRACE("(%p, %ls, %p)\n", this, policy
, value
);
388 HRESULT STDMETHODCALLTYPE
CShellDispatch::GetSetting(LONG setting
, VARIANT_BOOL
*result
)
390 TRACE("(%p, %lu, %p)\n", this, setting
, result
);
395 // *** IObjectSafety methods ***
396 HRESULT STDMETHODCALLTYPE
CShellDispatch::GetInterfaceSafetyOptions(REFIID riid
, DWORD
*pdwSupportedOptions
, DWORD
*pdwEnabledOptions
)
398 TRACE("(%p, %s, %p, %p)\n", this, wine_dbgstr_guid(&riid
), pdwSupportedOptions
, pdwEnabledOptions
);
402 HRESULT STDMETHODCALLTYPE
CShellDispatch::SetInterfaceSafetyOptions(REFIID riid
, DWORD dwOptionSetMask
, DWORD dwEnabledOptions
)
404 TRACE("(%p, %s, %lu, %lu)\n", this, wine_dbgstr_guid(&riid
), dwOptionSetMask
, dwEnabledOptions
);
409 // *** IObjectWithSite methods ***
410 HRESULT STDMETHODCALLTYPE
CShellDispatch::SetSite(IUnknown
*pUnkSite
)
412 TRACE("(%p, %p)\n", this, pUnkSite
);
416 HRESULT STDMETHODCALLTYPE
CShellDispatch::GetSite(REFIID riid
, PVOID
*ppvSite
)
418 TRACE("(%p, %s, %p)\n", this, wine_dbgstr_guid(&riid
), ppvSite
);
422 HRESULT WINAPI
CShellDispatch_Constructor(REFIID riid
, LPVOID
* ppvOut
)
424 return ShellObjectCreatorInit
<CShellDispatch
>(riid
, ppvOut
);