/*******************************************************************************
 * Copyright (c) 2000, 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.browser;

import java.util.Hashtable;

import org.eclipse.swt.*;
import org.eclipse.swt.internal.C;
import org.eclipse.swt.internal.ole.win32.*;
import org.eclipse.swt.ole.win32.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.internal.win32.*;

@SuppressWarnings("rawtypes")
class WebSite extends OleControlSite {
	COMObject iDocHostUIHandler;
	COMObject iDocHostShowUI;
	COMObject iServiceProvider;
	COMObject iInternetSecurityManager;
	COMObject iOleCommandTarget;
	COMObject iAuthenticate;
	COMObject iDispatch;
	boolean ignoreNextMessage, ignoreAllMessages;
	Boolean canExecuteApplets;

	static final int OLECMDID_SHOWSCRIPTERROR = 40;
	static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'};
	static final String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$NON-NLS-1$

public WebSite(Composite parent, int style, String progId) {
	super(parent, style, progId);		
}

protected void createCOMInterfaces () {
	super.createCOMInterfaces();
	iDocHostUIHandler = new COMObject(new int[]{2, 0, 0, 4, 1, 5, 0, 0, 1, 1, 1, 3, 3, 2, 2, 1, 3, 2}){
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		public long /*int*/ method3(long /*int*/[] args) {return ShowContextMenu((int)/*64*/args[0], args[1], args[2], args[3]);}
		public long /*int*/ method4(long /*int*/[] args) {return GetHostInfo(args[0]);}
		public long /*int*/ method5(long /*int*/[] args) {return ShowUI((int)/*64*/args[0], args[1], args[2], args[3], args[4]);}
		public long /*int*/ method6(long /*int*/[] args) {return HideUI();}
		public long /*int*/ method7(long /*int*/[] args) {return UpdateUI();}
		public long /*int*/ method8(long /*int*/[] args) {return EnableModeless((int)/*64*/args[0]);}
		public long /*int*/ method9(long /*int*/[] args) {return OnDocWindowActivate((int)/*64*/args[0]);}
		public long /*int*/ method10(long /*int*/[] args) {return OnFrameWindowActivate((int)/*64*/args[0]);}
		public long /*int*/ method11(long /*int*/[] args) {return ResizeBorder(args[0], args[1], (int)/*64*/args[2]);}
		public long /*int*/ method12(long /*int*/[] args) {return TranslateAccelerator(args[0], args[1], (int)/*64*/args[2]);}
		public long /*int*/ method13(long /*int*/[] args) {return GetOptionKeyPath(args[0], (int)/*64*/args[1]);}
		public long /*int*/ method14(long /*int*/[] args) {return GetDropTarget(args[0], args[1]);}
		public long /*int*/ method15(long /*int*/[] args) {return GetExternal(args[0]);}
		public long /*int*/ method16(long /*int*/[] args) {return TranslateUrl((int)/*64*/args[0], args[1], args[2]);}		
		public long /*int*/ method17(long /*int*/[] args) {return FilterDataObject(args[0], args[1]);}
	};
	iDocHostShowUI = new COMObject(new int[]{2, 0, 0, 7, C.PTR_SIZEOF == 4 ? 7 : 6}){
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		public long /*int*/ method3(long /*int*/[] args) {return ShowMessage(args[0], args[1], args[2], (int)/*64*/args[3], args[4], (int)/*64*/args[5], args[6]);}
		public long /*int*/ method4(long /*int*/[] args) {
			if (args.length == 7) {
				return ShowHelp(args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5], args[6]);
			} else {
				return ShowHelp_64(args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], args[4], args[5]);
			}
		}
	};
	iServiceProvider = new COMObject(new int[]{2, 0, 0, 3}){
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		public long /*int*/ method3(long /*int*/[] args) {return QueryService(args[0], args[1], args[2]);}
	};
	iInternetSecurityManager = new COMObject(new int[]{2, 0, 0, 1, 1, 3, 4, 8, 7, 3, 3}){
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		public long /*int*/ method3(long /*int*/[] args) {return SetSecuritySite(args[0]);}
		public long /*int*/ method4(long /*int*/[] args) {return GetSecuritySite(args[0]);}
		public long /*int*/ method5(long /*int*/[] args) {return MapUrlToZone(args[0], args[1], (int)/*64*/args[2]);}
		public long /*int*/ method6(long /*int*/[] args) {return GetSecurityId(args[0], args[1], args[2], args[3]);}
		public long /*int*/ method7(long /*int*/[] args) {return ProcessUrlAction(args[0], (int)/*64*/args[1], args[2], (int)/*64*/args[3], args[4], (int)/*64*/args[5], (int)/*64*/args[6], (int)/*64*/args[7]);}
		public long /*int*/ method8(long /*int*/[] args) {return QueryCustomPolicy(args[0], args[1], args[2], args[3], args[4], (int)/*64*/args[5], (int)/*64*/args[6]);}
		public long /*int*/ method9(long /*int*/[] args) {return SetZoneMapping((int)/*64*/args[0], args[1], (int)/*64*/args[2]);}
		public long /*int*/ method10(long /*int*/[] args) {return GetZoneMappings((int)/*64*/args[0], args[1], (int)/*64*/args[2]);}
	};
	iOleCommandTarget = new COMObject(new int[]{2, 0, 0, 4, 5}) {
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		public long /*int*/ method2(long /*int*/[] args) {return Release();}		
		public long /*int*/ method3(long /*int*/[] args) {return QueryStatus(args[0], (int)/*64*/args[1], args[2], args[3]);}		
		public long /*int*/ method4(long /*int*/[] args) {return Exec(args[0], (int)/*64*/args[1], (int)/*64*/args[2], args[3], args[4]);}
	};
	iAuthenticate = new COMObject(new int[]{2, 0, 0, 3}){
		public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);}
		public long /*int*/ method1(long /*int*/[] args) {return AddRef();}
		public long /*int*/ method2(long /*int*/[] args) {return Release();}
		public long /*int*/ method3(long /*int*/[] args) {return Authenticate(args[0], args[1], args[2]);}
	};
	iDispatch = new COMObject (new int[] {2, 0, 0, 1, 3, 5, 8}) {
		public long /*int*/ method0 (long /*int*/[] args) {
			/* 
			 * IDispatch check must be done here instead of in the shared QueryInterface
			 * implementation, to avoid answering the superclass's IDispatch implementation
			 * instead of this one.
			 */
			GUID guid = new GUID ();
			COM.MoveMemory (guid, args[0], GUID.sizeof);
			if (COM.IsEqualGUID (guid, COM.IIDIDispatch)) {
				COM.MoveMemory (args[1], new long /*int*/[] {iDispatch.getAddress ()}, OS.PTR_SIZEOF);
				AddRef ();
				return COM.S_OK;
			}
			return QueryInterface (args[0], args[1]);
		}
		public long /*int*/ method1 (long /*int*/[] args) {return AddRef ();}
		public long /*int*/ method2 (long /*int*/[] args) {return Release ();}
		public long /*int*/ method3 (long /*int*/[] args) {return GetTypeInfoCount (args[0]);}
		public long /*int*/ method4 (long /*int*/[] args) {return GetTypeInfo ((int)/*64*/args[0], (int)/*64*/args[1], args[2]);}
		public long /*int*/ method5 (long /*int*/[] args) {return GetIDsOfNames ((int)/*64*/args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], args[4]);}
		public long /*int*/ method6 (long /*int*/[] args) {return Invoke ((int)/*64*/args[0], (int)/*64*/args[1], (int)/*64*/args[2], (int)/*64*/args[3], args[4], args[5], args[6], args[7]);}
	};
}

protected void disposeCOMInterfaces() {
	super.disposeCOMInterfaces();
	if (iDocHostUIHandler != null) {
		iDocHostUIHandler.dispose();
		iDocHostUIHandler = null;
	}
	if (iDocHostShowUI != null) {
		iDocHostShowUI.dispose();
		iDocHostShowUI = null;
	}
	if (iServiceProvider != null) {
		iServiceProvider.dispose();
		iServiceProvider = null;
	}
	if (iInternetSecurityManager != null) {
		iInternetSecurityManager.dispose();
		iInternetSecurityManager = null;
	}
	if (iOleCommandTarget != null) {
		iOleCommandTarget.dispose();
		iOleCommandTarget = null;
	}
	if (iAuthenticate != null) {
		iAuthenticate.dispose();
		iAuthenticate = null;
	}
	if (iDispatch != null) {
		iDispatch.dispose ();
		iDispatch = null;
	}
}

protected int AddRef() {
	/* Workaround for javac 1.1.8 bug */
	return super.AddRef();
}

protected int QueryInterface(long /*int*/ riid, long /*int*/ ppvObject) {
	int result = super.QueryInterface(riid, ppvObject);
	if (result == COM.S_OK) return result;
	if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
	GUID guid = new GUID();
	COM.MoveMemory(guid, riid, GUID.sizeof);
	if (COM.IsEqualGUID(guid, COM.IIDIDocHostUIHandler)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iDocHostUIHandler.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(guid, COM.IIDIDocHostShowUI)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iDocHostShowUI.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iServiceProvider.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
    if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) {
        COM.MoveMemory(ppvObject, new long /*int*/[] {iInternetSecurityManager.getAddress()}, OS.PTR_SIZEOF);
        AddRef();
        return COM.S_OK;
    }
	if (COM.IsEqualGUID(guid, COM.IIDIOleCommandTarget)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iOleCommandTarget.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	COM.MoveMemory(ppvObject, new long /*int*/[] {0}, OS.PTR_SIZEOF);
	return COM.E_NOINTERFACE;
}

/* IDocHostUIHandler */

int EnableModeless(int EnableModeless) {
	return COM.E_NOTIMPL;
}

int FilterDataObject(long /*int*/ pDO, long /*int*/ ppDORet) {
	return COM.E_NOTIMPL;
}

int GetDropTarget(long /*int*/ pDropTarget, long /*int*/ ppDropTarget) {
	return COM.E_NOTIMPL;
}

int GetExternal(long /*int*/ ppDispatch) {
	OS.MoveMemory (ppDispatch, new long /*int*/[] {iDispatch.getAddress()}, C.PTR_SIZEOF);
	AddRef ();
	return COM.S_OK;
}

int GetHostInfo(long /*int*/ pInfo) {
	int info = IE.DOCHOSTUIFLAG_THEME | IE.DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION;
	IE browser = (IE)((Browser)getParent().getParent()).webBrowser;
	if ((browser.style & SWT.BORDER) == 0) info |= IE.DOCHOSTUIFLAG_NO3DOUTERBORDER;
	DOCHOSTUIINFO uiInfo = new DOCHOSTUIINFO ();
	OS.MoveMemory(uiInfo, pInfo, DOCHOSTUIINFO.sizeof);
	uiInfo.dwFlags = info;
	OS.MoveMemory(pInfo, uiInfo, DOCHOSTUIINFO.sizeof);
	return COM.S_OK;
}

int GetOptionKeyPath(long /*int*/ pchKey, int dw) {
	return COM.E_NOTIMPL;
}

int HideUI() {
	return COM.E_NOTIMPL;
}

int OnDocWindowActivate(int fActivate) {
	return COM.E_NOTIMPL;
}

int OnFrameWindowActivate(int fActivate) {
	return COM.E_NOTIMPL;
}

protected int Release() {
	/* Workaround for javac 1.1.8 bug */
	return super.Release();
}

int ResizeBorder(long /*int*/ prcBorder, long /*int*/ pUIWindow, int fFrameWindow) {
	return COM.E_NOTIMPL;
}

int ShowContextMenu(int dwID, long /*int*/ ppt, long /*int*/ pcmdtReserved, long /*int*/ pdispReserved) {
	Browser browser = (Browser)getParent().getParent();
	Event event = new Event();
	POINT pt = new POINT();
	OS.MoveMemory(pt, ppt, POINT.sizeof);
	event.x = pt.x;
	event.y = pt.y;
	browser.notifyListeners(SWT.MenuDetect, event);
	if (!event.doit) return COM.S_OK;
	Menu menu = browser.getMenu();
	if (menu != null && !menu.isDisposed ()) {
		if (pt.x != event.x || pt.y != event.y) {
			menu.setLocation (event.x, event.y);
		}
		menu.setVisible (true);
		return COM.S_OK;
	}
	/* Show default IE popup menu */
	return COM.S_FALSE;
}

int ShowUI(int dwID, long /*int*/ pActiveObject, long /*int*/ pCommandTarget, long /*int*/ pFrame, long /*int*/ pDoc) {
	return COM.S_FALSE;
}

int TranslateAccelerator(long /*int*/ lpMsg, long /*int*/ pguidCmdGroup, int nCmdID) {
	/*
	* Feature in Internet Explorer.  By default the embedded Internet Explorer control runs
	* the Internet Explorer shortcuts (e.g. Ctrl+F for Find).  This overrides the shortcuts
	* defined by SWT.  The workaround is to forward the accelerator keys to the parent window
	* and have Internet Explorer ignore the ones handled by the parent window.
	*/
	Menu menubar = getShell().getMenuBar();
	if (menubar != null && !menubar.isDisposed() && menubar.isEnabled()) {
		Shell shell = menubar.getShell();
		long /*int*/ hwnd = shell.handle;
		long /*int*/ hAccel = OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
		if (hAccel != 0) {
			MSG msg = new MSG();
			OS.MoveMemory(msg, lpMsg, MSG.sizeof);
			if (OS.TranslateAccelerator(hwnd, hAccel, msg) != 0) return COM.S_OK;
		}
	}
	/*
	* By default the IE shortcuts are run.  However, the shortcuts below should not run
	* in this context.  The workaround is to block IE from handling these shortcuts by
	* answering COM.S_OK.
	* 
	* - F5 causes a refresh, which is not appropriate when rendering HTML from memory
	* - CTRL+L and CTRL+O show an Open Location dialog in IE8, which is undesirable and
	* can crash in some contexts
	* - CTRL+N opens a standalone IE, which is undesirable and can crash in some contexts
	*/
	int result = COM.S_FALSE;
	MSG msg = new MSG();
	OS.MoveMemory(msg, lpMsg, MSG.sizeof);
	if (msg.message == OS.WM_KEYDOWN) {
		switch ((int)/*64*/msg.wParam) {
			case OS.VK_F5:
				OleAutomation auto = new OleAutomation(this);
				int[] rgdispid = auto.getIDsOfNames(new String[] { "LocationURL" }); //$NON-NLS-1$
				Variant pVarResult = auto.getProperty(rgdispid[0]);
				auto.dispose();
				if (pVarResult != null) {
					if (pVarResult.getType() == OLE.VT_BSTR) {
						String url = pVarResult.getString();
						if (url.equals(IE.ABOUT_BLANK)) result = COM.S_OK;
					}
					pVarResult.dispose();
				}
				break;
			case OS.VK_TAB:
				/* 
				 * Do not interfere with tab traversal since it's not known
				 * if it will be within IE or out to another Control.
				 */
				break;
			case OS.VK_UP:
			case OS.VK_DOWN:
			case OS.VK_LEFT:
			case OS.VK_RIGHT:
			case OS.VK_HOME:
			case OS.VK_END:
			case OS.VK_PRIOR:
			case OS.VK_NEXT:
				/* Do not translate/consume IE's keys for scrolling content. */
				break;
			case OS.VK_BACK:
			case OS.VK_RETURN:
				/*
				* Translating OS.VK_BACK or OS.VK_RETURN results in the native control
				* handling them twice (eg.- inserting two lines instead of one).  So
				* these keys are not translated here, and instead are explicitly handled
				* in the keypress handler.
				*/
				break;
			case OS.VK_L:
			case OS.VK_N:
			case OS.VK_O:
				if (OS.GetKeyState (OS.VK_CONTROL) < 0 && OS.GetKeyState (OS.VK_MENU) >= 0 && OS.GetKeyState (OS.VK_SHIFT) >= 0) {
					if (msg.wParam == OS.VK_N || IE.IEVersion >= 8) {
						frame.setData(CONSUME_KEY, "false"); //$NON-NLS-1$
						result = COM.S_OK;
						break;
					}
				}
				// FALL THROUGH
			default:
				OS.TranslateMessage(msg);
				frame.setData(CONSUME_KEY, "true"); //$NON-NLS-1$
				break;
		}
	}

	switch (msg.message) {
		case OS.WM_KEYDOWN:
		case OS.WM_KEYUP: {
			if (!OS.IsWinCE) {
				boolean isAccent = false;
				switch ((int)/*64*/msg.wParam) {
					case OS.VK_SHIFT:
					case OS.VK_MENU:
					case OS.VK_CONTROL:
					case OS.VK_CAPITAL:
					case OS.VK_NUMLOCK:
					case OS.VK_SCROLL:
						break;
					default: {
						/*
						* Bug in Windows. The high bit in the result of MapVirtualKey() on
						* Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
						* They should both be bit 32.  The fix is to test the right bit.
						*/
						int mapKey = OS.MapVirtualKey ((int)/*64*/msg.wParam, 2);
						if (mapKey != 0) {
							isAccent = (mapKey & (OS.IsWinNT ? 0x80000000 : 0x8000)) != 0;
							if (!isAccent) {
								for (int i=0; i<ACCENTS.length; i++) {
									int value = OS.VkKeyScan (ACCENTS [i]);
									if (value != -1 && (value & 0xFF) == msg.wParam) {
										int state = value >> 8;
										if ((OS.GetKeyState (OS.VK_SHIFT) < 0) == ((state & 0x1) != 0) &&
											(OS.GetKeyState (OS.VK_CONTROL) < 0) == ((state & 0x2) != 0) &&
											(OS.GetKeyState (OS.VK_MENU) < 0) == ((state & 0x4) != 0)) {
												if ((state & 0x7) != 0) isAccent = true;
												break;
										}
									}
								}
							}
						}
						break;
					}
				}
				if (isAccent) result = COM.S_OK;
			}
		}
	}
	return result;
}

int TranslateUrl(int dwTranslate, long /*int*/ pchURLIn, long /*int*/ ppchURLOut) {
	return COM.E_NOTIMPL;
}

int UpdateUI() {
	return COM.E_NOTIMPL;
}

/* IDocHostShowUI */

int ShowMessage(long /*int*/ hwnd, long /*int*/ lpstrText, long /*int*/ lpstrCaption, int dwType, long /*int*/ lpstrHelpFile, int dwHelpContext, long /*int*/ plResult) {
	boolean ignore = ignoreNextMessage || ignoreAllMessages;
	ignoreNextMessage = false;
	return ignore ? COM.S_OK : COM.S_FALSE;
}

int ShowHelp_64(long /*int*/ hwnd, long /*int*/ pszHelpFile, int uCommand, int dwData, long pt, long /*int*/ pDispatchObjectHit) {
	POINT point = new POINT();
	OS.MoveMemory(point, new long[]{pt}, 8);
	return ShowHelp(hwnd, pszHelpFile, uCommand, dwData, point.x, point.y, pDispatchObjectHit);
}

/* Note.  One of the arguments of ShowHelp is a POINT struct and not a pointer to a POINT struct. Because
 * of the way Callback gets int parameters from a va_list of C arguments 2 integer arguments must be declared,
 * ptMouse_x and ptMouse_y. Otherwise the Browser crashes when the user presses F1 to invoke
 * the help.
 */
int ShowHelp(long /*int*/ hwnd, long /*int*/ pszHelpFile, int uCommand, int dwData, int ptMouse_x, int ptMouse_y, long /*int*/ pDispatchObjectHit) {
	Browser browser = (Browser)getParent().getParent();
	Event event = new Event();
	event.type = SWT.Help;
	event.display = getDisplay();
	event.widget = browser;
	Shell shell = browser.getShell();
	Control control = browser;
	do {
		if (control.isListening(SWT.Help)) {
			control.notifyListeners(SWT.Help, event);
			break;
		}
		if (control == shell) break;
		control = control.getParent();
	} while (true);
	return COM.S_OK;
}

/* IServiceProvider */

int QueryService(long /*int*/ guidService, long /*int*/ riid, long /*int*/ ppvObject) {
	if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
	GUID guid = new GUID();
	COM.MoveMemory(guid, riid, GUID.sizeof);
	if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iInternetSecurityManager.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(guid, COM.IIDIAuthenticate)) {
		COM.MoveMemory(ppvObject, new long /*int*/[] {iAuthenticate.getAddress()}, OS.PTR_SIZEOF);
		AddRef();
		return COM.S_OK;
	}
	COM.MoveMemory(ppvObject, new long /*int*/[] {0}, OS.PTR_SIZEOF);
	return COM.E_NOINTERFACE;
}

/* IInternetSecurityManager */

int SetSecuritySite(long /*int*/ pSite) {
	return IE.INET_E_DEFAULT_ACTION;
}

int GetSecuritySite(long /*int*/ ppSite) {
	return IE.INET_E_DEFAULT_ACTION;
}

int MapUrlToZone(long /*int*/ pwszUrl, long /*int*/ pdwZone, int dwFlags) {
	/*
	* Feature in IE.  HTML rendered in memory does not enable local links
	* but the same HTML document loaded through a local file is permitted
	* to follow local links.  The workaround is to return URLZONE_INTRANET
	* instead of the default value URLZONE_LOCAL_MACHINE.
	*/
	IE ie = (IE)((Browser)getParent().getParent()).webBrowser;
	/*
	* For some reason IE8 invokes this function after the Browser has
	* been disposed.  To detect this case check for ie.auto != null. 
	*/
	if (ie.auto != null && ie.isAboutBlank && !ie.untrustedText) {
		COM.MoveMemory(pdwZone, new int[] {IE.URLZONE_INTRANET}, 4);
		return COM.S_OK;
	}
	return IE.INET_E_DEFAULT_ACTION;
}

int GetSecurityId(long /*int*/ pwszUrl, long /*int*/ pbSecurityId, long /*int*/ pcbSecurityId, long /*int*/ dwReserved) {
	return IE.INET_E_DEFAULT_ACTION;
}

int ProcessUrlAction(long /*int*/ pwszUrl, int dwAction, long /*int*/ pPolicy, int cbPolicy, long /*int*/ pContext, int cbContext, int dwFlags, int dwReserved) {
	ignoreNextMessage = false;

	/*
	* If the current page is about:blank and is trusted then
	* override default zone elevation settings to allow the action.  
	*/
	if (dwAction == IE.URLACTION_FEATURE_ZONE_ELEVATION) {
	    IE ie = (IE)((Browser)getParent().getParent()).webBrowser;
	    if (ie.auto != null && ie._getUrl().startsWith(IE.ABOUT_BLANK) && !ie.untrustedText) {
			if (cbPolicy >= 4) COM.MoveMemory(pPolicy, new int[] {IE.URLPOLICY_ALLOW}, 4);
			return COM.S_OK;
	    }
	}

	int policy = IE.INET_E_DEFAULT_ACTION;

	if (dwAction >= IE.URLACTION_JAVA_MIN && dwAction <= IE.URLACTION_JAVA_MAX) {
		if (canExecuteApplets ()) {
			policy = IE.URLPOLICY_JAVA_LOW;
		} else {
			policy = IE.URLPOLICY_JAVA_PROHIBIT;
			ignoreNextMessage = true;
		}
	}
	if (dwAction == IE.URLACTION_ACTIVEX_RUN) {
		GUID guid = new GUID();
		COM.MoveMemory(guid, pContext, GUID.sizeof);
		if (COM.IsEqualGUID(guid, COM.IIDJavaBeansBridge) && !canExecuteApplets ()) {
			policy = IE.URLPOLICY_DISALLOW;
			ignoreNextMessage = true;
		}
		if (COM.IsEqualGUID(guid, COM.IIDShockwaveActiveXControl)) {
			policy = IE.URLPOLICY_DISALLOW;
			ignoreNextMessage = true;
		}
	}
	if (dwAction == IE.URLACTION_SCRIPT_RUN) {
		IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
		policy = browser.jsEnabled ? IE.URLPOLICY_ALLOW : IE.URLPOLICY_DISALLOW;
	}

	if (policy == IE.INET_E_DEFAULT_ACTION) return IE.INET_E_DEFAULT_ACTION;
	if (cbPolicy >= 4) COM.MoveMemory(pPolicy, new int[] {policy}, 4);
	return policy == IE.URLPOLICY_ALLOW ? COM.S_OK : COM.S_FALSE;
}

boolean canExecuteApplets () {
	/*
	* Executing an applet in embedded IE will crash if IE's Java plug-in
	* launches its jre in IE's process, because this new jre conflicts
	* with the one running eclipse.  These cases need to be avoided by
	* vetoing the running of applets.
	* 
	* However as of Sun jre 1.6u10, applets can be launched in a separate
	* process, which avoids the conflict with the jre running eclipse.
	* Therefore if this condition is detected, and if the required jar 
	* libraries are available, then applets can be executed. 
	*/

	/* 
	* executing applets with IE6 embedded can crash, so do not
	* attempt this if the version is less than IE7
	*/
	if (IE.IEVersion < 7) return false;

	if (canExecuteApplets == null) {
		WebBrowser webBrowser = ((Browser)getParent ().getParent ()).webBrowser;
		String script = "try {var element = document.createElement('object');element.classid='clsid:CAFEEFAC-DEC7-0000-0000-ABCDEFFEDCBA';return element.object.isPlugin2();} catch (err) {};return false;"; //$NON-NLS-1$
		canExecuteApplets = ((Boolean)webBrowser.evaluate (script)); 
		if (canExecuteApplets.booleanValue ()) {
			try {
				Class.forName ("sun.plugin2.main.server.IExplorerPlugin"); /* plugin.jar */	//$NON-NLS-1$
				Class.forName ("com.sun.deploy.services.Service"); /* deploy.jar */	//$NON-NLS-1$
				Class.forName ("com.sun.javaws.Globals"); /* javaws.jar */	//$NON-NLS-1$
			} catch (ClassNotFoundException e) {
				/* one or more of the required jar libraries are not available */
				canExecuteApplets = Boolean.FALSE;
			}
		}
	}
	return canExecuteApplets.booleanValue ();
}

int QueryCustomPolicy(long /*int*/ pwszUrl, long /*int*/ guidKey, long /*int*/ ppPolicy, long /*int*/ pcbPolicy, long /*int*/ pContext, int cbContext, int dwReserved) {
	return IE.INET_E_DEFAULT_ACTION;
}

int SetZoneMapping(int dwZone, long /*int*/ lpszPattern, int dwFlags) {
	return IE.INET_E_DEFAULT_ACTION;
}

int GetZoneMappings(int dwZone, long /*int*/ ppenumString, int dwFlags) {
	return COM.E_NOTIMPL;
}

/* IOleCommandTarget */
int QueryStatus(long /*int*/ pguidCmdGroup, int cCmds, long /*int*/ prgCmds, long /*int*/ pCmdText) {
	return COM.E_NOTSUPPORTED;
}

int Exec(long /*int*/ pguidCmdGroup, int nCmdID, int nCmdExecOpt, long /*int*/ pvaIn, long /*int*/ pvaOut) {
	if (pguidCmdGroup != 0) {
		GUID guid = new GUID();
		COM.MoveMemory(guid, pguidCmdGroup, GUID.sizeof);

		/*
		* If a javascript error occurred then suppress IE's default script error dialog.
		*/
		if (COM.IsEqualGUID(guid, COM.CGID_DocHostCommandHandler)) {
			if (nCmdID == OLECMDID_SHOWSCRIPTERROR) return COM.S_OK;
		}

		/*
		* Bug in Internet Explorer.  OnToolBar TRUE is also fired when any of the 
		* address bar or menu bar are requested but not the tool bar.  A workaround
		* has been posted by a Microsoft developer on the public webbrowser_ctl
		* newsgroup. The workaround is to implement the IOleCommandTarget interface
		* to test the argument of an undocumented command.
		*/
		if (nCmdID == 1 && COM.IsEqualGUID(guid, COM.CGID_Explorer) && ((nCmdExecOpt & 0xFFFF) == 0xA)) {
			IE browser = (IE)((Browser)getParent().getParent()).webBrowser;
			browser.toolBar = (nCmdExecOpt & 0xFFFF0000) != 0;
		}
	}
	return COM.E_NOTSUPPORTED;
}

/* IAuthenticate */

int Authenticate (long /*int*/ hwnd, long /*int*/ szUsername, long /*int*/ szPassword) {
	IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
	for (int i = 0; i < browser.authenticationListeners.length; i++) {
		AuthenticationEvent event = new AuthenticationEvent (browser.browser);
		event.location = browser.lastNavigateURL;
		browser.authenticationListeners[i].authenticate (event);
		if (!event.doit) return COM.E_ACCESSDENIED;
		if (event.user != null && event.password != null) {
			TCHAR user = new TCHAR (0, event.user, true);
			int size = user.length () * TCHAR.sizeof;
			long /*int*/ userPtr = COM.CoTaskMemAlloc (size);
			OS.MoveMemory (userPtr, user, size);
			TCHAR password = new TCHAR (0, event.password, true);
			size = password.length () * TCHAR.sizeof;
			long /*int*/ passwordPtr = COM.CoTaskMemAlloc (size);
			OS.MoveMemory (passwordPtr, password, size);
			C.memmove (hwnd, new long /*int*/[] {0}, C.PTR_SIZEOF);
			C.memmove (szUsername, new long /*int*/[] {userPtr}, C.PTR_SIZEOF);
			C.memmove (szPassword, new long /*int*/[] {passwordPtr}, C.PTR_SIZEOF);
			return COM.S_OK;
		}
	}

	/* no listener handled the challenge, so defer to the native dialog */
	C.memmove (hwnd, new long /*int*/[] {getShell().handle}, C.PTR_SIZEOF);
	return COM.S_OK;
}

/* IDispatch */

int GetTypeInfoCount (long /*int*/ pctinfo) {
	C.memmove (pctinfo, new int[] {0}, 4);
	return COM.S_OK;
}

int GetTypeInfo (int iTInfo, int lcid, long /*int*/ ppTInfo) {
	return COM.S_OK;
}

int GetIDsOfNames (int riid, long /*int*/ rgszNames, int cNames, int lcid, long /*int*/ rgDispId) {
    long /*int*/[] ptr = new long /*int*/[1];
    OS.MoveMemory (ptr, rgszNames, C.PTR_SIZEOF);
    int length = OS.wcslen (ptr[0]);
    char[] buffer = new char[length];
    OS.MoveMemory (buffer, ptr[0], length * 2);
    String functionName = String.valueOf (buffer);
    int result = COM.S_OK; 
    int[] ids = new int[cNames];	/* DISPIDs */
    if (functionName.equals ("callJava")) { //$NON-NLS-1$
	    for (int i = 0; i < cNames; i++) {
	        ids[i] = i + 1;
	    }
    } else {
    	result = COM.DISP_E_UNKNOWNNAME;
	    for (int i = 0; i < cNames; i++) {
	        ids[i] = COM.DISPID_UNKNOWN;
	    }
    }
    OS.MoveMemory (rgDispId, ids, cNames * 4);
	return result;
}

int Invoke (int dispIdMember, long /*int*/ riid, int lcid, int dwFlags, long /*int*/ pDispParams, long /*int*/ pVarResult, long /*int*/ pExcepInfo, long /*int*/ pArgErr) {
	IE ie = (IE)((Browser)getParent ().getParent ()).webBrowser;
	Hashtable functions = ie.functions;
	if (functions == null) {
		if (pVarResult != 0) {
			COM.MoveMemory (pVarResult, new long /*int*/[] {0}, C.PTR_SIZEOF);
		}
		return COM.S_OK;
	}

	DISPPARAMS dispParams = new DISPPARAMS ();
	COM.MoveMemory (dispParams, pDispParams, DISPPARAMS.sizeof);
	if (dispParams.cArgs != 3) {
		if (pVarResult != 0) {
			COM.MoveMemory (pVarResult, new long /*int*/[] {0}, C.PTR_SIZEOF);
		}
		return COM.S_OK;
	}

	long /*int*/ ptr = dispParams.rgvarg + 2 * Variant.sizeof;
	Variant variant = Variant.win32_new (ptr);
	if (variant.getType () != COM.VT_I4) {
		variant.dispose ();
		if (pVarResult != 0) {
			COM.MoveMemory (pVarResult, new long /*int*/[] {0}, C.PTR_SIZEOF);
		}
		return COM.S_OK;
	}
	int index = variant.getInt ();
	variant.dispose ();
	if (index <= 0) {
		if (pVarResult != 0) {
			COM.MoveMemory (pVarResult, new long /*int*/[] {0}, C.PTR_SIZEOF);
		}
		return COM.S_OK;
	}

	ptr = dispParams.rgvarg + Variant.sizeof;
	variant = Variant.win32_new (ptr);
	int type = variant.getType ();
	if (type != COM.VT_BSTR) {
		variant.dispose ();
		if (pVarResult != 0) {
			COM.MoveMemory (pVarResult, new long /*int*/[] {0}, C.PTR_SIZEOF);
		}
		return COM.S_OK;
	}
	String token = variant.getString ();
	variant.dispose ();

	variant = Variant.win32_new (dispParams.rgvarg);
	Object key = new Integer (index);
	BrowserFunction function = (BrowserFunction)functions.get (key);
	Object returnValue = null;
	if (function != null && token.equals (function.token)) {
		try {
			Object temp = convertToJava (variant);
			if (temp instanceof Object[]) {
				Object[] args = (Object[])temp;
				try {
					returnValue = function.function (args);
				} catch (Exception e) {
					/* exception during function invocation */
					returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
				}
			}
		} catch (IllegalArgumentException e) {
			/* invalid argument value type */
			if (function.isEvaluate) {
				/* notify the function so that a java exception can be thrown */
				function.function (new String[] {WebBrowser.CreateErrorString (new SWTException (SWT.ERROR_INVALID_RETURN_VALUE).getLocalizedMessage ())});
			}
			returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
		}
	}
	variant.dispose ();

	if (pVarResult != 0) {
		try {
			variant = convertToJS (returnValue);
		} catch (SWTException e) {
			/* invalid return value type */
			variant = convertToJS (WebBrowser.CreateErrorString (e.getLocalizedMessage ()));
		}
		Variant.win32_copy (pVarResult, variant);
		variant.dispose ();
	}
	return COM.S_OK;
}

Object convertToJava (Variant variant) {
	switch (variant.getType ()) {
		case OLE.VT_EMPTY:
		case OLE.VT_NULL: return null;
		case OLE.VT_BSTR: return variant.getString ();
		case OLE.VT_BOOL: return new Boolean (variant.getBoolean ());
		case OLE.VT_I2:
		case OLE.VT_I4:
		case OLE.VT_I8:
		case OLE.VT_R4:
		case OLE.VT_R8:
			return new Double (variant.getDouble ());
		case OLE.VT_DISPATCH: {
			Object[] args = null;
			OleAutomation auto = variant.getAutomation ();
			TYPEATTR typeattr = auto.getTypeInfoAttributes ();
			if (typeattr != null) {
				GUID guid = new GUID ();
				guid.Data1 = typeattr.guid_Data1;
				guid.Data2 = typeattr.guid_Data2;
				guid.Data3 = typeattr.guid_Data3;
				guid.Data4 = typeattr.guid_Data4;
				if (COM.IsEqualGUID (guid, COM.IIDIJScriptTypeInfo)) {
					int[] rgdispid = auto.getIDsOfNames (new String[] {"length"}); //$NON-NLS-1$
					if (rgdispid != null) {
						Variant varLength = auto.getProperty (rgdispid[0]);
						int length = varLength.getInt ();
						varLength.dispose ();
						args = new Object[length];
						for (int i = 0; i < length; i++) {
							rgdispid = auto.getIDsOfNames (new String[] {String.valueOf (i)});
							if (rgdispid != null) {
								Variant current = auto.getProperty (rgdispid[0]);
								try {
									args[i] = convertToJava (current);
									current.dispose ();
								} catch (IllegalArgumentException e) {
									/* invalid argument value type */
									current.dispose ();
									auto.dispose ();
									throw e;
								}
							}
						}
					}
				} else {
					auto.dispose ();
					SWT.error (SWT.ERROR_INVALID_ARGUMENT);
				}
			}
			auto.dispose ();
			return args;
		}
	}
	SWT.error (SWT.ERROR_INVALID_ARGUMENT);
	return null;
}

Variant convertToJS (Object value) {
	if (value == null) {
		return Variant.NULL;
	}
	if (value instanceof String) {
		return new Variant ((String)value);
	}
	if (value instanceof Boolean) {
		return new Variant (((Boolean)value).booleanValue ());
	}
	if (value instanceof Number) {
		return new Variant (((Number)value).doubleValue ());
	}
	if (value instanceof Object[]) {
		/* get IHTMLDocument2 */
		IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
		OleAutomation auto = browser.auto;
		int[] rgdispid = auto.getIDsOfNames (new String[] {"Document"}); //$NON-NLS-1$
		if (rgdispid == null) return new Variant ();
		Variant pVarResult = auto.getProperty (rgdispid[0]);
		if (pVarResult == null) return new Variant ();
		if (pVarResult.getType () == COM.VT_EMPTY) {
			pVarResult.dispose ();
			return new Variant ();
		}
		OleAutomation document = pVarResult.getAutomation ();
		pVarResult.dispose ();

		/* get IHTMLWindow2 */
		rgdispid = document.getIDsOfNames (new String[] {"parentWindow"}); //$NON-NLS-1$
		if (rgdispid == null) {
			document.dispose ();
			return new Variant ();
		}
		pVarResult = document.getProperty (rgdispid[0]);
		if (pVarResult == null || pVarResult.getType () == COM.VT_EMPTY) {
			if (pVarResult != null) pVarResult.dispose ();
			document.dispose ();
			return new Variant ();	
		}
		OleAutomation ihtmlWindow2 = pVarResult.getAutomation ();
		pVarResult.dispose ();
		document.dispose ();

		/* create a new JS array to be returned */
		rgdispid = ihtmlWindow2.getIDsOfNames (new String[] {"Array"}); //$NON-NLS-1$
		if (rgdispid == null) {
			ihtmlWindow2.dispose ();
			return new Variant ();
		}
		Variant arrayType = ihtmlWindow2.getProperty (rgdispid[0]);
		ihtmlWindow2.dispose ();
		IDispatch arrayTypeDispatch = arrayType.getDispatch ();
		long /*int*/[] result = new long /*int*/[1];
		int rc = arrayTypeDispatch.QueryInterface (COM.IIDIDispatchEx, result);
		arrayType.dispose ();
		if (rc != COM.S_OK) return new Variant ();

		IDispatchEx arrayTypeDispatchEx = new IDispatchEx (result[0]);
		result[0] = 0;
		long /*int*/ resultPtr = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
		DISPPARAMS params = new DISPPARAMS ();
		rc = arrayTypeDispatchEx.InvokeEx (COM.DISPID_VALUE, COM.LOCALE_USER_DEFAULT, COM.DISPATCH_CONSTRUCT, params, resultPtr, null, 0);
		if (rc != COM.S_OK) {
			OS.GlobalFree (resultPtr);
			return new Variant ();	
		}
		Variant array = Variant.win32_new (resultPtr);
		OS.GlobalFree (resultPtr);

		/* populate the array */
		Object[] arrayValue = (Object[])value;
		int length = arrayValue.length;
		auto = array.getAutomation ();
		int[] rgdispids = auto.getIDsOfNames (new String[] {"push"}); //$NON-NLS-1$
		if (rgdispids != null) {
			for (int i = 0; i < length; i++) {
				Object currentObject = arrayValue[i];
				try {
					Variant variant = convertToJS (currentObject);
					auto.invoke (rgdispids[0], new Variant[] {variant});
					variant.dispose ();
				} catch (SWTException e) {
					/* invalid return value type */
					auto.dispose ();
					array.dispose ();
					throw e;
				}
			}
		}
		auto.dispose ();
		return array;
	}
	SWT.error (SWT.ERROR_INVALID_RETURN_VALUE);
	return null;
}

}
