5 class WinMergePluginBase : public IDispatch, public ITypeInfo
10 DISPID_PluginEvent = 1,
11 DISPID_PluginDescription,
12 DISPID_PluginIsAutomatic,
13 DISPID_PluginFileFilters,
14 DISPID_PluginUnpackedFileExtension,
17 DISPID_ShowSettingsDialog,
25 HRESULT (STDMETHODCALLTYPE *pFunc)(IDispatch *pDispatch, BSTR bstrText, BSTR* pbstrResult);
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)
33 , m_sDescription(sDescription)
34 , m_sFileFilters(sFileFilters)
35 , m_sUnpackedFileExtension(sUnpackedFileExtension)
36 , m_bIsAutomatic(bIsAutomatic)
38 static const MemberInfo memberInfo[] =
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 },
49 for (auto item : memberInfo)
51 if (item.id == DISPID_PluginIsAutomatic && sEvent == _T("EDITOR_SCRIPT"))
53 if (item.id == DISPID_PluginUnpackedFileExtension && m_sUnpackedFileExtension.empty())
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);
61 virtual ~WinMergePluginBase() {}
63 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override
68 ULONG STDMETHODCALLTYPE AddRef(void) override
73 ULONG STDMETHODCALLTYPE Release(void) override
83 HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override
85 *pctinfo = static_cast<UINT>(m_memberInfo.size());
89 HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override
96 HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override
98 for (unsigned i = 0; i < cNames; ++i)
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;
108 HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override
111 return DISP_E_BADVARTYPE;
112 HRESULT hr = E_NOTIMPL;
113 if (wFlags == DISPATCH_METHOD)
115 switch (dispIdMember)
117 case DISPID_UnpackFile:
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);
127 case DISPID_PackFile:
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);
137 case DISPID_ShowSettingsDialog:
138 hr = ShowSettingsDialog(&pVarResult->boolVal);
141 if (m_mapDispIdToIndex.find(dispIdMember) != m_mapDispIdToIndex.end())
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);
151 else if (wFlags == DISPATCH_PROPERTYGET)
153 switch (dispIdMember)
155 case DISPID_PluginEvent:
156 pVarResult->vt = VT_BSTR;
157 hr = get_PluginEvent(&pVarResult->bstrVal);
159 case DISPID_PluginDescription:
160 pVarResult->vt = VT_BSTR;
161 hr = get_PluginDescription(&pVarResult->bstrVal);
163 case DISPID_PluginIsAutomatic:
164 pVarResult->vt = VT_BOOL;
165 hr = get_PluginIsAutomatic(&pVarResult->boolVal);
167 case DISPID_PluginFileFilters:
168 pVarResult->vt = VT_BSTR;
169 hr = get_PluginFileFilters(&pVarResult->bstrVal);
171 case DISPID_PluginUnpackedFileExtension:
172 pVarResult->vt = VT_BSTR;
173 hr = get_PluginUnpackedFileExtension(&pVarResult->bstrVal);
180 HRESULT STDMETHODCALLTYPE GetTypeAttr(TYPEATTR** ppTypeAttr) override
182 auto* pTypeAttr = new TYPEATTR();
183 pTypeAttr->cFuncs = static_cast<WORD>(m_memberInfo.size());
184 *ppTypeAttr = pTypeAttr;
188 HRESULT STDMETHODCALLTYPE GetTypeComp(ITypeComp** ppTComp) override
193 HRESULT STDMETHODCALLTYPE GetFuncDesc(UINT index, FUNCDESC** ppFuncDesc) override
195 if (index >= m_memberInfo.size())
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;
208 HRESULT STDMETHODCALLTYPE GetVarDesc(UINT index, VARDESC** ppVarDesc) override
213 HRESULT STDMETHODCALLTYPE GetNames(MEMBERID memid, BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames) override
215 if (m_mapDispIdToIndex.find(memid) == m_mapDispIdToIndex.end())
217 *rgBstrNames = SysAllocString(m_memberInfo[m_mapDispIdToIndex[memid]].name.c_str());
222 HRESULT STDMETHODCALLTYPE GetRefTypeOfImplType(UINT index, HREFTYPE *pRefType) override
227 HRESULT STDMETHODCALLTYPE GetImplTypeFlags(UINT index, INT *pImplTypeFlags) override
232 HRESULT STDMETHODCALLTYPE GetIDsOfNames(LPOLESTR* rgszNames, UINT cNames, MEMBERID* pMemId) override
234 return GetIDsOfNames(IID_NULL, rgszNames, cNames, 0, pMemId);
237 HRESULT STDMETHODCALLTYPE Invoke(PVOID pvInstance, MEMBERID memid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) override
239 return reinterpret_cast<IDispatch*>(pvInstance)->Invoke(memid, IID_NULL, 0, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
242 HRESULT STDMETHODCALLTYPE GetDocumentation(MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext, BSTR *pBstrHelpFile) override
247 HRESULT STDMETHODCALLTYPE GetDllEntry(MEMBERID memid, INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName, WORD *pwOrdinal)
252 HRESULT STDMETHODCALLTYPE GetRefTypeInfo(HREFTYPE hRefType, ITypeInfo **ppTInfo) override
257 HRESULT STDMETHODCALLTYPE AddressOfMember(MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) override
262 HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, PVOID *ppvObj) override
267 HRESULT STDMETHODCALLTYPE GetMops(MEMBERID memid, BSTR *pBstrMops) override
272 HRESULT STDMETHODCALLTYPE GetContainingTypeLib(ITypeLib **ppTLib, UINT *pIndex) override
277 void STDMETHODCALLTYPE ReleaseTypeAttr(TYPEATTR *pTypeAttr) override
282 void STDMETHODCALLTYPE ReleaseFuncDesc(FUNCDESC *pFuncDesc) override
287 void STDMETHODCALLTYPE ReleaseVarDesc(VARDESC *pVarDesc) override
291 virtual HRESULT STDMETHODCALLTYPE PackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT subcode, VARIANT_BOOL* pbSuccess)
293 *pbSuccess = VARIANT_FALSE;
297 virtual HRESULT STDMETHODCALLTYPE UnpackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT* pSubcode, VARIANT_BOOL* pbSuccess)
299 *pbSuccess = VARIANT_FALSE;
303 virtual HRESULT STDMETHODCALLTYPE ShowSettingsDialog(VARIANT_BOOL* pbHandled)
305 *pbHandled = VARIANT_FALSE;
309 virtual HRESULT STDMETHODCALLTYPE get_PluginEvent(BSTR* pVal)
311 *pVal = SysAllocString(m_sEvent.c_str());
315 virtual HRESULT STDMETHODCALLTYPE get_PluginDescription(BSTR* pVal)
317 *pVal = SysAllocString(m_sDescription.c_str());
321 virtual HRESULT STDMETHODCALLTYPE get_PluginIsAutomatic(VARIANT_BOOL* pVal)
323 *pVal = m_bIsAutomatic ? -1 : 0;
327 virtual HRESULT STDMETHODCALLTYPE get_PluginFileFilters(BSTR* pVal)
329 *pVal = SysAllocString(m_sFileFilters.c_str());
333 virtual HRESULT STDMETHODCALLTYPE get_PluginUnpackedFileExtension(BSTR* pVal)
335 *pVal = SysAllocString(m_sUnpackedFileExtension.c_str());
339 bool AddFunction(const std::wstring& name, HRESULT(STDMETHODCALLTYPE* pFunc)(IDispatch *pDispatch, BSTR bstrText, BSTR* pbstrResult))
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 });
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;