Microsoft KB Archive/320153

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

Article ID: 320153

Article Last Modified on 12/3/2002

-

APPLIES TO


 * Microsoft Internet Explorer (Programming)

-



This article was previously published under Q320153



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.



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.



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.



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



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.  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:


 * 1) if !defined(MYCONTROLSITEHEADER)
 * 2) define MYCONTROLSITEHEADER


 * 1) undef AFX_DATA
 * 2) define AFX_DATA AFX_DATA_IMPORT
 * 3) include <..\src\occimpl.h>
 * 4) undef AFX_DATA
 * 5) 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); } };

Implementation files:
 * 1) endif

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; }                   </li>  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 = &quot;mydomain\\myuserid&quot;; char* password = &quot;mysecretpassword&quot;; *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; }                   </li>  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(&quot;about:blank&quot;),NULL,NULL); // call this for workaround Navigate2(_T(&quot;http://myserver/mysecuredirectory/mysecurepage.htm&quot;),NULL,NULL); }                   </li> 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.</li></ol>

Keywords: kbbug kbpending kbsecurity kburlmon kbwebbrowser KB320153

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.