1 /*
2  * PROJECT:     ReactOS Zip Shell Extension
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     IExplorerCommand implementation
5  * COPYRIGHT:   Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 class CExplorerCommand :
11     public CComObjectRootEx<CComMultiThreadModelNoCS>,
12     public IExplorerCommand
13 {
14 private:
15     CComPtr<IContextMenu> m_pZipObject;
16 
17 public:
18 
19     STDMETHODIMP Initialize(IContextMenu* zipObject)
20     {
21         m_pZipObject = zipObject;
22         return S_OK;
23     }
24 
25     // *** IExplorerCommand methods ***
26     STDMETHODIMP GetTitle(IShellItemArray *psiItemArray, LPWSTR *ppszName)
27     {
28         CStringW Title(MAKEINTRESOURCEW(IDS_MENUITEM));
29         return SHStrDup(Title, ppszName);
30     }
31     STDMETHODIMP GetIcon(IShellItemArray *psiItemArray, LPWSTR *ppszIcon)
32     {
33         CStringW IconName = L"zipfldr.dll,-1";
34         return SHStrDup(IconName, ppszIcon);
35     }
36     STDMETHODIMP GetToolTip(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip)
37     {
38         CStringW HelpText(MAKEINTRESOURCEW(IDS_HELPTEXT));
39         return SHStrDup(HelpText, ppszInfotip);
40     }
41     STDMETHODIMP GetCanonicalName(GUID *pguidCommandName)
42     {
43         *pguidCommandName = CLSID_ZipFolderExtractAllCommand;
44         return S_OK;
45     }
46     STDMETHODIMP GetState(IShellItemArray *psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE *pCmdState)
47     {
48         *pCmdState = ECS_ENABLED;
49         return S_OK;
50     }
51     STDMETHODIMP Invoke(IShellItemArray *psiItemArray, IBindCtx *pbc)
52     {
53         CMINVOKECOMMANDINFO cm = { sizeof(cm), 0 };
54         cm.lpVerb = EXTRACT_VERBA;
55         cm.nShow = SW_SHOW;
56         return m_pZipObject->InvokeCommand(&cm);
57     }
58     STDMETHODIMP GetFlags(EXPCMDFLAGS *pFlags)
59     {
60         *pFlags = ECF_DEFAULT;
61         return S_OK;
62     }
63     STDMETHODIMP EnumSubCommands(IEnumExplorerCommand **ppEnum)
64     {
65         DbgPrint("%s\n", __FUNCTION__);
66         return E_NOTIMPL;
67     }
68 
69 public:
70     DECLARE_NOT_AGGREGATABLE(CExplorerCommand)
71     DECLARE_PROTECT_FINAL_CONSTRUCT()
72 
73     BEGIN_COM_MAP(CExplorerCommand)
74         COM_INTERFACE_ENTRY_IID(IID_IExplorerCommand, IExplorerCommand)
75     END_COM_MAP()
76 };
77 
78 
79 class CEnumExplorerCommand :
80     public CComObjectRootEx<CComMultiThreadModelNoCS>,
81     public IEnumExplorerCommand
82 {
83 private:
84     bool m_bFirst;
85     CComPtr<IContextMenu> m_pZipObject;
86 
87 public:
88 
89     CEnumExplorerCommand()
90         :m_bFirst(true)
91     {
92     }
93 
94     STDMETHODIMP Initialize(IContextMenu* zipObject)
95     {
96         m_pZipObject = zipObject;
97         return S_OK;
98     }
99 
100     // *** IEnumExplorerCommand methods ***
101     STDMETHODIMP Next(ULONG celt, IExplorerCommand **pUICommand, ULONG *pceltFetched)
102     {
103         if (!pUICommand)
104             return E_POINTER;
105 
106         if (pceltFetched)
107             *pceltFetched = 0;
108         if (m_bFirst && celt)
109         {
110             m_bFirst = false;
111             celt--;
112             HRESULT hr = ShellObjectCreatorInit<CExplorerCommand>(m_pZipObject, IID_PPV_ARG(IExplorerCommand, pUICommand));
113             if (SUCCEEDED(hr))
114             {
115                 if (pceltFetched)
116                     *pceltFetched = 1;
117             }
118             return hr;
119         }
120         return S_FALSE;
121     }
122     STDMETHODIMP Skip(ULONG celt)
123     {
124         if (m_bFirst)
125         {
126             m_bFirst = false;
127             return S_OK;
128         }
129         return S_FALSE;
130     }
131     STDMETHODIMP Reset()
132     {
133         m_bFirst = true;
134         return S_OK;
135     }
136     STDMETHODIMP Clone(IEnumExplorerCommand **ppenum)
137     {
138         return E_NOTIMPL;
139     }
140 
141 public:
142     DECLARE_NOT_AGGREGATABLE(CEnumExplorerCommand)
143     DECLARE_PROTECT_FINAL_CONSTRUCT()
144 
145     BEGIN_COM_MAP(CEnumExplorerCommand)
146         COM_INTERFACE_ENTRY_IID(IID_IEnumExplorerCommand, IEnumExplorerCommand)
147     END_COM_MAP()
148 };
149 
150 class CExplorerCommandProvider :
151     public CComObjectRootEx<CComMultiThreadModelNoCS>,
152     public IExplorerCommandProvider
153 {
154 private:
155     CComPtr<IContextMenu> m_pZipObject;
156 
157 public:
158     STDMETHODIMP Initialize(IContextMenu* zipObject)
159     {
160         m_pZipObject = zipObject;
161         return S_OK;
162     }
163 
164     // *** IExplorerCommandProvider methods ***
165     STDMETHODIMP GetCommands(IUnknown *punkSite, REFIID riid, void **ppv)
166     {
167         return ShellObjectCreatorInit<CEnumExplorerCommand>(m_pZipObject, riid, ppv);
168     }
169     STDMETHODIMP GetCommand(REFGUID rguidCommandId, REFIID riid, void **ppv)
170     {
171         UNIMPLEMENTED;
172         *ppv = NULL;
173         return E_NOTIMPL;
174     }
175 
176 public:
177     DECLARE_NOT_AGGREGATABLE(CExplorerCommandProvider)
178     DECLARE_PROTECT_FINAL_CONSTRUCT()
179 
180     BEGIN_COM_MAP(CExplorerCommandProvider)
181         COM_INTERFACE_ENTRY_IID(IID_IExplorerCommandProvider, IExplorerCommandProvider)
182     END_COM_MAP()
183 };
184 
185 
186 HRESULT _CExplorerCommandProvider_CreateInstance(IContextMenu* zipObject, REFIID riid, LPVOID * ppvOut)
187 {
188     return ShellObjectCreatorInit<CExplorerCommandProvider>(zipObject, riid, ppvOut);
189 }
190