1 /*******************************************************************************
2 * Copyright (c) 2000, 2017 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.ole.win32;
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.internal.*;
18 import org.eclipse.swt.internal.ole.win32.*;
19 import org.eclipse.swt.internal.win32.*;
21 final class OleEventSink
23 private OleControlSite widget;
25 private COMObject iDispatch;
28 private IUnknown objIUnknown;
29 private int eventCookie;
30 private GUID eventGuid;
32 private OleEventTable eventTable;
34 OleEventSink(OleControlSite widget, long iUnknown, GUID riid) {
37 this.eventGuid = riid;
38 this.objIUnknown = new IUnknown(iUnknown);
40 createCOMInterfaces();
44 long[] ppvObject = new long[1];
45 if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) {
46 IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]);
47 long[] ppCP = new long[1];
48 if (cpc.FindConnectionPoint(eventGuid, ppCP) == COM.S_OK) {
49 IConnectionPoint cp = new IConnectionPoint(ppCP[0]);
50 int[] pCookie = new int[1];
51 if (cp.Advise(iDispatch.getAddress(), pCookie) == COM.S_OK)
52 eventCookie = pCookie[0];
58 void addListener(int eventID, OleListener listener) {
59 if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
60 if (eventTable == null) eventTable = new OleEventTable ();
61 eventTable.hook(eventID, listener);
67 private void createCOMInterfaces() {
68 iDispatch = new COMObject(new int[]{2, 0, 0, 1, 3, 4, 8}){
70 public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
72 public long method1(long[] args) {return AddRef();}
74 public long method2(long[] args) {return Release();}
75 // method3 GetTypeInfoCount - not implemented
76 // method4 GetTypeInfo - not implemented
77 // method5 GetIDsOfNames - not implemented
79 public long method6(long[] args) {return Invoke((int)args[0], args[1], (int)args[2], (int)args[3], args[4], args[5], args[6], args[7]);}
83 // disconnect event sink
84 if (eventCookie != 0 && objIUnknown != null) {
85 long[] ppvObject = new long[1];
86 if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) {
87 IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]);
88 if (cpc.FindConnectionPoint(eventGuid, ppvObject) == COM.S_OK) {
89 IConnectionPoint cp = new IConnectionPoint(ppvObject[0]);
90 if (cp.Unadvise(eventCookie) == COM.S_OK) {
99 private void disposeCOMInterfaces() {
100 if (iDispatch != null)
105 private int Invoke(int dispIdMember, long riid, int lcid, int dwFlags, long pDispParams, long pVarResult, long pExcepInfo, long pArgErr)
107 if (eventTable == null || !eventTable.hooks(dispIdMember)) return COM.S_OK;
109 // Construct an array of the parameters that are passed in
110 // Note: parameters are passed in reverse order - here we will correct the order
111 Variant[] eventInfo = null;
112 if (pDispParams != 0) {
113 DISPPARAMS dispParams = new DISPPARAMS();
114 COM.MoveMemory(dispParams, pDispParams, DISPPARAMS.sizeof);
115 eventInfo = new Variant[dispParams.cArgs];
116 int size = VARIANT.sizeof;
117 long offset = (dispParams.cArgs - 1) * size;
119 for (int j = 0; j < dispParams.cArgs; j++){
120 eventInfo[j] = new Variant();
121 eventInfo[j].setData(dispParams.rgvarg + offset);
122 offset = offset - size;
126 OleEvent event = new OleEvent();
127 event.arguments = eventInfo;
128 notifyListener(dispIdMember,event);
130 if (eventInfo != null) {
131 for (int j = 0; j < eventInfo.length; j++){
132 eventInfo[j].dispose();
139 * Notify listeners of an event.
141 * This method notifies all listeners that an event
144 * @param eventType the desired SWT event
145 * @param event the event data
147 * @exception IllegalArgumentException <ul>
148 * <li>ERROR_NULL_ARGUMENT when handler is null</li>
150 * @exception SWTException <ul>
151 * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
152 * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
155 private void notifyListener (int eventType, OleEvent event) {
156 if (event == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
157 if (eventTable == null) return;
158 event.type = eventType;
159 event.widget = widget;
160 eventTable.sendEvent (event);
162 private int QueryInterface(long riid, long ppvObject) {
164 if (riid == 0 || ppvObject == 0)
165 return COM.E_INVALIDARG;
166 GUID guid = new GUID();
167 COM.MoveMemory(guid, riid, GUID.sizeof);
169 if ( COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) ||
170 COM.IsEqualGUID(guid, eventGuid)) {
171 OS.MoveMemory(ppvObject, new long[] {iDispatch.getAddress()}, C.PTR_SIZEOF);
176 OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
177 return COM.E_NOINTERFACE;
182 disposeCOMInterfaces();
187 void removeListener(int eventID, OleListener listener) {
188 if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
189 if (eventTable == null) return;
190 eventTable.unhook (eventID, listener);
192 boolean hasListeners() {
193 return eventTable.hasEntries();