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.
- Create a Web page that is named Mysecurepage.htm.
The content of the Web page is irrelevant. - Place the Web page in a secure directory that is named Mysecuredirectory, with basic authentication on a Web server (Mysecureserver).
- Create a default CHtmlView-based MFC application with multiple-document interface (MDI) or single-document interface (SDI).
- 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;
}
-
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;
}
-
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;
}
-
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);
}
-
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.