none
Can't Create Modal Dialog Windows from explorer bar if Enhanced Protected Mode enabled with Desktop-IE10 on Win8-64Bit RRS feed

  • Question

  • Both the 32Bit version and 64Bit version of my extension bar work with Protected Mode in IE9 on Win7-64bit.

    I understand the basics of the App Container used with the Enhanced Protected Mode of IE10 on Win8-64bit and thanks to some other help from this forum I can get the 64Bit version of my extension bar to display and in general work (can process browser documents, create temporary html files for browsing, etc) with EPM on in Desktop IE10 from Win8-64bit... so I am very close...

    I've read through the following articles but haven't found any discussion of dialg windows...

    http://blogs.msdn.com/b/ieinternals/archive/2012/03/23/understanding-ie10-enhanced-protected-mode-network-security-addons-cookies-metro-desktop.aspx

    which points to:

    http://msdn.microsoft.com/en-us/library/bb250462(v=vs.85).aspx#wpm_fliwl

    My extension bar is written in unmanaged Visual C++ and it uses dialog boxes to allow the user to edit settings and data held by it.  There are a lot of different dialog boxes, but none of them seem to function. Event the "About splash dialog" doesn't show... given the following code the Message Box will pop up but the dialog doesn't. 

    void CMainFrame::OnInfoAbout()
    {
        MessageBox("Would really like to see the splash screen ....");
    	CAboutDlg dlg;
    	dlg.DoModal();
    }
    
    the function OnInfoAbout() is registered as a handler for the class CMainFrame:

    ON_COMMAND(ID_INFO_ABOUT,  OnInfoAbout)

    The command comes from a popup menu which comes up when they click a button on the toolbar. Basically all my menus and such work and the data seems to be held correctly everywhere - but anywhere a dialog from my resources file is brought up with DoModal() nothing happens.

    Any help would be greatly appreciated.

    Brian


    Tuesday, January 29, 2013 12:53 AM

Answers

  • Okay - I'll be my own critic... there are issues with the above solution.

    (1) AfxgetMainWnd()->EndModalState() doesn't seem to clean up the disabled status of all the subwindows. I'm not sure why, but in my case the status bar at the bottom of my extension bar was left disabled. It may be the way the status bar is created and managed, but not sure why the StartModalState() would disable it and EndModalState() wouldn't re-enable it.

    (2) The return code doesn't match what you would have gotten from DoModal()... as long as the locks are given it returns true.

    (3) It simply isn't elegant

    Good news is there is a slight modification which avoids at least (1) and (2) - let you judge if it solves (3), but at least it seems to make use of the classes without forcing something.

    INT GetModalLock(CDialog &dlg, UINT nDlgID)
    {
        HWND hwndParent=NULL;
        HANDLE hModalDialogLock;
        INT nRetVal = 0;
    
        //-------------------------------------------------------------------------
        // The the IE process where we can reach the Tab Window Exports
        //-------------------------------------------------------------------------
        HMODULE hmod = IEProcess::GetProcessModule();
        if (hmod != NULL)
        {
            //---------------------------------------------------------------------
            // Use the Tab Window Exports to wait for the tab window to be ready
            // to give up the modal lock to our dialog
            //---------------------------------------------------------------------
            HRESULT hr = IEProcess::GetTabWindowExports(hmod)->WaitForTabWindow(false, hwndParent, &hwndParent);
            if (SUCCEEDED(hr))
            {
                //-----------------------------------------------------------------
                // Acquire the modal lock from the tab window.
                //-----------------------------------------------------------------
                hr = IEProcess::GetTabWindowExports(hmod)->AcquireModalDialogLockAndParent(hwndParent, &hwndParent, &hModalDialogLock);
                if (SUCCEEDED(hr))    
                {
                    //-------------------------------------------------------------
                    // Create the dialog window based on the template and display
                    // Need to make sure the dialog properties are set such that
                    // the window is always on top and system modal. Then run the
                    // dialog's modal loop
                    //-------------------------------------------------------------
                    dlg.Create(nDlgID);
                    dlg.ShowWindow(SW_SHOW);
                    nRetVal = dlg.RunModalLoop(MLF_SHOWONIDLE);
    
                    //-------------------------------------------------------------
                    // Release the modal lock granted by the tab
                    //-------------------------------------------------------------
                    IEProcess::GetTabWindowExports(hmod)->ReleaseModalDialogLockAndParent(hModalDialogLock);
                }
                else MessageBox(NULL,"Could not acquire modal dialogk lock to display the dialog.","",MB_OK);
            }
            else MessageBox(NULL,"Waiting for the Tab Window failed, unable to display the dialog.","",MB_OK);
        }
        else MessageBox(NULL,"No Internet Explorer process exports have been initialized, unable to display the dialog.","",MB_OK);
        
        return nRetVal;
    }

    The change in the return code from bool to INT allows us to capture the value send to EndModalLoop... thus the funciton returns 0 if it couldn't get the lock, IDOK (1) if the user clicks the "OK" button on the dialog, and IDCANCEL (2) if the user cancels or closes the dialog without clicking the "OK" button.

    The change to run the dialog's modal loop removes the need for the forced modal state and the use of a message pump which solves (1)... and maybe (3).

    As a follow on note - if you have dialogs that pop up other dialogs, you don't need to use this fuction for the second generation dialogs - those seem to work with calls to DoModal().

    • Edited by Image Surfer Pro Wednesday, January 30, 2013 8:08 AM Added "Follow on Note"
    • Marked as answer by Image Surfer Pro Wednesday, January 30, 2013 9:16 PM
    Wednesday, January 30, 2013 7:58 AM

All replies

  • Should also have said that if EMP is disabled the 32Bit version of the extension bar works fine - including the dialog windows...
    Tuesday, January 29, 2013 12:55 AM
  • Okay - so for everyone that is going to say "don't you know you have to acquire a lock ever since IE8"... First I'd like to say that my extension bar has worked with every IE since IE6 and fully supported IE7, IE8, and IE9 running in protected mode... so not sure why this section of code would have to change...

    2nd... here is code that does everything discussed in the IE8 sdk about acquiring the modal lock:

    bool GetModalLock(CDialog &dlg)
    {
        HWND hwndParent=NULL;
        HANDLE hModalDialogLock;
        bool bRetVal = false;
    
        INT_PTR nRes = -1;
    
        HMODULE hmod = IEProcess::GetProcessModule();
        if (hmod != NULL)
        {
            HRESULT hr = IEProcess::GetTabWindowExports(hmod)->WaitForTabWindow(false, hwndParent, &hwndParent);
            if (SUCCEEDED(hr))
            {
                hr = IEProcess::GetTabWindowExports(hmod)->AcquireModalDialogLockAndParent(hwndParent, &hwndParent, &hModalDialogLock);
                if (SUCCEEDED(hr))    
                {
                    MessageBox(NULL,"We found the IE Process Module, waited for the tab window, and aquired the modal dialog lock... you should see the about splash now","",MB_OK);
    
                    dlg.DoModal();
                    bRetVal = true;
    
                    IEProcess::GetTabWindowExports(hmod)->ReleaseModalDialogLockAndParent(hModalDialogLock);
                }
                else MessageBox(NULL,"Could not acquire modal dialogk lock","",MB_OK);
            }
            else MessageBox(NULL,"Waiting for the Tab Window failed","",MB_OK);
        }
        else MessageBox(NULL,"No Internet Explorer process exports have been initialized.","",MB_OK);
        
        return bRetVal;
    
    }
    
    void CMainFrame::OnInfoAbout()
    {
        MessageBox("Would really like to see the splash screen ....");
    	CAboutDlg dlg;
        GetModalLock(dlg);
    }
    

    When run in IE9 with protected mode on Vista and Windows7 (32bit and 64bit) I get the two expected message boxes and the splach dialog. When EPM is turned off on 64Bit Win8 and IE10 I get the two message boxes and the splash dialog...

    When I enable EPM in IE10 on Win8-64bit I get the two expected Message boxes but no splash dialog...

    Tuesday, January 29, 2013 10:27 PM
  • Hello,

    Thanks for your participation in this forum. I'm trying to involve some senior engineers into this issue and it will take some time. Your patience will be greatly appreciated.

    Sorry for any inconvenience and have a nice day!

    Regards,


    Damon Zheng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, January 30, 2013 3:08 AM
    Moderator
  • No problem Damon - I try not to post questions I come to a solution quickly on - so makes me feel better when others feel they may be hard too :)

    I did come to a solution... can't say I like it much as it seems a bit heavy handed... but in the end I now have dialogs that work and give the appearance of being Modal... I say appearance because they are very much forced.

    I use this funciton to simulate the application message pump:

    bool Pump ()
    {
        MSG msg;
    
        //-------------------------------------------------------------------------
        // Retrieve and dispatch any waiting messages - allows the dialog to
        // function and give you a bell if you click the disabled browswer window
        //-------------------------------------------------------------------------
        while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) 
        {
            //---------------------------------------------------------------------
            // This should always be true - bail if it isn't...
            //---------------------------------------------------------------------
            if (!AfxGetApp()->PumpMessage()) 
            {
                PostQuitMessage(0);
                return FALSE;
            }
        }
    
        //-------------------------------------------------------------------------
        // Simulate the framework's idle processing mechanism.
        //-------------------------------------------------------------------------
        LONG lIdle = 0;
        while (AfxGetApp()->OnIdle(lIdle++));
        return TRUE;
    }

    I use this function to display the dialog and force a "modal" state on the application. Use of the pump forces the application (IE) to remain locked here while the dialog does its thing. The forced modal state is cleared after the dialog is closed.

    bool GetModalLock(CDialog &dlg, UINT nDlgID)
    {
        HWND hwndParent=NULL;
        HANDLE hModalDialogLock;
        bool bRetVal = false;
    
        //-------------------------------------------------------------------------
        // The the IE process where we can reach the Tab Window Exports
        //-------------------------------------------------------------------------
        HMODULE hmod = IEProcess::GetProcessModule();
        if (hmod != NULL)
        {
            //---------------------------------------------------------------------
            // Use the Tab Window Exports to wait for the tab window to be ready
            // to give up the modal lock to our dialog
            //---------------------------------------------------------------------
            HRESULT hr = IEProcess::GetTabWindowExports(hmod)->WaitForTabWindow(false, hwndParent, &hwndParent);
            if (SUCCEEDED(hr))
            {
                //-----------------------------------------------------------------
                // Acquire the modal lock from the tab window.
                //-----------------------------------------------------------------
                hr = IEProcess::GetTabWindowExports(hmod)->AcquireModalDialogLockAndParent(hwndParent, &hwndParent, &hModalDialogLock);
                if (SUCCEEDED(hr))    
                {
                    //-------------------------------------------------------------
                    // Create the dialog window based on the template and display
                    // Need to make sure the dialog properties are set such that
                    // the window is always on top and system modal
                    //-------------------------------------------------------------
                    dlg.Create(nDlgID);
                    dlg.ShowWindow(SW_SHOW);
    
                    //-------------------------------------------------------------
                    // Enter the "Modal State" by forcing our application window
                    // to go disabled (this would include the dialog, so re-enable
                    // the dialog window)
                    //-------------------------------------------------------------
                    AfxGetMainWnd()->BeginModalState();
                    dlg.EnableWindow(TRUE);
    
                    //-------------------------------------------------------------
                    // Force the application to wait right here until the dialog
                    // is closed... too much of sleep here makes the dialog
                    // response choppy
                    //-------------------------------------------------------------
                    while (dlg.IsWindowVisible()) {Sleep(10); Pump();}
    
                    //-------------------------------------------------------------
                    // Close out the "Modal State" of the application window and
                    // release the modal lock. We were successful - so return 
                    // True.
                    //-------------------------------------------------------------
                    AfxGetMainWnd()->EndModalState();
                    IEProcess::GetTabWindowExports(hmod)->ReleaseModalDialogLockAndParent(hModalDialogLock);
                    bRetVal = true;
                }
                else MessageBox(NULL,"Could not acquire modal dialogk lock to display the dialog.","",MB_OK);
            }
            else MessageBox(NULL,"Waiting for the Tab Window failed, unable to display the dialog.","",MB_OK);
        }
        else MessageBox(NULL,"No Internet Explorer process exports have been initialized, unable to display the dialog.","",MB_OK);
        
        return bRetVal;
    }

    Use of the GetModalLock function then replaces anywhere I what to call DoModal() for a CDialog derived class.  For example the showing of the About dialog in the following code segment:

    void CMainFrame::OnInfoAbout()
    {
        CAboutDlg dlg;
        GetModalLock(dlg, IDD_ABOUT);
    }

    I'll wait and see if there are better approaches to the issue before marking this as answered - also open to criticism of the solution. I did try a lot of different approaches but in most cases the code wouldn't halt and wait for the dialog to close and so when the variable went out of scope the window closed (often only a flash). If the dialog variables were "global" or didn't go out of scope the dialog would stay on the screen but you lost that "synchronous" feeling of DoModal - which would be very problematic in several cases in my application as I take actions when the forms close (currently when DoModal returns).


    • Edited by Image Surfer Pro Wednesday, January 30, 2013 3:32 AM minor spelling edit
    Wednesday, January 30, 2013 3:28 AM
  • Okay - I'll be my own critic... there are issues with the above solution.

    (1) AfxgetMainWnd()->EndModalState() doesn't seem to clean up the disabled status of all the subwindows. I'm not sure why, but in my case the status bar at the bottom of my extension bar was left disabled. It may be the way the status bar is created and managed, but not sure why the StartModalState() would disable it and EndModalState() wouldn't re-enable it.

    (2) The return code doesn't match what you would have gotten from DoModal()... as long as the locks are given it returns true.

    (3) It simply isn't elegant

    Good news is there is a slight modification which avoids at least (1) and (2) - let you judge if it solves (3), but at least it seems to make use of the classes without forcing something.

    INT GetModalLock(CDialog &dlg, UINT nDlgID)
    {
        HWND hwndParent=NULL;
        HANDLE hModalDialogLock;
        INT nRetVal = 0;
    
        //-------------------------------------------------------------------------
        // The the IE process where we can reach the Tab Window Exports
        //-------------------------------------------------------------------------
        HMODULE hmod = IEProcess::GetProcessModule();
        if (hmod != NULL)
        {
            //---------------------------------------------------------------------
            // Use the Tab Window Exports to wait for the tab window to be ready
            // to give up the modal lock to our dialog
            //---------------------------------------------------------------------
            HRESULT hr = IEProcess::GetTabWindowExports(hmod)->WaitForTabWindow(false, hwndParent, &hwndParent);
            if (SUCCEEDED(hr))
            {
                //-----------------------------------------------------------------
                // Acquire the modal lock from the tab window.
                //-----------------------------------------------------------------
                hr = IEProcess::GetTabWindowExports(hmod)->AcquireModalDialogLockAndParent(hwndParent, &hwndParent, &hModalDialogLock);
                if (SUCCEEDED(hr))    
                {
                    //-------------------------------------------------------------
                    // Create the dialog window based on the template and display
                    // Need to make sure the dialog properties are set such that
                    // the window is always on top and system modal. Then run the
                    // dialog's modal loop
                    //-------------------------------------------------------------
                    dlg.Create(nDlgID);
                    dlg.ShowWindow(SW_SHOW);
                    nRetVal = dlg.RunModalLoop(MLF_SHOWONIDLE);
    
                    //-------------------------------------------------------------
                    // Release the modal lock granted by the tab
                    //-------------------------------------------------------------
                    IEProcess::GetTabWindowExports(hmod)->ReleaseModalDialogLockAndParent(hModalDialogLock);
                }
                else MessageBox(NULL,"Could not acquire modal dialogk lock to display the dialog.","",MB_OK);
            }
            else MessageBox(NULL,"Waiting for the Tab Window failed, unable to display the dialog.","",MB_OK);
        }
        else MessageBox(NULL,"No Internet Explorer process exports have been initialized, unable to display the dialog.","",MB_OK);
        
        return nRetVal;
    }

    The change in the return code from bool to INT allows us to capture the value send to EndModalLoop... thus the funciton returns 0 if it couldn't get the lock, IDOK (1) if the user clicks the "OK" button on the dialog, and IDCANCEL (2) if the user cancels or closes the dialog without clicking the "OK" button.

    The change to run the dialog's modal loop removes the need for the forced modal state and the use of a message pump which solves (1)... and maybe (3).

    As a follow on note - if you have dialogs that pop up other dialogs, you don't need to use this fuction for the second generation dialogs - those seem to work with calls to DoModal().

    • Edited by Image Surfer Pro Wednesday, January 30, 2013 8:08 AM Added "Follow on Note"
    • Marked as answer by Image Surfer Pro Wednesday, January 30, 2013 9:16 PM
    Wednesday, January 30, 2013 7:58 AM