OSDN Git Service

Add WinMergePluginBase.h (3)
[winmerge-jp/winmerge-jp.git] / Src / WinMergePluginBase.h
1 #include <oleauto.h>
2 #include <string>
3 #include <map>
4
5 class WinMergePluginBase : public IDispatch, public ITypeInfo
6 {
7 public:
8         enum
9         {
10                 DISPID_PluginEvent = 1,
11                 DISPID_PluginDescription,
12                 DISPID_PluginIsAutomatic,
13                 DISPID_PluginFileFilters,
14                 DISPID_PluginUnpackedFileExtension,
15                 DISPID_UnpackFile,
16                 DISPID_PackFile,
17                 DISPID_ShowSettingsDialog,
18         };
19         struct MemberInfo
20         {
21                 std::wstring name;
22                 DISPID id;
23                 short params;
24                 short flags;
25                 HRESULT (STDMETHODCALLTYPE *pFunc)(IDispatch *pDispatch, BSTR bstrText, BSTR* pbstrResult);
26         };
27
28         WinMergePluginBase(const std::wstring& sEvent, const std::wstring& sDescription = L"",
29                 const std::wstring& sFileFilters = L"", const std::wstring& sUnpackedFileExtension = L"", 
30                 bool bIsAutomatic = true)
31                 : m_nRef(0)
32                 , m_sEvent(sEvent)
33                 , m_sDescription(sDescription)
34                 , m_sFileFilters(sFileFilters)
35                 , m_sUnpackedFileExtension(sUnpackedFileExtension)
36                 , m_bIsAutomatic(bIsAutomatic)
37         {
38                 static const MemberInfo memberInfo[] =
39                 {
40                         { L"PluginEvent",                 DISPID_PluginEvent,                 0, DISPATCH_PROPERTYGET },
41                         { L"PluginDescription",           DISPID_PluginDescription,           0, DISPATCH_PROPERTYGET },
42                         { L"PluginIsAutomatic",           DISPID_PluginIsAutomatic,           0, DISPATCH_PROPERTYGET },
43                         { L"PluginFileFilters",           DISPID_PluginFileFilters,           0, DISPATCH_PROPERTYGET },
44                         { L"PluginUnpackedFileExtension", DISPID_PluginUnpackedFileExtension, 0, DISPATCH_PROPERTYGET },
45                         { L"UnpackFile",                  DISPID_UnpackFile,                  4, DISPATCH_METHOD },
46                         { L"PackFile",                    DISPID_PackFile ,                   4, DISPATCH_METHOD },
47                         { L"ShowSettingsDialog",          DISPID_ShowSettingsDialog,          0, DISPATCH_METHOD },
48                 };
49                 for (auto item : memberInfo)
50                 {
51                         if (item.id == DISPID_PluginIsAutomatic && sEvent == _T("EDITOR_SCRIPT"))
52                                 break;
53                         if (item.id == DISPID_PluginUnpackedFileExtension && m_sUnpackedFileExtension.empty())
54                                 continue;
55                         m_mapNameToIndex.insert_or_assign(item.name, static_cast<int>(m_memberInfo.size()));
56                         m_mapDispIdToIndex.insert_or_assign(item.id, static_cast<int>(m_memberInfo.size()));
57                         m_memberInfo.push_back(item);
58                 }
59         }
60
61         virtual ~WinMergePluginBase() {}
62
63         HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override
64         {
65                 return E_NOTIMPL;
66         }
67
68         ULONG STDMETHODCALLTYPE AddRef(void) override
69         {
70                 return ++m_nRef;
71         }
72
73         ULONG STDMETHODCALLTYPE Release(void) override
74         {
75                 if (--m_nRef == 0)
76                 {
77                         delete this;
78                         return 0;
79                 }
80                 return m_nRef;
81         }
82
83         HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override
84         {
85                 *pctinfo = static_cast<UINT>(m_memberInfo.size());
86                 return S_OK;
87         }
88
89         HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override
90         {
91                 *ppTInfo = this;
92                 (*ppTInfo)->AddRef();
93                 return S_OK;
94         }
95
96         HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override
97         {
98                 for (unsigned i = 0; i < cNames; ++i)
99                 {
100                         auto it = m_mapNameToIndex.find(rgszNames[i]);
101                         if (it == m_mapNameToIndex.end())
102                                 return DISP_E_UNKNOWNNAME;
103                         rgDispId[i] = m_memberInfo[it->second].id;
104                 }
105                 return S_OK;
106         }
107
108         HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override
109         {
110                 if (!pDispParams)
111                         return DISP_E_BADVARTYPE;
112                 HRESULT hr = E_NOTIMPL;
113                 if (wFlags == DISPATCH_METHOD)
114                 {
115                         switch (dispIdMember)
116                         {
117                         case DISPID_UnpackFile:
118                         {
119                                 BSTR fileSrc = pDispParams->rgvarg[3].bstrVal;
120                                 BSTR fileDst = pDispParams->rgvarg[2].bstrVal;
121                                 VARIANT_BOOL* pbChanged = pDispParams->rgvarg[1].pboolVal;
122                                 INT* pSubcode = &pDispParams->rgvarg[0].intVal;
123                                 VARIANT_BOOL* pbSuccess = &pVarResult->boolVal;
124                                 hr = UnpackFile(fileSrc, fileDst, pbChanged, pSubcode, pbSuccess);
125                                 break;
126                         }
127                         case DISPID_PackFile:
128                         {
129                                 BSTR fileSrc = pDispParams->rgvarg[3].bstrVal;
130                                 BSTR fileDst = pDispParams->rgvarg[2].bstrVal;
131                                 VARIANT_BOOL* pbChanged = pDispParams->rgvarg[1].pboolVal;
132                                 INT subcode = pDispParams->rgvarg[0].intVal;
133                                 VARIANT_BOOL* pbSuccess = &pVarResult->boolVal;
134                                 hr = PackFile(fileSrc, fileDst, pbChanged, subcode, pbSuccess);
135                                 break;
136                         }
137                         case DISPID_ShowSettingsDialog:
138                                 hr = ShowSettingsDialog(&pVarResult->boolVal);
139                                 break;
140                         default:
141                                 if (m_mapDispIdToIndex.find(dispIdMember) != m_mapDispIdToIndex.end())
142                                 {
143                                         BSTR bstrText = pDispParams->rgvarg[0].bstrVal;
144                                         pVarResult->vt = VT_BSTR;
145                                         BSTR* pbstrResult = &pVarResult->bstrVal;
146                                         hr = m_memberInfo[m_mapDispIdToIndex[dispIdMember]].pFunc(this, bstrText, pbstrResult);
147                                 }
148                                 break;
149                         }
150                 }
151                 else if (wFlags == DISPATCH_PROPERTYGET)
152                 {
153                         switch (dispIdMember)
154                         {
155                         case DISPID_PluginEvent:
156                                 pVarResult->vt = VT_BSTR;
157                                 hr = get_PluginEvent(&pVarResult->bstrVal);
158                                 break;
159                         case DISPID_PluginDescription:
160                                 pVarResult->vt = VT_BSTR;
161                                 hr = get_PluginDescription(&pVarResult->bstrVal);
162                                 break;
163                         case DISPID_PluginIsAutomatic:
164                                 pVarResult->vt = VT_BOOL;
165                                 hr = get_PluginIsAutomatic(&pVarResult->boolVal);
166                                 break;
167                         case DISPID_PluginFileFilters:
168                                 pVarResult->vt = VT_BSTR;
169                                 hr = get_PluginFileFilters(&pVarResult->bstrVal);
170                                 break;
171                         case DISPID_PluginUnpackedFileExtension:
172                                 pVarResult->vt = VT_BSTR;
173                                 hr = get_PluginUnpackedFileExtension(&pVarResult->bstrVal);
174                                 break;
175                         }
176                 }
177                 return hr;
178         }
179
180         HRESULT STDMETHODCALLTYPE GetTypeAttr(TYPEATTR** ppTypeAttr) override
181         {
182                 auto* pTypeAttr = new TYPEATTR();
183                 pTypeAttr->cFuncs = static_cast<WORD>(m_memberInfo.size());
184                 *ppTypeAttr = pTypeAttr;
185                 return S_OK;
186         }
187         
188         HRESULT STDMETHODCALLTYPE GetTypeComp(ITypeComp** ppTComp) override
189         {
190                 return E_NOTIMPL;
191         }
192         
193         HRESULT STDMETHODCALLTYPE GetFuncDesc(UINT index, FUNCDESC** ppFuncDesc) override
194         {
195                 if (index >= m_memberInfo.size())
196                         return E_INVALIDARG;
197                 auto* pFuncDesc = new FUNCDESC();
198                 pFuncDesc->funckind = FUNC_DISPATCH;
199                 pFuncDesc->invkind = static_cast<INVOKEKIND>(m_memberInfo[index].flags);
200                 pFuncDesc->wFuncFlags = 0;
201                 pFuncDesc->cParams = m_memberInfo[index].params;
202                 pFuncDesc->memid = m_memberInfo[index].id;
203                 pFuncDesc->callconv = CC_STDCALL;
204                 *ppFuncDesc = pFuncDesc;
205                 return S_OK;
206         }
207         
208         HRESULT STDMETHODCALLTYPE GetVarDesc(UINT index, VARDESC** ppVarDesc) override
209         {
210                 return E_NOTIMPL;
211         }
212         
213         HRESULT STDMETHODCALLTYPE GetNames(MEMBERID memid, BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames) override
214         {
215                 if (m_mapDispIdToIndex.find(memid) == m_mapDispIdToIndex.end())
216                         return E_INVALIDARG;
217                 *rgBstrNames = SysAllocString(m_memberInfo[m_mapDispIdToIndex[memid]].name.c_str());
218                 *pcNames = 1;
219                 return S_OK;
220         }
221         
222         HRESULT STDMETHODCALLTYPE GetRefTypeOfImplType(UINT index, HREFTYPE *pRefType) override
223         {
224                 return E_NOTIMPL;
225         }
226
227         HRESULT STDMETHODCALLTYPE GetImplTypeFlags(UINT index, INT *pImplTypeFlags) override
228         {
229                 return E_NOTIMPL;
230         }
231         
232         HRESULT STDMETHODCALLTYPE GetIDsOfNames(LPOLESTR* rgszNames, UINT cNames, MEMBERID* pMemId) override
233         {
234                 return GetIDsOfNames(IID_NULL, rgszNames, cNames, 0, pMemId);
235         }
236         
237         HRESULT STDMETHODCALLTYPE Invoke(PVOID pvInstance, MEMBERID memid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) override
238         {
239                 return reinterpret_cast<IDispatch*>(pvInstance)->Invoke(memid, IID_NULL, 0, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
240         }
241         
242         HRESULT STDMETHODCALLTYPE GetDocumentation(MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext, BSTR *pBstrHelpFile) override
243         {
244                 return E_NOTIMPL;
245         }
246         
247         HRESULT STDMETHODCALLTYPE GetDllEntry(MEMBERID memid, INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName, WORD *pwOrdinal)
248         {
249                 return E_NOTIMPL;
250         }
251         
252         HRESULT STDMETHODCALLTYPE GetRefTypeInfo(HREFTYPE hRefType, ITypeInfo **ppTInfo) override
253         {
254                 return E_NOTIMPL;
255         }
256         
257         HRESULT STDMETHODCALLTYPE AddressOfMember(MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) override
258         {
259                 return E_NOTIMPL;
260         }
261         
262         HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, PVOID *ppvObj) override
263         {
264                 return E_NOTIMPL;
265         }
266         
267         HRESULT STDMETHODCALLTYPE GetMops(MEMBERID memid, BSTR *pBstrMops) override
268         {
269                 return E_NOTIMPL;
270         }
271         
272         HRESULT STDMETHODCALLTYPE GetContainingTypeLib(ITypeLib **ppTLib, UINT *pIndex) override
273         {
274                 return E_NOTIMPL;
275         }
276         
277         void STDMETHODCALLTYPE ReleaseTypeAttr(TYPEATTR *pTypeAttr) override
278         {
279                 delete pTypeAttr;
280         }
281         
282         void STDMETHODCALLTYPE ReleaseFuncDesc(FUNCDESC *pFuncDesc) override
283         {
284                 delete pFuncDesc;
285         }
286         
287         void STDMETHODCALLTYPE ReleaseVarDesc(VARDESC *pVarDesc) override
288         {
289         }
290         
291         virtual HRESULT STDMETHODCALLTYPE PackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT subcode, VARIANT_BOOL* pbSuccess)
292         {
293                 *pbSuccess = VARIANT_FALSE;
294                 return E_NOTIMPL;
295         }
296
297         virtual HRESULT STDMETHODCALLTYPE UnpackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT* pSubcode, VARIANT_BOOL* pbSuccess)
298         {
299                 *pbSuccess = VARIANT_FALSE;
300                 return E_NOTIMPL;
301         }
302
303         virtual HRESULT STDMETHODCALLTYPE ShowSettingsDialog(VARIANT_BOOL* pbHandled)
304         {
305                 *pbHandled = VARIANT_FALSE;
306                 return E_NOTIMPL;
307         }
308
309         virtual HRESULT STDMETHODCALLTYPE get_PluginEvent(BSTR* pVal)
310         {
311                 *pVal = SysAllocString(m_sEvent.c_str());
312                 return S_OK;
313         }
314
315         virtual HRESULT STDMETHODCALLTYPE get_PluginDescription(BSTR* pVal)
316         {
317                 *pVal = SysAllocString(m_sDescription.c_str());
318                 return S_OK;
319         }
320
321         virtual HRESULT STDMETHODCALLTYPE get_PluginIsAutomatic(VARIANT_BOOL* pVal)
322         {
323                 *pVal = m_bIsAutomatic ? -1 : 0;
324                 return S_OK;
325         }
326
327         virtual HRESULT STDMETHODCALLTYPE get_PluginFileFilters(BSTR* pVal)
328         {
329                 *pVal = SysAllocString(m_sFileFilters.c_str());
330                 return S_OK;
331         }
332
333         virtual HRESULT STDMETHODCALLTYPE get_PluginUnpackedFileExtension(BSTR* pVal)
334         {
335                 *pVal = SysAllocString(m_sUnpackedFileExtension.c_str());
336                 return S_OK;
337         }
338
339         bool AddFunction(const std::wstring& name, HRESULT(STDMETHODCALLTYPE* pFunc)(IDispatch *pDispatch, BSTR bstrText, BSTR* pbstrResult))
340         {
341                 DISPID dispid = static_cast<DISPID>(m_memberInfo.size()) + 100;
342                 m_mapNameToIndex.insert_or_assign(name, static_cast<int>(m_memberInfo.size()));
343                 m_mapDispIdToIndex.insert_or_assign(dispid, static_cast<int>(m_memberInfo.size()));
344                 m_memberInfo.emplace_back(MemberInfo{ name, dispid, 1, DISPATCH_METHOD, pFunc });
345                 return true;
346         }
347
348 protected:
349         int m_nRef;
350         std::map<std::wstring, int> m_mapNameToIndex;
351         std::map<DISPID, int> m_mapDispIdToIndex;
352         std::vector<MemberInfo> m_memberInfo;
353         std::wstring m_sEvent;
354         std::wstring m_sDescription;
355         std::wstring m_sFileFilters;
356         std::wstring m_sUnpackedFileExtension;
357         bool m_bIsAutomatic;
358 };
359