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