Index: dll/win32/shell32/CShellDispatch.cpp =================================================================== --- dll/win32/shell32/CShellDispatch.cpp (revision 74189) +++ dll/win32/shell32/CShellDispatch.cpp (working copy) @@ -19,6 +19,7 @@ */ #include "precomp.h" +#include "winsvc.h" WINE_DEFAULT_DEBUG_CHANNEL(shell); @@ -208,10 +209,44 @@ return E_NOTIMPL; } -HRESULT STDMETHODCALLTYPE CShellDispatch::ShellExecute(BSTR file, VARIANT args, VARIANT dir, VARIANT op, VARIANT show) +HRESULT STDMETHODCALLTYPE CShellDispatch::ShellExecute(BSTR file, VARIANT v_args, VARIANT v_dir, VARIANT v_op, VARIANT v_show) { - TRACE("(%p, %ls, %s, %s, %s, %s)\n", this, file, debugstr_variant(&args), debugstr_variant(&dir), debugstr_variant(&op), debugstr_variant(&show)); - return E_NOTIMPL; + VARIANT args_str, dir_str, op_str, show_int; + WCHAR *args = NULL, *dir = NULL, *op = NULL; + INT show = 0; + HINSTANCE ret; + + TRACE("(%p, %ls, %s, %s, %s, %s)\n", this, file, debugstr_variant(&v_args), debugstr_variant(&v_dir), + debugstr_variant(&v_op), debugstr_variant(&v_show)); + + VariantInit(&args_str); + VariantChangeType(&args_str, &v_args, 0, VT_BSTR); + if (V_VT(&args_str) == VT_BSTR) + args = V_BSTR(&args_str); + + VariantInit(&dir_str); + VariantChangeType(&dir_str, &v_dir, 0, VT_BSTR); + if (V_VT(&dir_str) == VT_BSTR) + dir = V_BSTR(&dir_str); + + VariantInit(&op_str); + VariantChangeType(&op_str, &v_op, 0, VT_BSTR); + if (V_VT(&op_str) == VT_BSTR) + op = V_BSTR(&op_str); + + VariantInit(&show_int); + VariantChangeType(&show_int, &v_show, 0, VT_I4); + if (V_VT(&show_int) == VT_I4) + show = V_I4(&show_int); + + ret = ShellExecuteW(NULL, op, file, args, dir, show); + + VariantClear(&args_str); + VariantClear(&dir_str); + VariantClear(&op_str); + VariantClear(&show_int); + + return (ULONG_PTR)ret > 32 ? S_OK : S_FALSE; } HRESULT STDMETHODCALLTYPE CShellDispatch::FindPrinter(BSTR name, BSTR location, BSTR model) @@ -238,10 +273,48 @@ return E_NOTIMPL; } -HRESULT STDMETHODCALLTYPE CShellDispatch::IsServiceRunning(BSTR service, VARIANT *running) +HRESULT STDMETHODCALLTYPE CShellDispatch::IsServiceRunning(BSTR name, VARIANT *running) { - TRACE("(%p, %ls, %p)\n", this, service, running); - return E_NOTIMPL; + SERVICE_STATUS_PROCESS status; + SC_HANDLE scm, service; + DWORD dummy; + + TRACE("(%s, %p)\n", debugstr_w(name), running); + + V_VT(running) = VT_BOOL; + V_BOOL(running) = VARIANT_FALSE; + + scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); + if (!scm) + { + ERR("failed to connect to service manager\n"); + return S_OK; + } + + service = OpenServiceW(scm, name, SERVICE_QUERY_STATUS); + if (!service) + { + ERR("Failed to open service %s (%u)\n", debugstr_w(name), GetLastError()); + CloseServiceHandle(scm); + return S_OK; + } + + if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status, + sizeof(SERVICE_STATUS_PROCESS), &dummy)) + { + TRACE("failed to query service status (%u)\n", GetLastError()); + CloseServiceHandle(service); + CloseServiceHandle(scm); + return S_OK; + } + + if (status.dwCurrentState == SERVICE_RUNNING) + V_BOOL(running) = VARIANT_TRUE; + + CloseServiceHandle(service); + CloseServiceHandle(scm); + + return S_OK; } HRESULT STDMETHODCALLTYPE CShellDispatch::CanStartStopService(BSTR service, VARIANT *ret)