Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 76347 - Application throws exception while querying interface
Summary: Application throws exception while querying interface
Status: RESOLVED DUPLICATE of bug 21148
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: Veronika Irvine CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-10-15 08:12 EDT by Tadas Savičius CLA
Modified: 2004-10-18 16:34 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tadas Savičius CLA 2004-10-15 08:12:57 EDT
We have situation: 
java application tries to open word application. It fails on two computers. But
works fine on another two computers. 

This is sample code:
* * * * * 
        Shell shell = new Shell();
        OleFrame frame = new OleFrame(shell, SWT.NONE);
        
        OleControlSite clientSite = new OleControlSite(frame,
SWT.NONE,"Word.Document");
* * * * *

Application throws exception: 
org.eclipse.swt.SWTException: Failed to find requested interface on OLE Object.
result = -2147467262
	at org.eclipse.swt.ole.win32.OLE.error(OLE.java:312)
...

It fails while trying to query interface "COM.IIDIViewObject2". The problem is -
it does well on two computers and fails on others two. 
So, first, we have tried to reinstall word. And we've found another mystic
behaviour:
if we do not restart computer after installing word - application works fine. If
we do restart it - application throws error... 


So, we wrote test application to see what differences are between these situations.

Here is the code we tested:

import java.awt.Composite;

import org.eclipse.swt.SWTException;
import org.eclipse.swt.internal.ole.win32.COM;
import org.eclipse.swt.internal.ole.win32.COMObject;
import org.eclipse.swt.internal.ole.win32.GUID;
import org.eclipse.swt.internal.ole.win32.IMoniker;
import org.eclipse.swt.internal.ole.win32.IOleCommandTarget;
import org.eclipse.swt.internal.ole.win32.IOleDocument;
import org.eclipse.swt.internal.ole.win32.IOleDocumentView;
import org.eclipse.swt.internal.ole.win32.IOleInPlaceObject;
import org.eclipse.swt.internal.ole.win32.IOleLink;
import org.eclipse.swt.internal.ole.win32.IOleObject;
import org.eclipse.swt.internal.ole.win32.IPersist;
import org.eclipse.swt.internal.ole.win32.IStorage;
import org.eclipse.swt.internal.ole.win32.IUnknown;
import org.eclipse.swt.internal.ole.win32.IViewObject2;
import org.eclipse.swt.internal.ole.win32.OLEINPLACEFRAMEINFO;
import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.internal.win32.RECT;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.widgets.Listener;


public class TestCOM {

    public TestCOM() {
        createCOMInterfaces();
    }
    
    public static void main(String[] args) {
        new TestCOM().OleClientSite(null,0,WORDPROGID);
    }
    
    public void OleClientSite(Composite parent, int style, String progId) {
//        this(parent, style);
        try {
            appClsid = getClassID(progId);
            if (appClsid == null)
                OLE.error(OLE.ERROR_INVALID_CLASSID);
            track("appClsid ",appClsid);
                
            // Open a temporary storage object
            tempStorage = createTempStorage();
        
            // Create ole object with storage object
            int[] address = new int[1];
            int result = COM.OleCreate(appClsid, COM.IIDIUnknown,
COM.OLERENDER_DRAW, null, 0, tempStorage.getAddress(), address);
            track("COM.OleCreate",address);
            if (result != COM.S_OK)
                OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);

            objIUnknown = new IUnknown(address[0]);

            // Init sinks
            addObjectReferences();

            if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK) state =
STATE_RUNNING;
            
        } catch (SWTException e) {
            dispose();
            disposeCOMInterfaces();
            throw e;
        }
    }
    
    protected void addObjectReferences() {
        //
        int[] ppvObject = new int[1];
        if (objIUnknown.QueryInterface(COM.IIDIPersist, ppvObject) == COM.S_OK) {
            track("COM.IIDIPersist ",ppvObject);
            IPersist objIPersist = new IPersist(ppvObject[0]);
            GUID tempid = new GUID();
            if (objIPersist.GetClassID(tempid) == COM.S_OK)
                objClsid = tempid;
            track("tempid ",tempid);
            track("objClsid ",objClsid);

            objIPersist.Release();
        }
        
        //
        ppvObject = new int[1];
        int result = objIUnknown.QueryInterface(COM.IIDIViewObject2, ppvObject);
        track("COM.IIDIViewObject2 ",ppvObject);
        if (result != COM.S_OK)
            OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND, result);
        objIViewObject2 = new IViewObject2(ppvObject[0]);
        objIViewObject2.SetAdvise(aspect, 0, iAdviseSink.getAddress());

        //
        ppvObject = new int[1];
        result = objIUnknown.QueryInterface(COM.IIDIOleObject, ppvObject);
        track("COM.IIDIOleObject ",ppvObject);
        if (result != COM.S_OK)
            OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND, result);
        objIOleObject = new IOleObject(ppvObject[0]);
        objIOleObject.SetClientSite(iOleClientSite.getAddress());
        int[] pdwConnection = new int[1];
        objIOleObject.Advise(iAdviseSink.getAddress(), pdwConnection);
        track("objIOleObject.Advise pdwConnection",pdwConnection);
        objIOleObject.SetHostNames("main", "main");  //$NON-NLS-1$ //$NON-NLS-2$

        // Notify the control object that it is embedded in an OLE container
        COM.OleSetContainedObject(objIUnknown.getAddress(), true);

        // Is OLE object linked or embedded?
        ppvObject = new int[1];
        if (objIUnknown.QueryInterface(COM.IIDIOleLink, ppvObject) == COM.S_OK) {
            IOleLink objIOleLink = new IOleLink(ppvObject[0]);
            int[] ppmk = new int[1];
            if (objIOleLink.GetSourceMoniker(ppmk) == COM.S_OK) {
                IMoniker objIMoniker = new IMoniker(ppmk[0]);
                objIMoniker.Release();
                type = COM.OLELINKED;
                objIOleLink.BindIfRunning();
            } else {
                isStatic = true;
            }
            objIOleLink.Release();
        }
    }
    protected int AddRef() {
        refCount++;
        return refCount;
    }


    protected IStorage createTempStorage() {
        int[] tempStorage = new int[1];
        int grfMode = COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE |
COM.STGM_DELETEONRELEASE;
        int result = COM.StgCreateDocfile(null, grfMode, 0, tempStorage);
        track("COM.StgCreateDocfile",tempStorage);
        if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_FILE, result);
        return new IStorage(tempStorage[0]);
    }

    protected GUID getClassID(String clientName) {
        // create a GUID struct to hold the result
        GUID guid = new GUID();
        
        // create a null terminated array of char
        char[] buffer = null;
        if (clientName != null) {
            int count = clientName.length();
            buffer = new char[count + 1];
            clientName.getChars(0, count, buffer, 0);
        }
        if (COM.CLSIDFromProgID(buffer, guid) != COM.S_OK){
            int result = COM.CLSIDFromString(buffer, guid);
            if (result != COM.S_OK)
                OLE.error(OLE.ERROR_INVALID_CLASSID, result);
        }
        return guid;
    }
    /**
     * Deactivates an active in-place object and discards the object's undo state.
     */
    public void deactivateInPlaceClient() {
        if (objIOleInPlaceObject != null) {
            objIOleInPlaceObject.InPlaceDeactivate();
        }
    }
    protected void createCOMInterfaces() {
        
        iUnknown = new COMObject(new int[]{2, 0, 0}){
            public int method0(int[] args) {return QueryInterface(args[0],
args[1]);}
            public int method1(int[] args) {return AddRef();}
            public int method2(int[] args) {return Release();}
        };
        
        iOleClientSite = new COMObject(new int[]{2, 0, 0, 0, 3, 1, 0, 1, 0}){
            public int method0(int[] args) {return QueryInterface(args[0],
args[1]);}
            public int method1(int[] args) {return AddRef();}
            public int method2(int[] args) {return Release();}
            public int method3(int[] args) {return SaveObject();}
            // method4 GetMoniker - not implemented
            public int method5(int[] args) {return GetContainer(args[0]);}
            public int method6(int[] args) {return ShowObject();}
            public int method7(int[] args) {return OnShowWindow(args[0]);}
            // method8 RequestNewObjectLayout - not implemented
        };
        
        iAdviseSink = new COMObject(new int[]{2, 0, 0, 2, 2, 1, 0, 0}){
            public int method0(int[] args) {return QueryInterface(args[0],
args[1]);}
            public int method1(int[] args) {return AddRef();}
            public int method2(int[] args) {return Release();}
            public int method3(int[] args) {return OnDataChange(args[0], args[1]);}
            public int method4(int[] args) {return OnViewChange(args[0], args[1]);}
            //method5 OnRename - not implemented
            public int method6(int[] args) {OnSave();return 0;}
            public int method7(int[] args) {return OnClose();}  
        };
        
        iOleInPlaceSite = new COMObject(new int[]{2, 0, 0, 1, 1, 0, 0, 0, 5, 1,
1, 0, 0, 0, 1}){
            public int method0(int[] args) {return QueryInterface(args[0],
args[1]);}
            public int method1(int[] args) {return AddRef();}
            public int method2(int[] args) {return Release();}
            public int method3(int[] args) {return GetWindow(args[0]);}
            public int method4(int[] args) {return ContextSensitiveHelp(args[0]);}
            public int method5(int[] args) {return CanInPlaceActivate();}
            public int method6(int[] args) {return OnInPlaceActivate();}
            public int method7(int[] args) {return OnUIActivate();}
            public int method8(int[] args) {return GetWindowContext(args[0],
args[1], args[2], args[3], args[4]);}
            public int method9(int[] args) {return Scroll(args[0]);}
            public int method10(int[] args) {return OnUIDeactivate(args[0]);}
            public int method11(int[] args) {return OnInPlaceDeactivate();}
            // method12 DiscardUndoState - not implemented
            // method13 DeactivateAndUndoChange - not implemented
            public int method14(int[] args) {return OnPosRectChange(args[0]);}
        };
        
        iOleDocumentSite = new COMObject(new int[]{2, 0, 0, 1}){
            public int method0(int[] args) {return QueryInterface(args[0],
args[1]);}
            public int method1(int[] args) {return AddRef();}
            public int method2(int[] args) {return Release();}
            public int method3(int[] args) {return ActivateMe(args[0]);}
        };  
    }
    private void deleteTempStorage() {
        //Destroy this item's contents in the temp root IStorage.
        if (tempStorage != null){
            tempStorage.Release();
        }
        tempStorage = null;
    }
    protected void disposeCOMInterfaces() {
        if (iUnknown != null)
            iUnknown.dispose();
        iUnknown = null;
        
        if (iOleClientSite != null)
        iOleClientSite.dispose();
        iOleClientSite = null;
        
        if (iAdviseSink != null)
            iAdviseSink.dispose();
        iAdviseSink = null;
        
        if (iOleInPlaceSite != null)
            iOleInPlaceSite.dispose();
        iOleInPlaceSite = null;
        
        if (iOleDocumentSite != null)
            iOleDocumentSite.dispose();
        iOleDocumentSite = null;
    }

    private int GetContainer(int ppContainer) {
        /* Simple containers that do not support links to their embedded 
         * objects probably do not need to implement this method. Instead, 
         * they can return E_NOINTERFACE and set ppContainer to NULL.
         */
        if (ppContainer != 0)
            COM.MoveMemory(ppContainer, new int[]{0}, 4);
        return COM.E_NOINTERFACE;
    }
    int ActivateMe(int pViewToActivate) {
        return COM.S_OK;
    }
    private int CanInPlaceActivate() {
        return COM.S_FALSE;
    }
    private int ContextSensitiveHelp(int fEnterMode) {
        return COM.S_OK;
    }
    protected int GetWindow(int phwnd) {
        if (phwnd == 0)
            return COM.E_INVALIDARG;
        if (frame == null) {
            COM.MoveMemory(phwnd, new int[] {0}, 4);
            return COM.E_NOTIMPL;
        }
        
        // Copy the Window's handle into the memory passed in
        COM.MoveMemory(phwnd, new int[] {frame.handle}, 4);
        return COM.S_OK;
    }
    /*
    RECT getRect() {
        Point location = this.getLocation();
        Rectangle area = frame.getClientArea();
        RECT rect = new RECT();
        rect.left   = location.x;
        rect.top    = location.y;
        rect.right  = location.x + area.width - borderWidths.left -
borderWidths.right;
        rect.bottom = location.y + area.height - borderWidths.top -
borderWidths.bottom;
        return rect;
    }
    */
    private int GetWindowContext(int ppFrame, int ppDoc, int lprcPosRect, int
lprcClipRect, int lpFrameInfo) {  
            return COM.E_NOTIMPL;
    }
    private int OnClose() {
        return COM.S_OK;
    }
    private int OnDataChange(int pFormatetc, int pStgmed) {
        return COM.S_OK;
    }
    private int OnInPlaceActivate() {
        return COM.S_OK;
    }
    private int OnInPlaceDeactivate() {
        return COM.S_OK;
    }
    private int OnPosRectChange(int lprcPosRect) {
        return COM.S_OK;
    }
    private void OnSave() {
    }
    private int OnShowWindow(int fShow) {
        return COM.S_OK;
    }
    private int OnUIActivate() {
        return COM.S_OK;
    }
    private int OnUIDeactivate(int fUndoable) {
            return COM.S_OK;
    }
    private int OnViewChange(int dwAspect, int lindex) {
        return COM.S_OK;
    }
    protected int QueryInterface(int riid, int ppvObject) {

        if (riid == 0 || ppvObject == 0)
            return COM.E_NOINTERFACE;
        GUID guid = new GUID();
        COM.MoveMemory(guid, riid, GUID.sizeof);

        if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) {
            COM.MoveMemory(ppvObject, new int[] {iUnknown.getAddress()}, 4);
            AddRef();
            return COM.S_OK;
        }
        if (COM.IsEqualGUID(guid, COM.IIDIAdviseSink)) {
            COM.MoveMemory(ppvObject, new int[] {iAdviseSink.getAddress()}, 4);
            AddRef();
            return COM.S_OK;
        }
        if (COM.IsEqualGUID(guid, COM.IIDIOleClientSite)) {
            COM.MoveMemory(ppvObject, new int[] {iOleClientSite.getAddress()}, 4);
            AddRef();
            return COM.S_OK;
        }
        if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceSite)) {
            COM.MoveMemory(ppvObject, new int[] {iOleInPlaceSite.getAddress()}, 4);
            AddRef();
            return COM.S_OK;
        }
//     INTENTIONALLY COMMENTED - see bug 35493  
//      if (COM.IsEqualGUID(guid, COM.IIDIOleDocumentSite )) {
//          String progID = getProgramID();
//          if (!progID.startsWith("PowerPoint")) { //$NON-NLS-1$
//              COM.MoveMemory(ppvObject, new int[]
{iOleDocumentSite.getAddress()}, 4);
//              AddRef();
//              return COM.S_OK;
//          }
//      }
        COM.MoveMemory(ppvObject, new int[] {0}, 4);
        return COM.E_NOINTERFACE;
    }
    protected int Release() {
        refCount--;
        
        if (refCount == 0) {
            disposeCOMInterfaces();
        }
        return refCount;
    }
    private int SaveObject() {
        return COM.S_OK;
    }
    private int Scroll(int scrollExtant) {
        return COM.S_OK;
    }
    private int ShowObject() {
        /* Tells the container to position the object so it is visible to 
         * the user. This method ensures that the container itself is 
         * visible and not minimized.
         */
        return COM.S_OK;
    }

    public void dispose() {
        
    }
    // Interfaces for this Ole Client Container
    private COMObject  iUnknown;
    private COMObject  iOleClientSite;
    private COMObject  iAdviseSink;
    private COMObject  iOleInPlaceSite;
    private COMObject  iOleDocumentSite;
    
    protected GUID appClsid;
    private GUID objClsid;
    private int  refCount;
    
    // References to the associated Frame.
    protected OleFrame frame;
    
    // Access to the embedded/linked Ole Object 
    protected IUnknown                  objIUnknown;
    protected IOleObject                 objIOleObject;
    protected IViewObject2             objIViewObject2;
    protected IOleInPlaceObject     objIOleInPlaceObject;
    protected IOleCommandTarget objIOleCommandTarget;
    protected IOleDocumentView    objDocumentView;
    
    // Related storage information
    protected IStorage tempStorage;     // IStorage interface of the receiver
    
    // Internal state and style information
    private int     aspect;    // the display aspect of the embedded object,
e.g., DvaspectContent or DvaspectIcon
    private int     type;      // Indicates the type of client that can be
supported inside this container
    private boolean isStatic;  // Indicates item's display is static, i.e., a
bitmap, metafile, etc.
    
    private RECT borderWidths = new RECT();
    private RECT indent = new RECT();
    private boolean inUpdate = false;
    private boolean inInit = true;
    private boolean inDispose = false;
    
    private static final String WORDPROGID = "Word.Document"; //$NON-NLS-1$
    
    private Listener listener;
    
    static final int STATE_NONE = 0;
    static final int STATE_RUNNING = 1;
    static final int STATE_INPLACEACTIVE = 2;
    static final int STATE_UIACTIVE = 3;
    static final int STATE_ACTIVE = 4;
    int state = STATE_NONE;

    public void track(String msg) {
        System.err.println(msg);
    }
    
    public void track(String msg, GUID guid) {
        System.err.print(msg);
        System.err.println(formatGuid(guid));
    }
    
    public void track(String msg, int[] addr) {
        System.err.print(msg);
        System.err.print(" 0x0");
        System.err.println(Integer.toHexString(addr[0]));
    }
    
    public static String formatGuid(GUID guid) {
        StringBuffer sb = new StringBuffer();

        sb.append(Integer.toHexString(guid.data3));
        sb.append(Integer.toHexString(guid.data2));
        sb.append(Integer.toHexString(guid.data1));
        sb.append('-');
        sb.append(Integer.toHexString(guid.b1));
        sb.append(Integer.toHexString(guid.b2));
        sb.append(Integer.toHexString(guid.b3));
        sb.append('-');
        sb.append(Integer.toHexString(guid.b4));
        sb.append(Integer.toHexString(guid.b5));
        sb.append(Integer.toHexString(guid.b6));
        sb.append(Integer.toHexString(guid.b7));
        
        return sb.toString();
    }

}



The results on computers there it works (and on computers there it doesn't work,
but after reinstalling word and BEFORE restart) are similar to: 

appClsid 0020906-000-00046
COM.StgCreateDocfile 0x03070888
COM.OleCreate 0x0a1628
COM.IIDIPersist  0x093038
tempid 0020906-000-00046
objClsid 0020906-000-00046
COM.IIDIOleObject  0x093034
COM.IIDIDataObject  0x093030
COM.IIDIViewObject2  0x0a1e30

And on computers there application doesn't work (and computers there it fails
after restart): 

appClsid 0020906-000-00046
COM.StgCreateDocfile 0x034f0888
COM.OleCreate 0x0a8edc
COM.IIDIPersist  0x0aa5fc
tempid 0020906-000-00046
objClsid 0020906-000-00046
COM.IIDIOleObject  0x0aa71c
COM.IIDIDataObject  0x0aa7ec
COM.IIDIViewObject2  0x00
org.eclipse.swt.SWTException: Failed to find requested interface on OLE Object.
result = -2147467262
	at org.eclipse.swt.ole.win32.OLE.error(OLE.java:312)
	at TestCOM.addObjectReferences(TestCOM.java:108)
	at TestCOM.OleClientSite(TestCOM.java:57)
	at TestCOM.main(TestCOM.java:33)
Exception in thread "main"  


The main difference here is that 
COM.OleCreate 0x0a1628 is higher than COM.IIDIPersist  0x093038 there
application works and 
COM.OleCreate 0x0a8edc is lower than COM.IIDIPersist  0x0aa5fc there it doesn't
work. 
It seems that application working state depends on whichone is higher.... 


Any thoughts on this?
Comment 1 Veronika Irvine CLA 2004-10-18 16:34:54 EDT
I don't think comparing the relative position of VTable addresses in global 
memory has very much significance.  This one still remains a mystery to me.  
To date, I still have not found a machine in my building that can reproduce 
this problem to really debug it.

Can you verify that the GUID for IVewObject2 is the same on all of your 
machines? (Look in the registry using regedit or use OleViewer to see the 
guids).

*** This bug has been marked as a duplicate of 21148 ***