5 class WinMergePluginBase : public IDispatch, public ITypeInfo
10 DISPID_PluginEvent = 1,
11 DISPID_PluginDescription,
12 DISPID_PluginIsAutomatic,
13 DISPID_PluginFileFilters,
16 DISPID_ShowSettingsDialog,
24 HRESULT (STDMETHODCALLTYPE *pFunc)(IDispatch *pDispatch, BSTR bstrText, BSTR* pbstrResult);
27 WinMergePluginBase(const std::wstring& sEvent, const std::wstring& sDescription = L"",
28 const std::wstring& sFileFilters = L"", bool bIsAutomatic = true)
31 , m_sDescription(sDescription)
32 , m_sFileFilters(sFileFilters)
33 , m_bIsAutomatic(bIsAutomatic)
35 static const MemberInfo memberInfo[] =
37 { L"PluginEvent", DISPID_PluginEvent, 0, DISPATCH_PROPERTYGET },
38 { L"PluginDescription", DISPID_PluginDescription, 0, DISPATCH_PROPERTYGET },
39 { L"PluginIsAutomatic", DISPID_PluginIsAutomatic, 0, DISPATCH_PROPERTYGET },
40 { L"PluginFileFilters", DISPID_PluginFileFilters, 0, DISPATCH_PROPERTYGET },
41 { L"UnpackFile", DISPID_UnpackFile, 4, DISPATCH_METHOD },
42 { L"PackFile", DISPID_PackFile , 4, DISPATCH_METHOD },
43 { L"ShowSettingsDialog", DISPID_ShowSettingsDialog, 0, DISPATCH_METHOD },
45 for (auto item : memberInfo)
47 if (item.id == DISPID_PluginIsAutomatic && sEvent == _T("EDITOR_SCRIPT"))
49 m_mapNameToIndex.insert_or_assign(item.name, static_cast<int>(m_memberInfo.size()));
50 m_mapDispIdToIndex.insert_or_assign(item.id, static_cast<int>(m_memberInfo.size()));
51 m_memberInfo.push_back(item);
55 virtual ~WinMergePluginBase() {}
57 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override
62 ULONG STDMETHODCALLTYPE AddRef(void) override
67 ULONG STDMETHODCALLTYPE Release(void) override
77 HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override
79 *pctinfo = static_cast<UINT>(m_memberInfo.size());
83 HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override
90 HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override
92 for (unsigned i = 0; i < cNames; ++i)
94 auto it = m_mapNameToIndex.find(rgszNames[i]);
95 if (it == m_mapNameToIndex.end())
96 return DISP_E_UNKNOWNNAME;
97 rgDispId[i] = m_memberInfo[it->second].id;
102 HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override
105 return DISP_E_BADVARTYPE;
106 HRESULT hr = E_NOTIMPL;
107 if (wFlags == DISPATCH_METHOD)
109 switch (dispIdMember)
111 case DISPID_UnpackFile:
113 BSTR fileSrc = pDispParams->rgvarg[3].bstrVal;
114 BSTR fileDst = pDispParams->rgvarg[2].bstrVal;
115 VARIANT_BOOL* pbChanged = pDispParams->rgvarg[1].pboolVal;
116 INT* pSubcode = &pDispParams->rgvarg[0].intVal;
117 VARIANT_BOOL* pbSuccess = &pVarResult->boolVal;
118 hr = UnpackFile(fileSrc, fileDst, pbChanged, pSubcode, pbSuccess);
121 case DISPID_PackFile:
123 BSTR fileSrc = pDispParams->rgvarg[3].bstrVal;
124 BSTR fileDst = pDispParams->rgvarg[2].bstrVal;
125 VARIANT_BOOL* pbChanged = pDispParams->rgvarg[1].pboolVal;
126 INT subcode = pDispParams->rgvarg[0].intVal;
127 VARIANT_BOOL* pbSuccess = &pVarResult->boolVal;
128 hr = PackFile(fileSrc, fileDst, pbChanged, subcode, pbSuccess);
131 case DISPID_ShowSettingsDialog:
132 hr = ShowSettingsDialog(&pVarResult->boolVal);
135 if (m_mapDispIdToIndex.find(dispIdMember) != m_mapDispIdToIndex.end())
137 BSTR bstrText = pDispParams->rgvarg[0].bstrVal;
138 pVarResult->vt = VT_BSTR;
139 BSTR* pbstrResult = &pVarResult->bstrVal;
140 hr = m_memberInfo[m_mapDispIdToIndex[dispIdMember]].pFunc(this, bstrText, pbstrResult);
145 else if (wFlags == DISPATCH_PROPERTYGET)
147 switch (dispIdMember)
149 case DISPID_PluginFileFilters:
150 pVarResult->vt = VT_BSTR;
151 hr = get_PluginFileFilters(&pVarResult->bstrVal);
153 case DISPID_PluginIsAutomatic:
154 pVarResult->vt = VT_BOOL;
155 hr = get_PluginIsAutomatic(&pVarResult->boolVal);
157 case DISPID_PluginDescription:
158 pVarResult->vt = VT_BSTR;
159 hr = get_PluginDescription(&pVarResult->bstrVal);
161 case DISPID_PluginEvent:
162 pVarResult->vt = VT_BSTR;
163 hr = get_PluginEvent(&pVarResult->bstrVal);
170 HRESULT STDMETHODCALLTYPE GetTypeAttr(TYPEATTR** ppTypeAttr) override
172 auto* pTypeAttr = new TYPEATTR();
173 pTypeAttr->cFuncs = static_cast<WORD>(m_memberInfo.size());
174 *ppTypeAttr = pTypeAttr;
178 HRESULT STDMETHODCALLTYPE GetTypeComp(ITypeComp** ppTComp) override
183 HRESULT STDMETHODCALLTYPE GetFuncDesc(UINT index, FUNCDESC** ppFuncDesc) override
185 if (index >= m_memberInfo.size())
187 auto* pFuncDesc = new FUNCDESC();
188 pFuncDesc->funckind = FUNC_DISPATCH;
189 pFuncDesc->invkind = static_cast<INVOKEKIND>(m_memberInfo[index].flags);
190 pFuncDesc->wFuncFlags = 0;
191 pFuncDesc->cParams = m_memberInfo[index].params;
192 pFuncDesc->memid = m_memberInfo[index].id;
193 pFuncDesc->callconv = CC_STDCALL;
194 *ppFuncDesc = pFuncDesc;
198 HRESULT STDMETHODCALLTYPE GetVarDesc(UINT index, VARDESC** ppVarDesc) override
203 HRESULT STDMETHODCALLTYPE GetNames(MEMBERID memid, BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames) override
205 if (m_mapDispIdToIndex.find(memid) == m_mapDispIdToIndex.end())
207 *rgBstrNames = SysAllocString(m_memberInfo[m_mapDispIdToIndex[memid]].name.c_str());
212 HRESULT STDMETHODCALLTYPE GetRefTypeOfImplType(UINT index, HREFTYPE *pRefType) override
217 HRESULT STDMETHODCALLTYPE GetImplTypeFlags(UINT index, INT *pImplTypeFlags) override
222 HRESULT STDMETHODCALLTYPE GetIDsOfNames(LPOLESTR* rgszNames, UINT cNames, MEMBERID* pMemId) override
224 return GetIDsOfNames(IID_NULL, rgszNames, cNames, 0, pMemId);
227 HRESULT STDMETHODCALLTYPE Invoke(PVOID pvInstance, MEMBERID memid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) override
229 return reinterpret_cast<IDispatch*>(pvInstance)->Invoke(memid, IID_NULL, 0, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
232 HRESULT STDMETHODCALLTYPE GetDocumentation(MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext, BSTR *pBstrHelpFile) override
237 HRESULT STDMETHODCALLTYPE GetDllEntry(MEMBERID memid, INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName, WORD *pwOrdinal)
242 HRESULT STDMETHODCALLTYPE GetRefTypeInfo(HREFTYPE hRefType, ITypeInfo **ppTInfo) override
247 HRESULT STDMETHODCALLTYPE AddressOfMember(MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) override
252 HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, PVOID *ppvObj) override
257 HRESULT STDMETHODCALLTYPE GetMops(MEMBERID memid, BSTR *pBstrMops) override
262 HRESULT STDMETHODCALLTYPE GetContainingTypeLib(ITypeLib **ppTLib, UINT *pIndex) override
267 void STDMETHODCALLTYPE ReleaseTypeAttr(TYPEATTR *pTypeAttr) override
272 void STDMETHODCALLTYPE ReleaseFuncDesc(FUNCDESC *pFuncDesc) override
277 void STDMETHODCALLTYPE ReleaseVarDesc(VARDESC *pVarDesc) override
281 virtual HRESULT STDMETHODCALLTYPE PackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT subcode, VARIANT_BOOL* pbSuccess)
283 *pbSuccess = VARIANT_FALSE;
287 virtual HRESULT STDMETHODCALLTYPE UnpackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT* pSubcode, VARIANT_BOOL* pbSuccess)
289 *pbSuccess = VARIANT_FALSE;
293 virtual HRESULT STDMETHODCALLTYPE ShowSettingsDialog(VARIANT_BOOL* pbHandled)
295 *pbHandled = VARIANT_FALSE;
299 virtual HRESULT STDMETHODCALLTYPE get_PluginIsAutomatic(VARIANT_BOOL* pVal)
301 *pVal = m_bIsAutomatic ? -1 : 0;
305 virtual HRESULT STDMETHODCALLTYPE get_PluginFileFilters(BSTR* pVal)
307 *pVal = SysAllocString(m_sFileFilters.c_str());
311 virtual HRESULT STDMETHODCALLTYPE get_PluginDescription(BSTR* pVal)
313 *pVal = SysAllocString(m_sDescription.c_str());
317 virtual HRESULT STDMETHODCALLTYPE get_PluginEvent(BSTR* pVal)
319 *pVal = SysAllocString(m_sEvent.c_str());
323 bool AddFunction(const std::wstring& name, HRESULT(STDMETHODCALLTYPE* pFunc)(IDispatch *pDispatch, BSTR bstrText, BSTR* pbstrResult))
325 DISPID dispid = static_cast<DISPID>(m_memberInfo.size()) + 100;
326 m_mapNameToIndex.insert_or_assign(name, static_cast<int>(m_memberInfo.size()));
327 m_mapDispIdToIndex.insert_or_assign(dispid, static_cast<int>(m_memberInfo.size()));
328 m_memberInfo.emplace_back(MemberInfo{ name, dispid, 1, DISPATCH_METHOD, pFunc });
334 std::map<std::wstring, int> m_mapNameToIndex;
335 std::map<DISPID, int> m_mapDispIdToIndex;
336 std::vector<MemberInfo> m_memberInfo;
337 std::wstring m_sEvent;
338 std::wstring m_sDescription;
339 std::wstring m_sFileFilters;