ReactOS 0.4.17-dev-923-g4c9a150
mmcshext.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS MSC Shell Extension
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Shell extension implementation
5 * COPYRIGHT: Copyright 2026 Whindmar Saksit <whindsaks@proton.me>
6 */
7
8#include <windows.h>
9#include <atlbase.h>
10#include <atlcom.h>
11#include <strsafe.h>
12#include <shlobj.h>
13#include <shobjidl.h>
14#include <shlwapi.h>
15#include <initguid.h>
16#include <msxml2.h>
17
18DEFINE_GUID(CLSID_MscExtractIcon, 0x7A80E4A8,0x8005,0x11D2,0xBC,0xF8,0x00,0xC0,0x4F,0x72,0xC7,0x17);
19
20CComModule g_Module;
21
23 public CComCoClass<CMscExtractIcon, &CLSID_MscExtractIcon>,
24 public CComObjectRootEx<CComMultiThreadModelNoCS>,
25 public IExtractIconW,
26 public IPersistFile
27{
28protected:
30
31public:
33 {
34 }
35
37 {
39 }
40
41 HRESULT GetIconLocationFromMsc(_In_ PWSTR pszIconFile, _In_ UINT cchMax, _Out_ int *piIndex);
42
44 {
45 *piIndex = 0;
46 WCHAR szDir[MAX_PATH + 1 + 8 + 3];
48 PathAddBackslashW(szDir);
49 return StringCchPrintfW(pszIconFile, cchMax, L"%smmc.exe", szDir) == S_OK ? S_OK : S_FALSE;
50 }
51
52 // IExtractIconW
53 IFACEMETHODIMP Extract(_In_ PCWSTR pszFile, _In_ UINT nIconIndex, _Out_ HICON *phiconLarge, _Out_ HICON *phiconSmall, _In_ UINT nIconSize) override
54 {
55 return S_FALSE; // All my paths are real files, call SHExtractIconsW/SHDefExtractIconW for me.
56 }
57
58 IFACEMETHODIMP GetIconLocation(_In_ UINT GilIn, _In_ PWSTR pszIconFile, _In_ UINT cchMax, _Out_ int *piIndex, _Out_ UINT *GilOut) override
59 {
60 *GilOut = GIL_PERINSTANCE; // Every .msc file has a unique icon
61
62 if (GilIn & GIL_ASYNC)
63 return E_PENDING;
64
65 if ((GilIn & GIL_DEFAULTICON) || FAILED(GetIconLocationFromMsc(pszIconFile, cchMax, piIndex)))
66 return GetDefaultIconLocation(pszIconFile, cchMax, piIndex);
67 return S_OK;
68 }
69
70 // IPersistFile
72 {
73 return E_NOTIMPL;
74 }
75
77 {
78 return E_NOTIMPL;
79 }
80
81 IFACEMETHODIMP Load(_In_ LPCOLESTR pszFileName, _In_ DWORD dwMode) override
82 {
84 m_File = NULL;
86 }
87
88 IFACEMETHODIMP Save(_In_ LPCOLESTR pszFileName, _In_ BOOL fRemember) override
89 {
90 return E_NOTIMPL;
91 }
92
94 {
95 return E_NOTIMPL;
96 }
97
98 IFACEMETHODIMP GetCurFile(_In_ LPOLESTR *ppszFileName) override
99 {
100 return E_NOTIMPL;
101 }
102
103 DECLARE_REGISTRY_RESOURCEID(IDR_EXTRACTICON)
105
107 COM_INTERFACE_ENTRY_IID(IID_IExtractIconW, IExtractIconW)
110};
111
112BEGIN_OBJECT_MAP(ObjectMap)
113 OBJECT_ENTRY(CLSID_MscExtractIcon, CMscExtractIcon)
115
117{
118 VARIANT v;
119 V_VT(&v) = VT_BSTR;
120 V_BSTR(&v) = const_cast<PWSTR>(L"XPath"); // Use XPath, not the old XSLPattern
121 return pDoc->setProperty(const_cast<PWSTR>(L"SelectionLanguage"), v);
122}
123
125{
126 CComPtr<IXMLDOMNamedNodeMap> pMap;
127 HRESULT hr;
128 *pOut = NULL;
129 if (SUCCEEDED(hr = pNode->get_attributes(&pMap)))
130 {
131 if (SUCCEEDED(hr = pMap->getNamedItem(const_cast<PWSTR>(pszName), &pNode)))
132 {
134 if (pNode)
135 {
136 hr = pNode->get_text(pOut);
137 if (SUCCEEDED(hr) && !*pOut)
139 pNode->Release();
140 }
141 }
142 }
143 return hr;
144}
145
147{
148 VARIANT_BOOL succ = VARIANT_FALSE;
149 HRESULT hr = CoCreateInstance(CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
150 IID_IXMLDOMDocument, (void**)ppDoc);
151 if (FAILED(hr))
152 return hr;
153 else if (SUCCEEDED(hr = (*ppDoc)->load(*pVar, &succ)) && succ)
154 return hr;
155 (*ppDoc)->Release();
156 return SUCCEEDED(hr) ? E_FAIL : hr;
157}
158
160{
161 if (!m_File)
162 return E_UNEXPECTED;
163
164 CComPtr<IStream> pStream;
166 if (FAILED(hr))
167 return hr;
168
169 VARIANT v;
170 V_VT(&v) = VT_UNKNOWN;
171 V_UNKNOWN(&v) = pStream;
172 CComPtr<IXMLDOMDocument2> pDoc;
173 if (FAILED(hr = LoadXmlFromVariant(&v, &pDoc)))
174 return hr;
176
177 CComPtr<IXMLDOMNode> pDomNode;
178 hr = pDoc->selectSingleNode(const_cast<PWSTR>(L"/MMC_ConsoleFile/VisualAttributes/Icon"), &pDomNode);
179 if (FAILED(hr))
180 return hr;
181 if (hr != S_OK) // Some files have an empty <VisualAttributes/> element
183
184 BSTR bstr;
185 *piIndex = 0;
186 if (SUCCEEDED(GetAttributeValue(pDomNode, L"Index", &bstr)))
187 {
188 *piIndex = StrToIntW(bstr);
189 SysFreeString(bstr);
190 }
191
192 if (SUCCEEDED(hr = GetAttributeValue(pDomNode, L"File", &bstr)))
193 {
194 hr = StringCchCopyW(pszIconFile, cchMax, bstr);
195 SysFreeString(bstr);
196 }
197 return hr;
198}
199
201{
202 return g_Module.DllCanUnloadNow();
203}
204
206{
207 return g_Module.DllGetClassObject(rclsid, riid, ppv);
208}
209
211{
212 return g_Module.DllRegisterServer(FALSE);
213}
214
216{
217 return g_Module.DllUnregisterServer(FALSE);
218}
219
221{
222 switch (dwReason)
223 {
226 g_Module.Init(ObjectMap, hInstance, NULL);
227 break;
228 }
229 return TRUE;
230}
UINT cchMax
DWORD dwReason
Definition: misc.cpp:135
#define STDAPI
Definition: basetyps.h:41
#define EXTERN_C
Definition: basetyps.h:12
HINSTANCE hInstance
Definition: charmap.c:19
IFACEMETHODIMP Load(_In_ LPCOLESTR pszFileName, _In_ DWORD dwMode) override
Definition: mmcshext.cpp:81
IFACEMETHODIMP Save(_In_ LPCOLESTR pszFileName, _In_ BOOL fRemember) override
Definition: mmcshext.cpp:88
IFACEMETHODIMP GetCurFile(_In_ LPOLESTR *ppszFileName) override
Definition: mmcshext.cpp:98
IFACEMETHODIMP IsDirty() override
Definition: mmcshext.cpp:76
HRESULT GetIconLocationFromMsc(_In_ PWSTR pszIconFile, _In_ UINT cchMax, _Out_ int *piIndex)
Definition: mmcshext.cpp:159
IFACEMETHODIMP GetIconLocation(_In_ UINT GilIn, _In_ PWSTR pszIconFile, _In_ UINT cchMax, _Out_ int *piIndex, _Out_ UINT *GilOut) override
Definition: mmcshext.cpp:58
IFACEMETHODIMP Extract(_In_ PCWSTR pszFile, _In_ UINT nIconIndex, _Out_ HICON *phiconLarge, _Out_ HICON *phiconSmall, _In_ UINT nIconSize) override
Definition: mmcshext.cpp:53
IFACEMETHODIMP SaveCompleted(_In_ LPCOLESTR pszFileName) override
Definition: mmcshext.cpp:93
IFACEMETHODIMP GetClassID(_Out_ CLSID *pClassID) override
Definition: mmcshext.cpp:71
HRESULT GetDefaultIconLocation(_In_ PWSTR pszIconFile, _In_ UINT cchMax, _Out_ int *piIndex)
Definition: mmcshext.cpp:43
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
HRESULT hr
Definition: delayimp.cpp:582
#define E_PENDING
Definition: dinput.h:172
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, IUnknown *outer, DWORD cls_context, REFIID riid, void **obj)
Definition: combase.c:1685
INT WINAPI StrToIntW(LPCWSTR lpString)
Definition: string.c:407
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
OLECHAR * BSTR
Definition: compat.h:2293
#define MAX_PATH
Definition: compat.h:34
short VARIANT_BOOL
Definition: compat.h:2290
@ VT_BSTR
Definition: compat.h:2303
@ VT_UNKNOWN
Definition: compat.h:2308
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
HRESULT WINAPI SHStrDupW(const WCHAR *src, WCHAR **dest)
Definition: main.c:1692
HRESULT WINAPI SHCreateStreamOnFileW(const WCHAR *path, DWORD mode, IStream **stream)
Definition: main.c:1180
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:370
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
const GLdouble * v
Definition: gl.h:2040
unsigned int UINT
Definition: sysinfo.c:13
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
ULONG Release()
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define BEGIN_COM_MAP(x)
Definition: atlcom.h:581
#define END_OBJECT_MAP()
Definition: atlcom.h:691
#define COM_INTERFACE_ENTRY_IID(iid, x)
Definition: atlcom.h:601
#define OBJECT_ENTRY(clsid, class)
Definition: atlcom.h:693
#define DECLARE_NOT_AGGREGATABLE(x)
Definition: atlcom.h:651
#define DECLARE_REGISTRY_RESOURCEID(x)
Definition: atlcom.h:645
#define BEGIN_OBJECT_MAP(x)
Definition: atlcom.h:689
#define END_COM_MAP()
Definition: atlcom.h:592
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID *ppv)
Definition: mmcshext.cpp:205
static HRESULT LoadXmlFromVariant(_In_ VARIANT *pVar, _Out_ IXMLDOMDocument2 **ppDoc)
Definition: mmcshext.cpp:146
STDAPI DllRegisterServer()
Definition: mmcshext.cpp:210
STDAPI DllCanUnloadNow()
Definition: mmcshext.cpp:200
STDAPI DllUnregisterServer()
Definition: mmcshext.cpp:215
static HRESULT SetXPathSelectionLanguage(_In_ IXMLDOMDocument2 *pDoc)
Definition: mmcshext.cpp:116
static HRESULT GetAttributeValue(_In_ IXMLDOMNode *pNode, _In_ LPCWSTR pszName, _Out_ BSTR *pOut)
Definition: mmcshext.cpp:124
CComModule g_Module
Definition: mmcshext.cpp:20
EXTERN_C BOOL WINAPI DllMain(_In_ HINSTANCE hInstance, _In_ DWORD dwReason, _In_ LPVOID lpReserved)
Definition: mmcshext.cpp:220
static HICON
Definition: imagelist.c:80
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define IFACEMETHODIMP
Definition: ntbasedef.h:157
#define STGM_SHARE_DENY_WRITE
Definition: objbase.h:941
#define STGM_READ
Definition: objbase.h:936
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:273
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
const GUID IID_IPersistFile
#define PathAddBackslashW
Definition: pathcch.h:302
short WCHAR
Definition: pedump.c:58
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: guiddef.h:68
#define REFIID
Definition: guiddef.h:118
#define REFCLSID
Definition: guiddef.h:117
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
const uint16_t * LPCWSTR
Definition: typedefs.h:57
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:44
#define GetSystemDirectory
Definition: winbase.h:3565
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
static HRESULT HRESULT_FROM_WIN32(unsigned int x)
Definition: winerror.h:210
#define E_UNEXPECTED
Definition: winerror.h:3528
#define ERROR_NOT_FOUND
Definition: winerror.h:1014
_In_ DWORD _In_ int _In_ int _In_opt_ LPNLSVERSIONINFO _In_opt_ LPVOID lpReserved
Definition: winnls.h:1279