Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

BUG: Implementation of IAuthenticate to Bypass the Username or Password Dialog Box May Fail


Symptoms

When you host the Web Browser control and you implement the IAuthenticate interface to programmatically bypass the authentication process, sometimes Internet Explorer may not call the Authenticate function, which causes an authentication dialog to appear.

↑ Back to the top


Cause

This bug prevents Internet Explorer from calling Authenticate when MSHTML is not the current Active Document server. You can observe this bug when you initially move to a Hypertext Markup Language (HTML) page or when you move to an HTML page from an Active Document server other than MSHTML, such as a Microsoft Office document Active Document server or a Visual Basic Document (VBD) Active Document server.

↑ Back to the top


Resolution

You can work around the bug if you move to about:blank before you move to the secure page. You can also move to a non-secure page, which redirects you to the secure page.

↑ Back to the top


Status

Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

↑ Back to the top


More information

Internet Explorer obtains the IAuthenticate interface through the IServiceProvider::QueryService method. When the bug occurs, Internet Explorer does not ask for the IAuthenticate interface. Therefore, the Authenticate method cannot be called.

Steps to Reproduce the Behavior

Note: You must be familiar with Microsoft Foundation Classes (MFC) to understand the following steps.
  1. Create a Web page that is named Mysecurepage.htm.

    The content of the Web page is irrelevant.
  2. Place the Web page in a secure directory that is named Mysecuredirectory, with basic authentication on a Web server (Mysecureserver).
  3. Create a default CHtmlView-based MFC application with multiple-document interface (MDI) or single-document interface (SDI).
  4. Modify the MFC program to provide a custom control site object by overriding the COleControlSite class.

    You can read the following Microsoft KnowledgeBase article to obtain information about override of the MFC default control containment:
    HOWTO: Override the MFC Default Control Containment
    196835
    A sample of how the code may appear follows: Header file:
    #if !defined(MYCONTROLSITEHEADER)
    #define MYCONTROLSITEHEADER
    
    #undef AFX_DATA
    #define AFX_DATA AFX_DATA_IMPORT
    #include <..\src\occimpl.h>
    #undef AFX_DATA
    #define AFX_DATA AFX_DATA_EXPORT
    
    class CCustomControlSite : public COleControlSite
    {
    public:
    	CCustomControlSite::CCustomControlSite(COleControlContainer* pCtrlCont) :
    		COleControlSite(pCtrlCont)
    	{
    	}
    };
    
    class CMyOccManager : public COccManager
    {
    public:
    	CMyOccManager() {}
    
    	virtual COleControlSite* CreateSite(COleControlContainer* pCtrlCont)
    	{
    		// advanced control container override
    		return new CCustomControlSite(pCtrlCont);
    	}
    };
    
    #endif
    					
    Implementation files:
    CMyOccManager theManager;
    
    BOOL CMyApp::InitInstance()
    {
    	AfxEnableControlContainer(&theManager);
    ...
    					

    BOOL CReproView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
    {
    	// create the view window itself
    	m_pCreateContext = pContext;
    	if (!CView::Create(lpszClassName, lpszWindowName,
    				dwStyle, rect, pParentWnd,  nID, pContext))
    	{
    		return FALSE;
    	}
    
    	RECT rectClient;
    	GetClientRect(&rectClient);
    
    	// create the control window
    	// AFX_IDW_PANE_FIRST is a safe but arbitrary ID
    	if (!m_wndBrowser.CreateControl(CLSID_WebBrowser, lpszWindowName,
    				WS_VISIBLE | WS_CHILD, rectClient, this, AFX_IDW_PANE_FIRST))
    	{
    		DestroyWindow();
    		return FALSE;
    	}
    
    	LPUNKNOWN lpUnk = m_wndBrowser.GetControlUnknown();
    	HRESULT hr = lpUnk->QueryInterface(IID_IWebBrowser2, (void**) &m_pBrowserApp);
    	if (!SUCCEEDED(hr))
    	{
    		m_pBrowserApp = NULL;
    		m_wndBrowser.DestroyWindow();
    		DestroyWindow();
    		return FALSE;
    	}
    
    	return TRUE;
    }
    					
  5. Header file:Add code to implement the IServiceProvider interface in the custom COleControlSite class you just implemented.

    A sample of how the header file and the implementation file may appear follows: Header file:
    class CCustomControlSite : public COleControlSite
    {
    public:
    	CCustomControlSite::CCustomControlSite(COleControlContainer* pCtrlCont) :
    		COleControlSite(pCtrlCont)
    	{
    	}
    
    protected:
    
    	DECLARE_INTERFACE_MAP()
    
    	// ... other stuff
    
    	/////////////////////////////////////// 
    	//// Implement IServiceProvider
    	BEGIN_INTERFACE_PART(ServiceProvider, IServiceProvider)
    	STDMETHOD(QueryService)(REFGUID,REFIID,void**);
    	END_INTERFACE_PART(ServiceProvider)
    };
    					
    Implementation file:
    BEGIN_INTERFACE_MAP(CCustomControlSite, COleControlSite)
    	INTERFACE_PART(CCustomControlSite, IID_IServiceProvider, ServiceProvider)
    END_INTERFACE_MAP()
    
    ///////////////////////////////////////////////////////////// 
    // ServiceProvider Methods
    ULONG FAR EXPORT CCustomControlSite::XServiceProvider::AddRef()
    {
    	METHOD_PROLOGUE(CCustomControlSite, ServiceProvider)
    	return pThis->ExternalAddRef();
    }
    
    ULONG FAR EXPORT CCustomControlSite::XServiceProvider::Release()
    {                            
    	METHOD_PROLOGUE(CCustomControlSite, ServiceProvider)
    	return pThis->ExternalRelease();
    }
    
    HRESULT FAR EXPORT CCustomControlSite::XServiceProvider::QueryInterface(REFIID riid, 
    	void** ppvObj)
    {
    	METHOD_PROLOGUE(CCustomControlSite, ServiceProvider)
    	HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);
    	return hr;
    }
    STDMETHODIMP CCustomControlSite::XServiceProvider::QueryService(REFGUID guidService,  
    	REFIID riid,
    	void** ppvObject)
    {
    	if (guidService == IID_IAuthenticate &&
    		riid == IID_IAuthenticate)
    	{
    		METHOD_PROLOGUE(CCustomControlSite, ServiceProvider);
    		HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObject);
    		return hr;
    	}
    	else
    	{
    		*ppvObject = NULL;
    
    	}
    	return E_NOINTERFACE;
    }
    					
  6. Header file:Add code to implement the IAuthenicate interface in the custom COleControlSite class.

    A sample of how the header file and the implementation file may appear follows: Header file:
    class CCustomControlSite : public COleControlSite
    {
    public:
    	CCustomControlSite::CCustomControlSite(COleControlContainer* pCtrlCont) :
    		COleControlSite(pCtrlCont)
    	{
    	}
    
    protected:
    
    	DECLARE_INTERFACE_MAP()
    
    	// ... other stuff
    
    	/////////////////////////////////////// 
    	//// Implement IAuthenticate
    	BEGIN_INTERFACE_PART(Authenticate, IAuthenticate)
    	STDMETHOD(Authenticate)(HWND*, LPWSTR*, LPWSTR*);
    	END_INTERFACE_PART(Authenticate)
    };
    					
    Implementation file:
    BEGIN_INTERFACE_MAP(CCustomControlSite, COleControlSite)
    	INTERFACE_PART(CCustomControlSite, IID_IServiceProvider, ServiceProvider)
    	INTERFACE_PART(CCustomControlSite, IID_IAuthenticate, Authenticate)
    END_INTERFACE_MAP()
    
    // 
    // IAuthenticate
    // 
    ULONG FAR EXPORT CCustomControlSite::XAuthenticate::AddRef()
    {
    	METHOD_PROLOGUE(CCustomControlSite, Authenticate)
    	return pThis->ExternalAddRef();
    }
    
    ULONG FAR EXPORT CCustomControlSite::XAuthenticate::Release()
    {                            
    	METHOD_PROLOGUE(CCustomControlSite, Authenticate)
    	return pThis->ExternalRelease();
    }
    
    HRESULT FAR EXPORT CCustomControlSite::XAuthenticate::QueryInterface(REFIID
    	riid, void **ppvObj)
    {
    	METHOD_PROLOGUE(CCustomControlSite, Authenticate)
    	HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);
    	return hr;
    }
    
    HRESULT FAR EXPORT CCustomControlSite::XAuthenticate::Authenticate(
    	/* [out] */ HWND *phwnd,
    	/* [out] */ LPWSTR *pszUsername,
    	/* [out] */ LPWSTR *pszPassword) 
    {
    	USES_CONVERSION;
    	METHOD_PROLOGUE(CCustomControlSite, Authenticate)
    
    	char* userName = "mydomain\\myuserid";
    	char* password = "mysecretpassword";
    	*phwnd = NULL;
    	long size = (strlen(userName)+1)*sizeof(WCHAR);
    	*pszUsername = (LPWSTR)::CoTaskMemAlloc(size);
    	memcpy(*pszUsername, T2W(userName), size);
    	size = (strlen(password)+1)*sizeof(WCHAR);
    	*pszPassword = (LPWSTR)::CoTaskMemAlloc(size);
    	memcpy(*pszPassword, T2W(password), size);
    	return S_OK;
    }
    					
  7. Header file:Add code to move to the secure page.

    A sample that uses the Navigate method follows:
    void CQ320153View::OnInitialUpdate()
    {
    	CHtmlView::OnInitialUpdate();
    
    	// Navigate2(_T("about:blank"),NULL,NULL); // call this for workaround
    	Navigate2(_T("http://myserver/mysecuredirectory/mysecurepage.htm"),NULL,NULL);
    }
    					
  8. Header file:Build the project and run the program.

    Notice the prompt for the authentication dialog. The prompt disappears if you comment out the code to move to about:blank.

↑ Back to the top


Article Info
Article ID : 320153
Revision : 2
Created on : 1/1/0001
Published on : 1/1/0001
Exists online : False
Views : 376