diff --git a/dll/win32/shell32/CFolder.cpp b/dll/win32/shell32/CFolder.cpp index 26eea6cfba5..3421ecbcc12 100644 --- a/dll/win32/shell32/CFolder.cpp +++ b/dll/win32/shell32/CFolder.cpp @@ -1,21 +1,8 @@ /* - * Folder implementation - * - * Copyright 2015 Mark Jansen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * PROJECT: shell32 + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: Folder implementation + * COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org) */ #include "precomp.h" @@ -31,9 +18,10 @@ CFolder::~CFolder() { } -void CFolder::Init(LPITEMIDLIST idlist) +HRESULT CFolder::Initialize(LPITEMIDLIST idlist) { - m_idlist.Attach(idlist); + m_idlist.Attach(ILClone(idlist)); + return CShellDispatch_Constructor(IID_PPV_ARG(IShellDispatch, &m_Application)); } HRESULT CFolder::GetShellFolder(CComPtr& psfCurrent) @@ -65,35 +53,39 @@ HRESULT STDMETHODCALLTYPE CFolder::get_Title(BSTR *pbs) HRESULT STDMETHODCALLTYPE CFolder::get_Application(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); - return E_NOTIMPL; + + if (!ppid) + return E_INVALIDARG; + + *ppid = m_Application; + (*ppid)->AddRef(); + + return S_OK; } HRESULT STDMETHODCALLTYPE CFolder::get_Parent(IDispatch **ppid) { TRACE("(%p %p)\n", this, ppid); + + if (ppid) + *ppid = NULL; + return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CFolder::get_ParentFolder(Folder **ppsf) { TRACE("(%p, %p)\n", this); + + *ppsf = NULL; + return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CFolder::Items(FolderItems **ppid) { - CFolderItems* items = new CComObject(); - items->AddRef(); - - HRESULT hr = items->Init(ILClone(m_idlist)); - if (FAILED_UNEXPECTEDLY(hr)) - { - items->Release(); - return hr; - } - - *ppid = items; - return S_OK; + /* FolderItems_Constructor */ + return ShellObjectCreatorInit(static_cast(m_idlist), this, IID_PPV_ARG(FolderItems, ppid)); } HRESULT STDMETHODCALLTYPE CFolder::ParseName(BSTR bName, FolderItem **ppid) @@ -113,11 +105,10 @@ HRESULT STDMETHODCALLTYPE CFolder::ParseName(BSTR bName, FolderItem **ppid) if (!SUCCEEDED(hr)) return S_FALSE; - CFolderItem* item = new CComObject(); - item->AddRef(); - item->Init(ILCombine(m_idlist, relativePidl)); - *ppid = item; - return S_OK; + CComHeapPtr combined; + combined.Attach(ILCombine(m_idlist, relativePidl)); + + return ShellObjectCreatorInit(this, static_cast(combined), IID_PPV_ARG(FolderItem, ppid)); } HRESULT STDMETHODCALLTYPE CFolder::NewFolder(BSTR bName, VARIANT vOptions) @@ -151,11 +142,8 @@ HRESULT STDMETHODCALLTYPE CFolder::get_Self(FolderItem **ppfi) TRACE("(%p, %p)\n", this, ppfi); if (!ppfi) return E_POINTER; - CFolderItem* item = new CComObject(); - item->AddRef(); - item->Init(ILClone(m_idlist)); - *ppfi = item; - return S_OK; + + return ShellObjectCreatorInit(this, static_cast(m_idlist), IID_PPV_ARG(FolderItem, ppfi)); } HRESULT STDMETHODCALLTYPE CFolder::get_OfflineStatus(LONG *pul) diff --git a/dll/win32/shell32/CFolder.h b/dll/win32/shell32/CFolder.h index bfd5c9d08d5..df0d482b432 100644 --- a/dll/win32/shell32/CFolder.h +++ b/dll/win32/shell32/CFolder.h @@ -1,21 +1,8 @@ /* - * Folder implementation - * - * Copyright 2015 Mark Jansen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * PROJECT: shell32 + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: Folder implementation + * COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org) */ #ifndef _FOLDER_H_ @@ -31,12 +18,13 @@ private: HRESULT GetShellFolder(CComPtr& psfCurrent); CComHeapPtr m_idlist; + CComPtr m_Application; public: CFolder(); ~CFolder(); - void Init(LPITEMIDLIST idlist); + HRESULT Initialize(LPITEMIDLIST idlist); // *** Folder methods *** virtual HRESULT STDMETHODCALLTYPE get_Title(BSTR *pbs); diff --git a/dll/win32/shell32/CFolderItemVerbs.cpp b/dll/win32/shell32/CFolderItemVerbs.cpp index 87866fa786d..0397f724f8e 100644 --- a/dll/win32/shell32/CFolderItemVerbs.cpp +++ b/dll/win32/shell32/CFolderItemVerbs.cpp @@ -107,7 +107,7 @@ HRESULT CFolderItemVerbs::Init(LPITEMIDLIST idlist) HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Count(LONG *plCount) { if (!plCount) - return E_POINTER; + return E_INVALIDARG; *plCount = m_count; return S_OK; } @@ -115,12 +115,20 @@ HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Count(LONG *plCount) HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Application(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); + + if (ppid) + *ppid = NULL; + return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Parent(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); + + if (ppid) + *ppid = NULL; + return E_NOTIMPL; } @@ -130,9 +138,8 @@ HRESULT STDMETHODCALLTYPE CFolderItemVerbs::Item(VARIANT indexVar, FolderItemVer return E_POINTER; CComVariant var; - VariantCopyInd(&var, &indexVar); - HRESULT hr = VariantChangeType(&var, &var, 0, VT_I4); + HRESULT hr = VariantChangeType(&var, &indexVar, 0, VT_I4); if (FAILED_UNEXPECTEDLY(hr)) return E_INVALIDARG; @@ -144,7 +151,9 @@ HRESULT STDMETHODCALLTYPE CFolderItemVerbs::Item(VARIANT indexVar, FolderItemVer BSTR name = NULL; if(index == m_count) + { name = SysAllocStringLen(NULL, 0); + } else { MENUITEMINFOW info = { sizeof(info), 0 }; diff --git a/dll/win32/shell32/CFolderItems.cpp b/dll/win32/shell32/CFolderItems.cpp index 614ead2e8bd..9d2e27090bb 100644 --- a/dll/win32/shell32/CFolderItems.cpp +++ b/dll/win32/shell32/CFolderItems.cpp @@ -1,21 +1,8 @@ /* - * FolderItem(s) implementation - * - * Copyright 2015,2016 Mark Jansen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * PROJECT: shell32 + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: FolderItem(s) implementation + * COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org) */ #include "precomp.h" @@ -31,28 +18,49 @@ CFolderItem::~CFolderItem() { } -void CFolderItem::Init(LPITEMIDLIST idlist) +HRESULT CFolderItem::Initialize(Folder* folder, LPITEMIDLIST idlist) { - m_idlist.Attach(idlist); + m_idlist.Attach(ILClone(idlist)); + m_Folder = folder; + return S_OK; } // *** FolderItem methods *** HRESULT STDMETHODCALLTYPE CFolderItem::get_Application(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); - return E_NOTIMPL; + return m_Folder->get_Application(ppid); } HRESULT STDMETHODCALLTYPE CFolderItem::get_Parent(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); + if (ppid) + { + *ppid = m_Folder; + m_Folder->AddRef(); + } return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CFolderItem::get_Name(BSTR *pbs) { TRACE("(%p, %p)\n", this, pbs); - return E_NOTIMPL; + + *pbs = NULL; + + CComPtr Parent; + LPCITEMIDLIST last_part; + HRESULT hr = SHBindToParent(m_idlist, IID_PPV_ARG(IShellFolder2, &Parent), &last_part); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + STRRET strret; + hr = Parent->GetDisplayNameOf(last_part, SHGDN_INFOLDER, &strret); + if (!FAILED_UNEXPECTEDLY(hr)) + hr = StrRetToBSTR(&strret, last_part, pbs); + + return hr; } HRESULT STDMETHODCALLTYPE CFolderItem::put_Name(BSTR bs) @@ -170,11 +178,11 @@ CFolderItems::~CFolderItems() { } -HRESULT CFolderItems::Init(LPITEMIDLIST idlist) +HRESULT CFolderItems::Initialize(LPITEMIDLIST idlist, Folder* parent) { CComPtr psfDesktop, psfTarget; - m_idlist.Attach(idlist); + m_idlist.Attach(ILClone(idlist)); HRESULT hr = SHGetDesktopFolder(&psfDesktop); if (FAILED_UNEXPECTEDLY(hr)) @@ -189,6 +197,7 @@ HRESULT CFolderItems::Init(LPITEMIDLIST idlist) if (FAILED_UNEXPECTEDLY(hr)) return hr; + m_Folder = parent; return S_OK; } @@ -210,8 +219,7 @@ HRESULT STDMETHODCALLTYPE CFolderItems::get_Count(long *plCount) return hr; CComHeapPtr Pidl; - hr = m_EnumIDList->Next(1, &Pidl, 0); - while (hr != S_FALSE) + while ((hr = m_EnumIDList->Next(1, &Pidl, 0)) != S_FALSE) { count++; Pidl.Free(); @@ -226,12 +234,16 @@ HRESULT STDMETHODCALLTYPE CFolderItems::get_Count(long *plCount) HRESULT STDMETHODCALLTYPE CFolderItems::get_Application(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); - return E_NOTIMPL; + return m_Folder->get_Application(ppid); } HRESULT STDMETHODCALLTYPE CFolderItems::get_Parent(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); + + if (ppid) + *ppid = NULL; + return E_NOTIMPL; } @@ -240,40 +252,48 @@ HRESULT STDMETHODCALLTYPE CFolderItems::Item(VARIANT index, FolderItem **ppid) if (!m_EnumIDList) return E_FAIL; - if (V_VT(&index) != VT_I4 && V_VT(&index) != VT_UI4) - return E_INVALIDARG; + if (V_VT(&index) == VT_I2) + VariantChangeType(&index, &index, 0, VT_I4); - ULONG count = V_UI4(&index); - - HRESULT hr = m_EnumIDList->Reset(); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - hr = m_EnumIDList->Skip(count); - - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - CComHeapPtr spPidl; - hr = m_EnumIDList->Next(1, &spPidl, 0); - if (hr == S_OK) + if (V_VT(&index) == VT_I4) { - CFolderItem* item = new CComObject(); - item->AddRef(); - item->Init(spPidl.Detach()); - *ppid = item; - return S_OK; + ULONG count = V_UI4(&index); + + HRESULT hr = m_EnumIDList->Reset(); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = m_EnumIDList->Skip(count); + + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + CComHeapPtr spPidl; + hr = m_EnumIDList->Next(1, &spPidl, 0); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + hr = ShellObjectCreatorInit(m_Folder, static_cast(spPidl), IID_PPV_ARG(FolderItem, ppid)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + return hr; + } + else if (V_VT(&index) == VT_BSTR) + { + if (!V_BSTR(&index)) + return S_FALSE; + + HRESULT hr = m_Folder->ParseName(V_BSTR(&index), ppid); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + return hr; } - return hr; + FIXME("Index type %d not handled.\n", V_VT(&index)); + return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CFolderItems::_NewEnum(IUnknown **ppunk) { - CFolderItems* items = new CComObject(); - items->AddRef(); - items->Init(ILClone(m_idlist)); - *ppunk = items; - return S_OK; + return ShellObjectCreatorInit(static_cast(m_idlist), m_Folder, IID_FolderItems, reinterpret_cast(ppunk)); } diff --git a/dll/win32/shell32/CFolderItems.h b/dll/win32/shell32/CFolderItems.h index ddb62c87e8d..ce339646dbc 100644 --- a/dll/win32/shell32/CFolderItems.h +++ b/dll/win32/shell32/CFolderItems.h @@ -1,21 +1,8 @@ /* - * FolderItem(s) implementation - * - * Copyright 2015 Mark Jansen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * PROJECT: shell32 + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: FolderItem(s) implementation + * COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org) */ #ifndef _FOLDERITEM_H_ @@ -29,13 +16,13 @@ class CFolderItem: { private: CComHeapPtr m_idlist; + CComPtr m_Folder; public: CFolderItem(); ~CFolderItem(); - // Please note: CFolderItem takes ownership of idlist. - void Init(LPITEMIDLIST idlist); + HRESULT Initialize(Folder* folder, LPITEMIDLIST idlist); // *** FolderItem methods *** @@ -75,6 +62,7 @@ class CFolderItems: private: CComHeapPtr m_idlist; CComPtr m_EnumIDList; + CComPtr m_Folder; long m_Count; public: @@ -82,7 +70,7 @@ public: ~CFolderItems(); // Please note: CFolderItems takes ownership of idlist. - HRESULT Init(LPITEMIDLIST idlist); + HRESULT Initialize(LPITEMIDLIST idlist, Folder* parent); // *** FolderItems methods *** virtual HRESULT STDMETHODCALLTYPE get_Count(long *plCount); diff --git a/dll/win32/shell32/CShellDispatch.cpp b/dll/win32/shell32/CShellDispatch.cpp index 7c98b4ae528..259b8919976 100644 --- a/dll/win32/shell32/CShellDispatch.cpp +++ b/dll/win32/shell32/CShellDispatch.cpp @@ -1,24 +1,12 @@ /* - * IShellDispatch implementation - * - * Copyright 2015 Mark Jansen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * PROJECT: shell32 + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: IShellDispatch implementation + * COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org) */ #include "precomp.h" +#include "winsvc.h" WINE_DEFAULT_DEBUG_CHANNEL(shell); @@ -40,13 +28,27 @@ HRESULT CShellDispatch::Initialize() HRESULT STDMETHODCALLTYPE CShellDispatch::get_Application(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); - return E_NOTIMPL; + + if (!ppid) + return E_INVALIDARG; + + *ppid = this; + AddRef(); + + return S_OK; } HRESULT STDMETHODCALLTYPE CShellDispatch::get_Parent(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); - return E_NOTIMPL; + + if (ppid) + { + *ppid = static_cast(this); + AddRef(); + } + + return S_OK; } HRESULT VariantToIdlist(VARIANT* var, LPITEMIDLIST* idlist) @@ -69,26 +71,56 @@ HRESULT STDMETHODCALLTYPE CShellDispatch::NameSpace(VARIANT vDir, Folder **ppsdf if (!ppsdf) return E_POINTER; *ppsdf = NULL; - LPITEMIDLIST idlist = NULL; - HRESULT hr = VariantToIdlist(&vDir, &idlist); + HRESULT hr; + + if (V_VT(&vDir) == VT_I2) + { + hr = VariantChangeType(&vDir, &vDir, 0, VT_I4); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + } + + CComHeapPtr idlist; + hr = VariantToIdlist(&vDir, &idlist); if (!SUCCEEDED(hr) || !idlist) return S_FALSE; - CFolder* fld = new CComObject(); - fld->Init(idlist); - *ppsdf = fld; - fld->AddRef(); - return hr; + + return ShellObjectCreatorInit(static_cast(idlist), IID_PPV_ARG(Folder, ppsdf)); +} + +static BOOL is_optional_argument(const VARIANT *arg) +{ + return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND; } HRESULT STDMETHODCALLTYPE CShellDispatch::BrowseForFolder(LONG Hwnd, BSTR Title, LONG Options, VARIANT RootFolder, Folder **ppsdf) { TRACE("(%p, %lu, %ls, %lu, %s, %p)\n", this, Hwnd, Title, Options, debugstr_variant(&RootFolder), ppsdf); - return E_NOTIMPL; + + *ppsdf = NULL; + + if (!is_optional_argument(&RootFolder)) + FIXME("root folder is ignored\n"); + + BROWSEINFOW bi = { 0 }; + bi.hwndOwner = reinterpret_cast(LongToHandle(Hwnd)); + bi.lpszTitle = Title; + bi.ulFlags = Options; + + CComHeapPtr selection; + selection.Attach(SHBrowseForFolderW(&bi)); + if (!selection) + return S_FALSE; + + return ShellObjectCreatorInit(static_cast(selection), IID_PPV_ARG(Folder, ppsdf)); } HRESULT STDMETHODCALLTYPE CShellDispatch::Windows(IDispatch **ppid) { TRACE("(%p, %p)\n", this, ppid); + + *ppid = NULL; + return E_NOTIMPL; } @@ -208,10 +240,35 @@ HRESULT STDMETHODCALLTYPE CShellDispatch::IsRestricted(BSTR group, BSTR restrict 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; + CComVariant args_str, dir_str, op_str, show_int; + WCHAR *args = NULL, *dir = NULL, *op = NULL; + INT show = 0; + HINSTANCE ret; + + TRACE("(%s, %s, %s, %s, %s)\n", debugstr_w(file), debugstr_variant(&v_args), + debugstr_variant(&v_dir), debugstr_variant(&v_op), debugstr_variant(&v_show)); + + args_str.ChangeType(VT_BSTR, &v_args); + if (V_VT(&args_str) == VT_BSTR) + args = V_BSTR(&args_str); + + dir_str.ChangeType(VT_BSTR, &v_dir); + if (V_VT(&dir_str) == VT_BSTR) + dir = V_BSTR(&dir_str); + + op_str.ChangeType(VT_BSTR, &v_op); + if (V_VT(&op_str) == VT_BSTR) + op = V_BSTR(&op_str); + + show_int.ChangeType(VT_I4, &v_show); + if (V_VT(&show_int) == VT_I4) + show = V_I4(&show_int); + + ret = ShellExecuteW(NULL, op, file, args, dir, show); + + return (ULONG_PTR)ret > 32 ? S_OK : S_FALSE; } HRESULT STDMETHODCALLTYPE CShellDispatch::FindPrinter(BSTR name, BSTR location, BSTR model) @@ -238,10 +295,48 @@ HRESULT STDMETHODCALLTYPE CShellDispatch::ServiceStop(BSTR service, VARIANT pers 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) diff --git a/dll/win32/shell32/CShellDispatch.h b/dll/win32/shell32/CShellDispatch.h index 539f3cfd296..6c32ecf6672 100644 --- a/dll/win32/shell32/CShellDispatch.h +++ b/dll/win32/shell32/CShellDispatch.h @@ -1,21 +1,8 @@ /* - * IShellDispatch implementation - * - * Copyright 2015 Mark Jansen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * PROJECT: shell32 + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: IShellDispatch implementation + * COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org) */ #ifndef _SHELLDISPATCH_H_