ShowBrowserBar() doesn’t show toolbar in IE8 - c++

Please help me understand what I’m doing wrong!
I have a problem when I programmatically activate my IE toolbar from other program.
Making it following the instruction given at Microsoft support site (http://support.microsoft.com/kb/q255920/):
SHDocVw::IWebBrowser2Ptr pIE;
HRESULT hr = ::CoCreateInstance(CLSID_InternetExplorer, NULL,
CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (LPVOID*)&pIE);
if(FAILED(hr)) return;
try {
_variant_t vClsID;
_variant_t vVis;
_variant_t vNotUsed;
vClsID.vt = VT_BSTR;
vClsID.bstrVal = SysAllocString(OLESTR("{MY_TOOLBAR_GUID}"));
vVis.vt = VT_BOOL;
vVis.boolVal = VARIANT_TRUE;
vNotUsed.vt = VT_INT;
vNotUsed.intVal = 1;
hr = pIE->ShowBrowserBar()(&vClsID, &vVis, &vNotUsed);
SysFreeString(vClsID.bstrVal);
if(FAILED(hr)) return;
}catch(...) {return;}
pIE->Navigate2(&Url);
pIE->Visible = TRUE;
This code works correctly in IE7, but doesn't work in IE8. In both cases ShowBrowserBar() returns S_OK, but in IE8 toolbar.dll is not loaded into the browser, i.e. the toolbar is not activated and therefore not displayed.
I also tried to launch IE8 with three tabs and check if ShowBrowserBar() attempts to open the toolbar in the tabs, not the manager process.
It is log file:
Handle url 'outlook:'
ShowBrowserBar() FAILED!
Handle url 'http://www.handypassword.com'
ShowBrowserBar() SUCCESSED!
Handle url 'http://www.google.ru/'
ShowBrowserBar() SUCCESSED!
Handle url 'http://vkontakte.ru/'
ShowBrowserBar() SUCCESSED!
Everything works as expected in IE7, but not in IE8, and I can't understand why the ShowBrowserBar() method returns S_OK in both of them.
Has anybody got any clues?
Warm regards,
Anna.

I find an answer of this problem!
By default, any add-on or toolbar you install in Internet Explorer will be enabled; but it can later on become disabled  (you can no longer use it), either because you or another Windows user has manually disabled it, or because a third-party installer in conflict automatically disabled it. If user disable toolbar manually you can't show it automatically! You need to re-enable the add-on, in Tools, Manage Add-Ons.

Related

Windows CredentialProvider autologon via event still shows login-button

I've written a custom CredentialProvider listening to events sent via bluetooth.
So far everything works fine. Except the fact that after sending the event the login screen changes and shows a single button "Sign in" below the username.
As stated in the answers to this SO-question I did he following to achieve autologon:
HRESULT CMobileCredential2::SetSelected(_Out_ BOOL *pbAutoLogon)
{
LOG_FUNCTION;
*pbAutoLogon = true;
return S_OK;
}
and in the eventhandling code I call:
HRESULT hr = _pcpe->CredentialsChanged(_upAdviseContext);
if (S_OK != hr)
{
LOG_ERROR("Could not login!");
}
I thought that the LogonUI would automatically log me in when I set autologon to true? Why do I have to click on another button? Is there any way to avoid this behaviour?
EDIT:
The following is to be found in the "Credential Provider Technical Reference" from Microsoft:
In Windows 10, if a credential provider wants to autologon the user
where we think may be inappropriate, we will paint a “sign in” button
as a speed bump.
I think that's the point I'm hitting here, but what is inappropriate? The password used consists of lower and uppercase characters as well as some numbers. Is there any possibility to cirumvent this?
After searching for a few days I stumbled upon this answer in the microsoft-forums, that contained the solution.
As it seems, Windows does not trust the custom credential enough to bypass this "speed bump", when pbAutoLogon is set to true in SetSelected(_Out_ BOOL *pbAutoLogon).
However it trusts the custom provider, so setting pbAutoLogonWithDefault to true in
GetCredentialCount(
_Out_ DWORD *pdwCount,
_Out_ DWORD *pdwDefault,
_Out_ BOOL *pbAutoLogonWithDefault)
seems to do the trick, as GetCredentialCount is always called before calling
GetSerialization(_Out_ CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpgsr,
_Out_ CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs,
_Outptr_result_maybenull_ PWSTR *ppwszOptionalStatusText,
_Out_ CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon)
of the custom credential.

IE BHO - DISPID_FILEDOWNLOAD being called for page loads?

I am implementing an Internet Explorer Browser Helper Object that should catch the DISPID_FILEDOWNLOAD event.
I first implemented this in C# which worked great except that I also need the cookies that go with the URL so need to call InternetGetCookiesEx. As .NET runs in it's own process it does not return me the session cookies so is no good.
I then wrote a quick test DLL in C++ so that it is loaded into the same process as IE which works great for the cookies but I now have a new problem:
I am getting calls to DISPID_FILEDOWNLOAD in my Invoke function for each page load when I only want them for an actual download.
In the C# version I only got a call to WebBrowser.FileDownload for an actual download but it seems that the C++ version is sending a DISPID_FILEDOWNLOAD even for each page load.
STDMETHODIMP CIEHlprObj::Invoke(
DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS* pDispParams,
VARIANT* pvarResult,
EXCEPINFO* pExcepInfo,
UINT* puArgErr
)
{
USES_CONVERSION;
if (!pDispParams)
return E_INVALIDARG;
LPOLESTR lpURL = NULL;
m_spWebBrowser2->get_LocationURL(&lpURL);
int i = 0;
switch (dispidMember)
{
case DISPID_BEFORENAVIGATE2:
case DISPID_BEFORENAVIGATE:
sCurrentFile=NULL;
if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF | VT_VARIANT))
{
CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
varURL.ChangeType(VT_BSTR);
char* myStr = OLE2T(varURL.bstrVal);
if (myStr)
{
sCurrentFile = AllocateString(myStr);
sCurrentFileW = varURL.bstrVal;
}
}
break;
case DISPID_FILEDOWNLOAD:
// CALLED FOR EACH PAGE LOAD!
if(sCurrentFile)
{
TCHAR cookies[8192];
DWORD size = 8192;
BOOL ret = InternetGetCookieEx(sCurrentFile,
0,
cookies,
&size,
INTERNET_COOKIE_HTTPONLY,
0);
::MessageBox(0, sCurrentFile, "Downloading called multiple times!!", MB_OK);
}
break;
default:
break;
}
return S_OK;
}
Is there some filter that needs checking somewhere to know if a DISPID_FILEDOWNLOAD event relates to a file load or an actual file download?
Many thanks
UPDATE:
On closer inspection it seems that the C# managed code version is actually doing the same, I just didn't notice it the firs time around.
It seems that the FileDownload event is being called in the following circumstances:
New window / tab opened
New domain connected to (maybe a new keep-alive connection?)
An actual download
Obviously I only want the even on the actual download event.
As a possible solution to this I notice MS provide a ActiveDocument (BOOL) argument along with the event.. according to the Microsoft documentation the ActiveDocument argument means:
A Boolean that specifies whether the file is an Active Document
http://msdn.microsoft.com/en-us/library/bb268220(v=vs.85).aspx
Not very helpful but if I log the DISPID_FILEDOWNLOAD events to a text file and look at them later it appears that I should ignore all events where ActiveDocument = true
Getting the params is quite easy:
BOOL cancel = *pDispParams->rgvarg[0].pboolVal;
BOOL active = pDispParams->rgvarg[1].boolVal;
So the code would just need updating to something like:
if (active)
return S_OK;
I can only assume that this is some event the IE is sending telling the BHO that a page is downloading.. not a file, although that should mean that I get a DISPID_FILEDOWNLOAD event for each page load, which I don't.. only new tabs/browser instances and some new connections.
Hopefully someone else will be able to contribute to this and clarify what is the best way of handling this as it feels like a bit of a hack.

Open URL with ShellExecute - SW_SHOWMAXIMIZED dont active window in C++

I used this function to open new tab in Chrome and active it:
ShellExecuteA(0,0,"chrome.exe","http://google.com --incognito",0,SW_SHOWMAXIMIZED);
but Chrome only open new tab but it doesnt active window.
(I call this function from global keyboard-hook of an application with no user interface, if user press specified key).
How I can fix it?
Looks like a bug in chrome.exe. I could repro with your ShellExecute call from a simple console app, if a regular (non-incognito) chrome.exe session was running and no incognito session was running. In other words, if a new incognito chrome session needed to be spawned, the regular session did not appear to correctly propagate the ShowWindow flags to the spawned incognito process. Another factor was that the activation failure also required the regular chrome session to be active before the test app ran. If any other app was active (say notepad.exe), then activation of the incognito session succeeded. The same behavior occurs with ShellExecuteEx and CreateProcess. Observing in Process Explorer (from sysinternals), it's clear that chrome.exe is forking the child process as necessary and then terminating itself. This makes it difficult to intercept an hProcess or processId in order to ultimately call SetActiveWindow.
Its not possible. You have to make Google Chrome as default browser and than try this:
(only tested on WinXP using
IE6)
first a function, that finds the default app for any File extension:**
enter code here
#include<Registry.hpp>
AnsiString GetDefaultApp(AnsiString ext)
{
TRegistry* reg = new(TRegistry);
reg->RootKey = HKEY_CURRENT_USER;
if(!reg->OpenKeyReadOnly("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\."+ext+"\\OpenWithList"))
return(NULL);
try
{
AnsiString MRUList = reg->ReadString("MRUList");
AnsiString ret = reg->ReadString(AnsiString(char(MRUList[1])));
return(ret);
}
catch(...)
{
return(NULL);
}
}
now the code to launch the default app for html files and giving
the URL as parameter:**
#include<shellapi>
void OpenURL(AnsiString URL)
{
AnsiString app = GetDefaultApp("html");
if(app == NULL)
return;
ShellExecute(NULL,"open",app.c_str(),URL.c_str(),NULL,SW_SHOWDEFAULT);
}
Now you can open a URL in a new Browser using this command:
OpenURL("http://www.AlgorithMan.de/");

Drag-and-drop from IE 9 into my application

It's kind of weird issue, let me try to explain. I wrote a (dialog based) app in c++/MFC that supports drag-n-dropping.
I do the following test on Windows 7 with default themes. My app is running on the screen. It is not a top window (in its z-order) or in other words it's obscured by other windows on top of it.
If I begin dragging a link or just a text selection from the Chrome or Firefox web browser, first into my app's icon on the taskbar, the icon flashes and my app pops up on the screen (by receiving the top z-order) so I can then drag-and-drop into my app. Everything works fine.
If I do the same from IE 9 (version 9.0.8112, update versions 9.0.12) when I drag selected text or a link first to the taskbar icon of my app to make my app become top window (in z-order), the app icon continues flashing but it never gets shown on the screen like it happens with Chrome or FF, so as a result I have to abandon my drag-and-drop.
Any idea why is it happening like that with IE and if there's a way to fix it?
EDIT: Here's the code sample in regards to my comments below:
HRESULT __stdcall DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
//IDropTarget::DragEnter
m_fAllowDrop = QueryDataObject(pDataObject);
if(m_fAllowDrop)
{
//SUCCESS
// get the dropeffect based on keyboard state
}
else
{
//FAILURE
*pdwEffect = DROPEFFECT_NONE;
}
return S_OK;
}
BOOL QueryDataObject(IDataObject* pDataObject, int* pnOutDataType)
{
static FORMATETC fmtetc_file = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
static FORMATETC fmtetc_txt = {CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
BOOL bRes = FALSE;
HRESULT hr;
//See if our data type
hr = pDataObject->QueryGetData(&fmtetc_file);
if(hr == S_OK)
{
bRes = TRUE;
}
//In my case hr is E_FAIL or 0x80004005
hr = pDataObject->QueryGetData(&fmtetc_txt);
if(hr == S_OK)
{
bRes = TRUE;
}
//In my case hr is E_FAIL or 0x80004005
return bRes;
}
As part of its sandboxing to prevent unauthorized changes to the machine, Internet Explorer runs in a lower UIPI (User Interface Privilege Isolation) integrity level than other apps do. As such, it does not have permission to access your app by default, which is more likely to be running in a medium or high UIPI integrity level (depending on whether it is UAC elevated or not). The flashing taskbar button means that something is trying to bring your app to the foreground but does not have permission to do so (see the documentation of SetForegroundWindow() for more details). UIPI does not allow a lower-integrity process to send window messages to a higher-integrity process unless the receiving process explicitally tells UIPI to allow it. Chrome and FireFox are likely running in the same integrity level as your app. In order to support drag-and-drop from Internet Explorer, call ChangeWindowMessageFilter() or ChangeWindowMessageFilterEx() to let your app receive WM_DROPFILES, WM_COPYDATA, and WM_COPYGLOBALDATA (0x0049) messages from lower-integrity processes.
Update: It looks like Internet Explorer in particular imposes additional restrictions on drag&drop operations when it is running in Protected Mode:
How to handle drag & drop from low integrity Internet Explorer
Understanding and Working in Protected Mode Internet Explorer - Allowing Drag and Drop Operations in your Application

IWebBrowser2: how to force links to open in new window?

The MSDN documentation on WebBrowser Customization explains how to prevent new windows from being opened and how to cancel navigation. In my case, my application is hosting an IWebBrowser2 but I don't want the user to navigate to new pages within my app. Instead, I'd like to open all links in a new IE window. The desired behavior is: user clicks a link, and a new window opens with that URL.
A similar question was asked and answered here and rather than pollute that answered post, it was suggested I open a new discussion.
The members on the related post suggested I should be able to do this by trapping DISPID_BEFORENAVIGATE2, setting the cancel flag, and writing code to open a new window, but I've found out that the browser control gets lots of BeforeNavigate2 events that seem to be initiated by scripts on the main page. For example, amazon.com fires BeforeNavigate2 events like crazy, and they are not a result of link invocation.
Replies appreciated!
What I ended up doing was using IHTMLDocument directly rather than IWebBrowser. IWebBrowser is a superset of IHTMLDocument, and the navigation model implemented by IWebBrowser isn't customizable to the degree I wanted.
I actually got MS Developer Support involved and this approach was their recommendation. They say this is what Outlook uses for HTML-based email, which is the user experience I wanted to emulate. They also confirmed that there's no reliable way to filter the OnBeforeNavigate events that result from user action from those that result from script activity.
Hope this helps anybody facing the same issues. It wasn't too hard to port the code to use IHTMLDocument. If you end up doing this, you may also find yourself looking for a way to figure out when the document is done loading. To do that, hook HTMLDocumentEvents instead of DWebBrowserEvents, and look for the DISPID_HTMLDOCUMENTEVENTS_ONREADYSTATECHANGE event. It doesn't tell you what the ready state is; you need to call IHTMLDocument::get_readyState and parse the resulting string. Goofy, but there you go.
You can bind to onclick event before document is complete while creating browser in OnCreate() using IHTMLDocument2::put_onclick():
#include <comutil.h>
ClickEvents<RootFrame> clickEvents;
_variant_t clickDispatch;
clickDispatch.vt = VT_DISPATCH;
clickDispatch.pdispVal = &clickEvents;
CComQIPtr<IDispatch> dispatch;
hr = webBrowser2->get_Document(&dispatch);
ASSERT_EXIT(SUCCEEDED(hr), "webBrowser->get_Document(&dispatch)");
CComQIPtr<IHTMLDocument2> htmlDocument2;
hr = dispatch->QueryInterface(IID_IHTMLDocument2, (void**) &htmlDocument2);
ASSERT_EXIT(SUCCEEDED(hr), "dispatch->QueryInterface(&htmlDocument2)");
htmlDocument2->put_onclick(clickDispatch);
ClickEvents class implements IDispatch, you only need to implement Invoke method, in rest return E_NOTIMPL:
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
HRESULT hr;
CComQIPtr<IWebBrowser2> webBrowser2;
hr = rootFrame->GetDlgControl(rootFrame->rootview.GetDlgCtrlID(), IID_IWebBrowser2, (void**) &webBrowser2);
ASSERT_EXIT(SUCCEEDED(hr), "rootframe->GetDlgControl(IID_IWebBrowser2) failed");
CComQIPtr<IDispatch> dispatch;
hr = webBrowser2->get_Document(&dispatch);
ASSERT_EXIT(SUCCEEDED(hr), "webBrowser2->get_Document(&dispatch)");
CComQIPtr<IHTMLDocument2> htmlDocument2;
hr = dispatch->QueryInterface(IID_IHTMLDocument2, (void**) &htmlDocument2);
ASSERT_EXIT(SUCCEEDED(hr), "dispatch->QueryInterface(&htmlDocument2)");
CComQIPtr<IHTMLWindow2> htmlWindow2;
hr = htmlDocument2->get_parentWindow((IHTMLWindow2**) &htmlWindow2);
ASSERT_EXIT(SUCCEEDED(hr), "htmlDocument2->get_parentWindow(&htmlWindow2)");
CComQIPtr<IHTMLEventObj> htmlEvent;
hr = htmlWindow2->get_event(&htmlEvent);
ASSERT_EXIT(SUCCEEDED(hr), "htmlWindow2->get_event(&htmlEvent)");
CComQIPtr<IHTMLElement> htmlElement;
hr = htmlEvent->get_srcElement(&htmlElement);
ASSERT_EXIT(SUCCEEDED(hr), "htmlEvent->get_srcElement(&htmlElement)");
CComBSTR hrefAttr(L"href");
VARIANT attrValue;
VariantInit(&attrValue);
hr = htmlElement->getAttribute(hrefAttr, 0 | 2, &attrValue); // 0 = case insensitive, 2 = return BSTR
ASSERT_EXIT(SUCCEEDED(hr), "htmlElement->getAttribute()");
wchar_t href[2084]; // maximum url length in IE, http://support.microsoft.com/kb/208427
wcsncpy_s(href, _countof(href), attrValue.bstrVal, _TRUNCATE);
if (!rootFrame->IsURLAllowed(href)) {
VARIANT variant;
variant.vt = VT_BOOL;
variant.boolVal = VARIANT_FALSE;
htmlEvent->put_returnValue(variant);
ShellExecute(0, L"open", href, 0, 0, SW_SHOWNORMAL);
}
return S_OK;
}
As you can see after querying some interfaces I finally have the element that got clicked, then I call IsURLAllowed() defined in my root frame to check whether to allow opening url in current webbrowser window or whether to open it using default browser on user's computer.
This handles all links even if they were appended to document using javascript.
The same should be done with "onsubmit" events for forms.
I also think I have a solution for "window.location" redirects in javascript, I haven't tested it yet, but I will soon test it and I will update this answer then. You could use a combination of "onunload" and "onbeforeunload" events along with DWebBrowserEvents2::BeforeNavigate2(), after onunload/onbeforeunload are called you will know that user is leaving current page so now in BeforeNavigate2() you can cancel it. You can attach unload events using IHTMLWindow2::put_onunload() and IHTMLWindow2::put_onbeforeunload().
See sources of a complete solution for the "onclick" below.
AttachClickEvents in BrowserFrame:
http://code.google.com/p/phpdesktop/source/browse/phpdesktop-msie/msie/browser_frame.h?r=709d00b991b5#125
Invoke in ClickEvents(IDispatch):
http://code.google.com/p/phpdesktop/source/browse/phpdesktop-msie/msie/click_events.h?r=a5b0b350c933#132
I'm hypothesising here but yet another approach could be to maintain a count of navigation events, incrementing the counter on DISPID_BEFORENAVIGATE2 and decrementing it on occurrences of DISPID_NAVIGATECOMPLETE2 and DISPID_NAVIGATEERROR. With that in place, you could speculate that whenever you get DISPID_BEFORENAVIGATE2 and your counter is at zero, it is actual user navigation / link invocation.
I have no idea whether this approach would work, or whether those are the right events you'd need to make it work, but it could be worth investigating.
You could try a different approach instead and physically add the attribute target="_blank"
to all <a> tags in the rendered document.
This approach would involve waiting for DISPID_DOCUMENTCOMPLETE and then using IHTMLDocument3::getElementsByTagName() to fetch all of the anchor elements. You would then use IHTMLElement::setAttribute() to set target="_blank" on each of them.
It seems to me, that it you want "to open all links in a new IE window", it means that you want that the opening of new windows must be done in another process. The easiest way to do so: using CreateObject("InternetExplorer.Application") way (see another question which solve a problem, which is opposite to your question: InternetExplorer.Application object and cookie container). With this way you will receive the best isolation from your application and the user who clicks on the link receive all possibilities which exist in IE. You should of cause continue usage of BeforeNavigate2 events to find out the moment when "a new IE window" should be opened.