MeniB

hello,
i'm trying to get the hWnd of a IWebBrowser2 control.
if i'm working on xp, everything is ok.
but with Vista - things different. hWnd returned is not valid. (IsWindow - fails)
any ideas why

It seems to me that because if you run iexplorer.exe in Protected mode, it runs ieuser.exe and it runs in its turn iexplorer.exe (with another Process ID). It seems that the hWnd is not of the second process...

How can i solve this



Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

Dave Massy

Hi,

The article at http://msdn.microsoft.com/ie/default.aspx pull=/library/en-us/ietechcol/dnwebgen/protectedmode.asp on protected mode should help.

Thanks
-Dave






Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

MeniB

I know this article for a little while.

It's not helping to solve this issue.

I need someone from the IE7 developer team to answer that - it seems to me like a bug.





Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

Dave Massy

Can you rpovide full details to reproduce the probelm We have not seen issues with the webbrowser control being instantiated in Windows Vista.

Thanks
-Dave






Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

Lance Leonard

Hi there,

I'm also having problem understanding your question. Can you tell us more about the environment you're using the IWebBrowser2 control in and how are you trying to obtain the hWnd That may help us understand your underlying question more clearly.

It's entirely possible that you're running into a security restriction related to protected mode, which is why Dave pointed you to the article in question (which, btw, was recently updated). Depending on your specific implementation scenario, you may need use one of the approaches recommended in the article to obtain the information you're after.

For example, suppose you're using IHTMLWindow2::open and using the return value to get to the browser window that opens. If your application is running at medium integrity and IE is running in protected mode, that return value will be null unless the URL is in the user's trusted sites list. In addition to the protected mode article, you may want to take a peek at Developer Best Practices and Guidelines for Applications in a Least Privileged Environment. I know it's a long document, but it may answer your question more completely.

Also, what are you planning to do with the hWnd once you have it Because protected mode prevents certain activities, it may be necessary to rethink the approach you're trying to take.

Hope this helps...

-- Lance






Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

MeniB

Hello and thank you for helping.

I'm running Windows Vista RC1 - 5724.

I'm trying to open up a new IE windows, navigate and then bring it to the front. My application runs with normal security.

If IE is in protected mode, the hWnd returned is not helpful, because as I can see it, it runs ieuser.exe which runs iexplore.exe again in protected mode... which has another hWnd handle...

if IE is NOT in protected mode, hWnd returned correctly and the IE windows is brought to the front..

the code is:

CComPtr<IWebBrowser2> spWebBrowser;
hr = spWebBrowser.CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_SERVER);
hr = spWebBrowser->Navigate(bstrFullUrl, &var, &var, &var, &var);
hr=spWebBrowser->get_HWND(reinterpret_cast<PLONG>(&hWnd));

Call My function - BringToFront(hWnd);

I started thinking to CoCreateInstace as a low user (How can I do that !) - because it won't run the IEuser.exe - which will give the right hWnd, but couldn't find anything to help me with this approach.





Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

MeniB

Any one

Help please...





Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

Lance Leonard

Hi there,

Sorry for the delay in replying.

As I understand it, the problem you running into occurs after the call to Navigate. When this is finished, a new instance of protected mode iexplore is started to handle the request. As a result, the spWebBrowser pointer is now defunct.

By the way, it's not necessary to try to bring the new browser window to the top of the z-order, as IE itself will bring itself to the top of the stack (to help prevent hidden activities).

To call CoCreateInstance as a low user, start a new thread, use SetThreadToken to lower the integrity level of the new thread, and then call CoCreateInstance from the new thread, as shown in the following code sample.

DWORD WINAPI LowThreadProc(LPVOID lpParam)
{
HANDLE hThread = GetCurrentThread();
HRESULT hr = S_OK;

if (!ImpersonateSelf(SecurityImpersonation))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}

if (SUCCEEDED(hr))
{
IUnknown *pv;
hr = SetThreadIntegrityLevelLow(&hThread);
if (S_OK == hr)
{
if (SUCCEEDED(CoInitialize(NULL)))
{
// do the required operations from this low thread and you
// can marshal any interfaces back to the thread which created this
// NOTE: Remember to use CLSCTX_ENABLE_CLOAKING if you are calling
// COM¡¯s CoCreateInstance/CoGetClassObject

CoUninitialize();
}

}
}

return WIN32_FROM_HRESULT(hr);
}


HRESULT SetThreadIntegrityLevelLow(HANDLE *phThread)
{
HANDLE hProcToken = NULL;
TOKEN_MANDATORY_LABEL TML = {0};
HANDLE hMICToken = NULL;
HRESULT hr = S_OK;
BOOL bOpenProcToken = FALSE;
BOOL bDuplicateToken = FALSE;
BOOL bConvertSid = FALSE;
BOOL bSetToken = FALSE;
BOOL bPILToken = FALSE;

bOpenProcToken = OpenProcessToken(GetCurrentProcess(),MAXIMUM_ALLOWED,&hProcToken);
if (bOpenProcToken)
{
bDuplicateToken = DuplicateTokenEx(hProcToken,
MAXIMUM_ALLOWED,
NULL,
SecurityImpersonation,
TokenImpersonation,
&hMICToken);
if (bDuplicateToken)
{
PSID pMICSid = NULL;

bConvertSid = ConvertStringSidToSid(SDDL_ML_LOW, &pMICSid);
if (bConvertSid)
{
//Set Process IL to Low
TML.Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
TML.Label.Sid = pMICSid;

bPILToken = SetTokenInformation(hMICToken ,
TokenIntegrityLevel,
&TML,
sizeof(TML) + GetLengthSid(pMICSid));

if (bPILToken)
{
bSetToken = SetThreadToken(phThread, hMICToken);
}
LocalFree(pMICSid);
}
CloseHandle(hMICToken);
}
CloseHandle(hProcToken);
}

if (!bOpenProcToken || !bDuplicateToken || !bConvertSid || !bSetToken)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}

return hr;
}

Hope this helps...

-- Lance






Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

MeniB

Thanks Lance, but it doesn't work...

"As I understand it, the problem you running into occurs after the call to Navigate. When this is finished, a new instance of protected mode iexplore is started to handle the request. As a result, the spWebBrowser pointer is now defunct."

As it wrote in here I suppose to navigate and only then putVisible it...

"By the way, it's not necessary to try to bring the new browser window to the top of the z-order, as IE itself will bring itself to the top of the stack (to help prevent hidden activities)."

Well, it doesn't occur! the window stay in the background of the application. only in debug mode it appears normal. (Why is this happening !)

I tried the code you gave, but no results - the window continue to open behind my application window.
The only change I can see is - if i'm debugging - the new IE7 process is opened directly with HIGH integrity (process explorer), and the Protected Mode status says "NO"... if i'm running it non-debug it opens iexplorer.exe which runs ieuser.exe that runs iexplorer.exe with low integrity...

Here is the code (I changed it a bit - copied some missing parts to make it work on VS6...):

typedef struct _TOKEN_MANDATORY_LABEL {
SID_AND_ATTRIBUTES Label;
} TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;

typedef WINADVAPI BOOL (WINAPI *CONVERTSTRINGSIDTOSID) (LPCSTR, PSID);

#define SE_GROUP_INTEGRITY (0x00000020L)
#define SE_GROUP_INTEGRITY_ENABLED (0x00000040L)

HRESULT SetThreadIntegrityLevelLow(HANDLE *phThread)
{
HANDLE hProcToken = NULL;
TOKEN_MANDATORY_LABEL TML = {0};
const TCHAR szIntegritySid[20] = _T("S-1-16-4096");
HANDLE hMICToken = NULL;
HRESULT hr = S_OK;
BOOL bOpenProcToken = FALSE;
BOOL bDuplicateToken = FALSE;
BOOL bConvertSid = FALSE;
BOOL bSetToken = FALSE;
BOOL bPILToken = FALSE;

bOpenProcToken = OpenProcessToken(GetCurrentProcess(),MAXIMUM_ALLOWED,&hProcToken);
if (bOpenProcToken)
{
bDuplicateToken = DuplicateTokenEx(hProcToken,
MAXIMUM_ALLOWED,
NULL,
SecurityImpersonation,
TokenImpersonation,
&hMICToken);
if (bDuplicateToken)
{
PSID pMICSid = NULL;

HINSTANCE hConvertDll = LoadLibrary(_T("Advapi32.dll"));

CONVERTSTRINGSIDTOSID pConvert = reinterpret_cast<CONVERTSTRINGSIDTOSID>(
GetProcAddress(hConvertDll, "ConvertStringSidToSidA"));
if(pConvert)
{

//bConvertSid = ConvertStringSidToSid(SDDL_ML_LOW, &pMICSid);
bConvertSid = pConvert(szIntegritySid, &pMICSid);

if (bConvertSid)
{
//Set Process IL to Low
TML.Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
TML.Label.Sid = pMICSid;

bPILToken = SetTokenInformation(hMICToken ,
(TOKEN_INFORMATION_CLASS)25,
&TML,
sizeof(TML) + GetLengthSid(pMICSid));

if (bPILToken)
{
bSetToken = SetThreadToken(phThread, hMICToken);
}
LocalFree(pMICSid);
}
CloseHandle(hMICToken);
}
}
CloseHandle(hProcToken);
}

if (!bOpenProcToken || !bDuplicateToken || !bConvertSid || !bSetToken)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}

return hr;
}

The code that opens IE window:

HRESULT hr = S_OK;
try
{
// Checking if we have internet connection to the url
CComPtr<IWebBrowser2> spWebBrowser;
HANDLE hThread = GetCurrentThread();

if (!ImpersonateSelf(SecurityImpersonation))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}

hr = SetThreadIntegrityLevelLow(&hThread);
hr = spWebBrowser.CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_SERVER);
if(SUCCEEDED(hr) && !!spWebBrowser)
{
CComVariant var(0);
SetProperties(bstrProperties, spWebBrowser.p);
hr = spWebBrowser->Navigate(bstrFullUrl, &var, &var, &var, &var);
if(SUCCEEDED(hr))
{
HWND hWnd = NULL;
if(SUCCEEDED(spWebBrowser->get_HWND(reinterpret_cast<PLONG>(&hWnd))) &&::IsWindow(hWnd))
BringToFront(hWnd);
hr = spWebBrowser->put_Visible(VARIANT_TRUE);
}
}
}





Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

MeniB

Any one

What can I do





Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

BGX

Any one has any further update on this

I seem to have similar problem -- After calling IWebBrowser2 to launch ie browser, an ie process of Mediem IL was first created, then IEUser kicks in to launch an ie process of Low IL. In order to solve the problem of having 2 ie process each time the interface is called, I tried the above method to bypass the broker process, it didn't work. I tried to add in the registry entry to modify the ElevationPolicy, it didn't help either.

Anyone has better insight into the problem

Thanks,





Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

Sharath Udupa - MSFT

The intention of the above sample code was not to bypass the broker process. It demonstrated how to start COM servers with Low IL by creating a thread and marking it with low IL. The best way to achieve what you intend would be to use the IELaunchURL API (http://msdn2.microsoft.com/en-us/library/aa767962.aspx) which will take care of several things for Protected Mode IE to work properly (such as appropriate brokers being started, etc). Once you have the PID of the Protected Mode IE, you could use IShellWindows enumerator to retrieve the IWebBrowser2 corresponding to that PID.

regards,
Sharath





Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

tkeller01

Sharath:

Thanks for helping clarify this thread: I've been battling similar problems with IE Protected mode, and after working with the IELaunchURL API for a bit (and obtaining the IWebBrowser2 interface as you suggested), I've regretfully come to the conclusion that I can't use it to accomplish what I need to accomplish. I need to use the IWebBrowser2 interface to set certain properties on the object before it starts navigating (such as width, height, top, and left), and the IELaunchURL API launches the browser object at the URL and makes it visible immediately. The result is a very twitchy, unsettling experience for the user and I can't have that happening in my application. I also have a need to respond to WebBrowser events as the control navigates, but I never see the events because the original WebBrowser control is defunct.

I have a couple of of follow-up questions relevant to this thread I hope you or another MSFT expert can weigh in on.

All questions assume that Protected Mode is enabled for at least one zone:

1) If I CoCreateInstance a WebBrowser object from a thread with low IL, can I expect that the resulting object is running in Protected Mode on or does the created object always run in a process with Protected Mode off (regardless of IL) until I call IWebBrowser::Navigate and it sees a URL from which it can deduce whether Protected Mode is needed or not

2) I can call IEIsProtectedModeURL to determine if the URL I want to navigate to requires IE in protected mode. Once I know this, is there anything I can do (i.e. set IL on the thread or process token) before calling CoCreateInstance that will return a WebBrowser control configured appropriately for the URL (meaning I can be certain that the call to Navigate won't cause IE to open it using another object in another process )

Thanks in advance,

tkeller






Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

cradke

Todd,

Lances code does seem to work. That is, using it launches a single instance if IE and gives back a valid IWebBrowser pointer that can be used to sync events. The important nugget of information found in the comments of Lance's code that MeniB left out is specifying CLSCTX_ENABLE_CLOAKING when calling CoCreateInstance. This constant (0x100000) should be or'd with the other parameter (e.g. CLSCTX_ENABLE_CLOAKING|CLSCTX_LOCAL_SERVER).

Regards,

Chris Radke





Re: Internet Explorer Extension Development IE7 protected mode hWnd problem

Jens Willebrand

Hello Lance,

thanks for the good informations provided in this discussion. I applied all of it and works fine now.

But we face a new severe problem since one of your reference customer in Germany is executing a worldwide rollout of Vista.

With Vista and IE7 Explorer no instance handles of running browsers are identified any more. We need this to identify a running instance of our own page, so that no new instance is started again if already open. What we see is that a normal explorer with the directory is recognized, but not an explorer with a URL.

Is this a new feature or a bug How can this be solved

See the code fragment below.

#include <ExDisp.h>
#include <ExDispID.h>
#include <shlwapi.h>
#import <shdocvw.dll>
#include <msHtml.h>

bool SearchIEInstance()
{

bool bFound =false;
HRESULT hr;
SHDocVw::IShellWindowsPtr spSHWnd;
IDispatchPtr spDisp;

hr = spSHWnd.CreateInstance( __uuidof(SHDocVw:Tongue TiedhellWindows) );
if( hr == S_FALSE )
{
return false;
}

long nCount = spSHWnd->GetCount ();

for (long i = 0; i < nCount; i++)
{
_variant_t va( i, VT_I4 );
spDisp = spSHWnd->Item( va );

IWebBrowser2* pWebBrowser = NULL;
hr = spDisp.QueryInterface( IID_IWebBrowser2, &pWebBrowser );

if( pWebBrowser != NULL )
{
HWND hWnd;
BSTR bstrURL;

pWebBrowser->get_HWND((long*)(&hWnd));

if( hWnd && ::IsWindow( hWnd ) )
{

HRESULT hr2 =pWebBrowser->get_LocationURL( &bstrURL );

// code to identify your instance if it contains the wanted url.....

// if ok return true;

return true;
}
}
}
return false;
}

Best regards Jens