Solved

AOL-specific problems with IHTMLDocument2.get_URL( ) calls (returns local AOL html file rather than web url)

Posted on 2006-07-06
8
894 Views
Last Modified: 2008-01-09
Dear Beloved Geniuses,

As part of a software package that needs to identify running browser instances and their document URL's, I have written some additional code to accommodate special circumstances present in IE browsers running under the AOL application.  This is necessary because my original code does not "see" those browser instances - AOL apparently sets some sort of flag that suppresses their IE instances from registering as a browser, which messes up my original method of retrieving browser instances using ShellWindows method calls.

The "specialty code" I've written to accommodate AOL uses the following algorithm:

1) Find top level windows that belong to the process "waol.exe" -
  a) EnumWindows( )
  b) for each top level window, GetWindowThreadProcessId( ), EnumProcessModules( ), and GetModuleFileNameEx( ) to check whether each window is owned by "waol.exe".
2) For each top-level window owned by waol.exe, use EnumChildWindows( ) and EnumChildWindowsEx( ) to find windows of the class "Shell DocObject View", then beneath that class, the child window of class "Internet Explorer_Server".
3) Having found such windows, I use their handles to attempt to retrieve the URL that the browser control is pointing at, using GetLocUrlFromHwnd (shown at the end of this posting)

The difficulty I'm having is this: while my enum code correctly identifies the browser control(s), and fetches a pointer to the IHTMLDocument2 interface, my call to get_URL( ) returns the following address:

"file:///C:/Documents and Settings/All Users/Application Data/AOL/C_America Online 9.0/ShopAssist/Apps/core/main.html"

rather than the URL of the page the browser is displaying.  I am pretty certain that things in my code are mostly correct, because I have checked the HWND for the browser control against results shown in Spy++, and the handle is dead-on, and my code has also not thrown a single exception, nor has it returned any errors.  Oh, and I have also gone to the trouble of "reaching farther down", by calling get_LocationUrl( ) from the IWebBrowser2 interface (retrieved from IHTMLDocument2 through calls made via IServiceProvider.)

One other special circumstance that may come to bear: ultimately, the consumer of this information is a Windows Service I have written - but this should not cause any grief, because the service obtains the URL information from a hidden helper application running in the logged-in user's security context by requesting said info through a .NET remoting call to the hidden application.  (i.e. the functionality I've described lives in the helper app, not in the service.)  Also, the code that DOES work (gets URLS for non-AOL browser instances) also lives in this helper app, so I'm pretty sure this has nothing to do with desktop/shell interaction problems.

Can someone help with this puzzle?  (By the way, I have also included the code within the aforementioned html disk file below, just in case that might provide part of the solution, or at least an indication of WHY I'm getting this local file address rather than a web address.)

Many thanks,

Skyline

The code:

#define qtseterr(a) {bErr = true; szErr = String::Copy(a);}

bool GetLocUrlfromHwnd(HWND hwndIn, String*& szRet)
{
   bool bRetval = false;
   System::String* szErr;
   bool bErr = false;
   try
   {
      IHTMLDocument2* pDoc;
      HMODULE hLib = LoadLibrary("OLEACC.DLL");
      if (NULL != hLib)
      {
         //grab proc address for ObjectFromLresult()
          typedef HRESULT (STDAPICALLTYPE *LPFNOBJECTFROMLRESULT)(LRESULT lResult, REFIID riid, WPARAM wParam, void** ppvObject);
         LPFNOBJECTFROMLRESULT pfObjFromLResult;
         pfObjFromLResult = (LPFNOBJECTFROMLRESULT) ::GetProcAddress(hLib, "ObjectFromLresult");
         if (pfObjFromLResult != NULL)
         {
            //call OFLR
            LRESULT lRes;
            UINT uiMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
            ::SendMessageTimeout(hwndIn, uiMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes);
            HRESULT hr;
            hr = (*pfObjFromLResult)(lRes, IID_IHTMLDocument2, 0, (void**)&pDoc);
            if (SUCCEEDED(hr))
            {
               //now have document interface pointer, go get the doc's URL
               BSTR bstrFeaster;
               hr = pDoc->get_URL(&bstrFeaster);
               if (SUCCEEDED(hr))
               {
                  bRetval = true;
                  szRet = String::Copy(bstrFeaster);
               }
            }//if success get doc object from LRES
            else
               qtseterr(S"get doc object failed")
         }//if success get proc address from loaded DLL
         else
            qtseterr(S"get proc address failed")
         FreeLibrary(hLib);
      }//if hLib not null (successful DLL load)
      else
         qtseterr(S"loadlibrary failed")
   }
   catch(Exception* ex)
   {
      qtseterr(String::Concat(S"Exception caught in GetLocUrlFromHwnd: ", ex->get_Message()))
   }
   if (bErr)
   {
      szRet = szErr;
   }
   return bRetval;
}//GetLocUrlFromHwnd

The HTML file:

<HTML>
<HEAD>
<TITLE>main page - sink & dispatch events and contains app iframes</TITLE>
<SCRIPT src="js/core.js"></SCRIPT>
<SCRIPT>
function createAppFrame(appName)
{
      var appUrl = "../" + appName + "/bs.html"
      var tagStr = "<iframe name='" + appName + "' src='" + appUrl + "' width=0 height=0></iframe>";
      document.writeln(tagStr);
}
</SCRIPT>
</HEAD>

<BODY topmargin="0" bottommargin="0" leftmargin="0" rightmargin="0" marginwidth="0" marginheight="0">
      <iframe name="ui" src="about:blank" width="100%" height="100%" frameborder="0" marginheight="0" marginwidth="0" scrolling="no"></iframe>

<SCRIPT>
for (var i=0; i< g_appObjArray.length; i++)
{
      createAppFrame(g_appObjArray[i].AppName);
}
</SCRIPT>
</BODY>      
</HTML>

There is also a javascript file that goes with this - I will post as a comment if someone needs it.  Anyone with a recent version of AOL can find the file (core.js) along the same path I mention for the above html file.
0
Comment
Question by:skyline_blvd
  • 4
  • 2
8 Comments
 

Author Comment

by:skyline_blvd
ID: 17053081
Addendum by author to paragraph 5 (mentions IWebBrowser2 etc.): the calls to IWebBrowser2.get_LocationUrl( ) result in the same bad results (main.html rather than the "real" url.)
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 17054650
What if your code is 100% correct?   What if waol.exe writes and displays that file (based upon the actual content of the page it is currently browsing, with perhaps a tweek here or there)?

The first thing I'd do is examine the HTML text of that main.html page.  Perhaps it contains an IFrame or something and there might be a way to obtain from *that* the "real" URL that waol.Exe is displaying.
0
 

Author Comment

by:skyline_blvd
ID: 17055749
Good point - I've examined that possibility, but am rather out of my element with respect to such things, Dan.  I felt rather like a guy stuck by the side of the road looking dumbly under the hood of my broken-down car - am not at ALL conversant in HTML, scripting, etc.   Which is the main reason I posted.  (If you can figure out what to do with that HTML, my friend, you get the points :)  In retrospect, perhaps this question belongs in a different category (Web Development, possibly?) - is there a way I can accomplish that move?

By the way, I will be traveling for the next week, so please, no one take offense if I fail to post/resolve points for a day or two; will not always be able to check this site frequently.  Thanks!
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 49

Expert Comment

by:DanRollins
ID: 17061624
You know the URL and it is a local file and you know its location on your hard disk.  So the first thing to do is use the Windows Explorer to find that file and then to open it in Notepad.  Copy it and give it an extension of .TXT then double-click the resulting file.
0
 

Author Comment

by:skyline_blvd
ID: 17109276
Thanks Dan - I knew how to view the source code of a page already ;) but I do appreciate the extra help lol!

So sorry for delaying so long, I have just returned from vacation with the family.  I'll be mucking around in that mystery file, as suggested, to see if I can find a way to dig further for IFrames (whatever that is) or other objects that may reveal the true URL being displayed.
0
 

Author Comment

by:skyline_blvd
ID: 17115210
I have found my bug-a-boo, thankfully - the short version of the story is that one of my trusted minions made an undocumented change to the collection to which the url(s) were being added that was causing only the last url added to be retained - in this case, the effect was that I was seeing only the listing for the (apparently hidden) browser window that utilises the aforementioned AOL html file.  So the bug in the derivative collection class was the culprit, making it *appear* that the code I've posted is not working when in fact it is.

I will be closing this issue now - hopefully its presence in the E-E database will prove helpful to folks who wish to fiddle with AOL-hosted browser windows!  Thanks to any and all who spent time on this!

Skyline
0
 
LVL 1

Accepted Solution

by:
GhostMod earned 0 total points
ID: 17185302
Closed, 500 points refunded.

GhostMod
Community Support Moderator
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

The following diagram presents a diamond class hierarchy: As depicted, diamond inheritance denotes when two classes (e.g., CDerived1 and CDerived2), separately extending a common base class (e.g., CBase), are sub classed simultaneously by a fourt…
In Easy String Encryption Using CryptoAPI in C++ (http://www.experts-exchange.com/viewArticle.jsp?aid=1193) I described how to encrypt text and recommended that the encrypted text be stored as a series of hexadecimal digits -- because cyphertext may…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now