<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Free Associations : ie</title><link>http://blogs.msdn.com/freeassociations/archive/tags/ie/default.aspx</link><description>Tags: ie</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>IEProcess.h - IE inproc APIs</title><link>http://blogs.msdn.com/freeassociations/archive/2008/11/04/ieprocess-h-ie-inproc-apis.aspx</link><pubDate>Wed, 05 Nov 2008 01:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9041900</guid><dc:creator>zekel</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/freeassociations/comments/9041900.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freeassociations/commentrss.aspx?PostID=9041900</wfw:commentRss><description>&lt;P&gt;IE8 beta1 introduced Loosely Coupled IE (LCIE) which gives tab a level of process isolation from the frame: &lt;A href="http://blogs.msdn.com/ie/archive/2008/03/11/ie8-and-loosely-coupled-ie-lcie.aspx" mce_href="http://blogs.msdn.com/ie/archive/2008/03/11/ie8-and-loosely-coupled-ie-lcie.aspx"&gt;http://blogs.msdn.com/ie/archive/2008/03/11/ie8-and-loosely-coupled-ie-lcie.aspx&lt;/A&gt;.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;For the most part this works pretty well.&amp;nbsp; But certain binary extensions (activeX objecst, BHOs, etc) that are already deployed have assumptions about window hierarchy and process model.&amp;nbsp; To get this to work the IE team has been diligently testing extensions and finding ways to fix them.&amp;nbsp; For the most part we do this by using the Detours library to redirect Windows APIs to private wrappers.&amp;nbsp; We have been using this technique since we added tabs.&amp;nbsp; For tabs we were just avoiding tabs contending for window modality by calling functions like MessageBox().&amp;nbsp; Our hook would effectively created a queue of modal dialogs avoiding confusing dialogs from hidden tabs, etc.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;But not all problems can’t be fixed by just detouring an existing API this way.&amp;nbsp; A reasonable example is when an application has a custom modal dialog manager.&amp;nbsp; This means that our hooks on DialogBoxParam() and related functions won’t be hit.&amp;nbsp; Other hooking options are complex and fragile so we opted to expose the "right" way for external developers.&amp;nbsp; IEProcess.h exposes functions for helping with this: &lt;A href="http://msdn.microsoft.com/en-us/library/cc994365(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc994365(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/cc994365(VS.85).aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;This API was designed with the idea that many components that are loaded in IE can actually be loaded elsewhere as well.&amp;nbsp; So instead of linking to IE dlls directly, some level of indirection is required.&amp;nbsp; This avoids the cost of loading a DLL when it won’t be used, and allows the IE dev team a little flexibility for how we expose these APIs.&amp;nbsp; First a caller detects whether any IEProcess exports with the following code:&lt;/P&gt;&lt;CODE&gt;&lt;PRE&gt;    HMODULE ieModule = IEProcess:GetProcessModule(); 
    //    if ieModule != NULL then there are exports available
&lt;/PRE&gt;&lt;/CODE&gt;
&lt;P&gt;After retrieving the module, the methods are grouped similar to COM interfaces, but are static, and exist for the lifetime of the process.&amp;nbsp; This is similar to doing GetProcAddress() for a set of functions:&lt;/P&gt;&lt;CODE&gt;&lt;PRE&gt;    static const IETabWindowExports* ieExports = GetTabWindowExports(ieModule);
    //   ieExports contains the methods we need to call
&lt;/PRE&gt;&lt;/CODE&gt;
&lt;P&gt;Now if you look here &lt;A href="http://msdn.microsoft.com/en-us/library/cc994365(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc994365(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/cc994365(VS.85).aspx&lt;/A&gt; again, you will see how we implemented our detour of DialogBoxParamW(), and this can be fairly easily replicated to a custom dialog manager.&amp;nbsp; WaitForTabWindow() queues your modal call with the tab; when it returns, its your turn.&amp;nbsp; Then take the lock with AcquireModalDialogLockAndParent(), which will create an appropriate top level window if required for security boundary reasons.&amp;nbsp; Then show the modal dialog, and call ReleaseModalDialogLockAndParent() when done.&amp;nbsp; It’s that easy!&lt;/P&gt;
&lt;P&gt;This is super straightforward if you always run in IE, but looks a little awkward to handle the error conditions if you run outside IE.&amp;nbsp; So I wrote a wrapper class that does pass through logic when running outside of IE.&amp;nbsp; It has an H and CPP file.&amp;nbsp; This is how MSHTML does its IE synchronization for HTML Dialogs, which have a custom dialog manager.&amp;nbsp; The header is below, and the CPP is attached.&lt;/P&gt;&lt;CODE&gt;&lt;PRE&gt;#pragma once

/// &lt;SUMMARY&gt;
/// Helper class that does delay load binding to the IEProcess
/// export tables with fallback logic for easy pass through.
/// &lt;/SUMMARY&gt;
class IEProcessHelper
{
public:

    /// &lt;SUMMARY&gt;
    /// Detect whether per-process exports are enabled for this process.
    /// This does it's binding on demand and the result is cached.
    /// &lt;/SUMMARY&gt;
    static bool IsIEProcess();    

    /// &lt;SUMMARY&gt;
    /// Retrieve the tab window related exports for this process.
    /// If they aren't available it returns a table of fallbacks 
    /// with pass through logic so that this never returns NULL.
    /// This does it's binding on demand and the result is cached.
    /// &lt;/SUMMARY&gt;
    static const IETabWindowExports* TabWindow();

private:
    
    static HRESULT WaitForTabWindowNotImpl(
        __in    bool    allowUnknownThread,  
        __in    HWND    hwndParentProposed,  
        __out   HWND*   phwndParentActual);  

    static HRESULT AcquireModalDialogLockAndParentNotImpl(
        __in        HWND    hwndParentProposed,  
        __out       HWND*   phwndParentActual,
        __deref_out HANDLE* phModalDialogLock);

    static void ReleaseModalDialogLockAndParentNotImpl(
        __in_opt HANDLE hModalDialogLock);

private:
    static const IETabWindowExports _TabWindowExportsNotImpl;
    static const IETabWindowExports* _TabWindowExports;
    static HMODULE _hmoduleIEProcess;
    static bool    _checkedIEProcess;
};
&lt;/PRE&gt;&lt;/CODE&gt;
&lt;P&gt;This simplifies our detour so that the following is the new calling pattern, and doesn’t require any kind of fallback logic.&lt;/P&gt;&lt;CODE&gt;&lt;PRE&gt;INT_PTR WINAPI Detour_DialogBoxParamW(
        HINSTANCE hInstance, LPCWSTR lpTemplateName, 
        HWND hwndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
{
    INT_PTR nRes = -1;

    HRESULT hr = IEProcessHelper::TabWindow()-&amp;gt;WaitForTabWindow(
            false, hwndParent, &amp;amp;hwndParent);
    if (SUCCEEDED(hr))
    {
        HANDLE hModalDialogLock;
        hr = IEProcessHelper::TabWindow()-&amp;gt;AcquireModalDialogLockAndParent(
                hwndParent, &amp;amp;hwndParent, &amp;amp;hModalDialogLock);
        if (SUCCEEDED(hr))    
        {
            nRes = Real_DialogBoxParamW(hInstance, lpTemplateName, 
                    hwndParent, lpDialogFunc, dwInitParam);

            IEProcessHelper::TabWindow()-&amp;gt;ReleaseModalDialogLockAndParent(
                    hModalDialogLock);
        }
    }
    
    return nRes;
} 
&lt;/PRE&gt;&lt;/CODE&gt;
&lt;P&gt;Check out MSDN related docs for running in Protected Mode: &lt;A href="http://msdn.microsoft.com/en-us/library/bb250462.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb250462.aspx"&gt;http://msdn.microsoft.com/en-us/library/bb250462.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9041900" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/freeassociations/attachment/9041900.ashx" length="2079" type="text/plain" /><category domain="http://blogs.msdn.com/freeassociations/archive/tags/ie/default.aspx">ie</category></item><item><title>The Bizarre and Unhappy Story of 'file:' URLs</title><link>http://blogs.msdn.com/freeassociations/archive/2005/05/19/the-bizarre-and-unhappy-story-of-file-urls.aspx</link><pubDate>Thu, 19 May 2005 19:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:420059</guid><dc:creator>zekel</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/freeassociations/comments/420059.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freeassociations/commentrss.aspx?PostID=420059</wfw:commentRss><description>&lt;P&gt;For my first blog entry, I will start with something I wrote for my team back in 1997 (reedited for this blog) that has been helpful to generations of subsequently bewildered developers:&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr&gt;
&lt;P&gt;Go back to&amp;nbsp;1995 and a small team dreaming an impossible dream of the&amp;nbsp;Internet on Windows!&amp;nbsp; URLs were young, so young they still hadn't been seen in a television ad....&amp;nbsp; &lt;/P&gt;
&lt;P&gt;IE1.0 was just a fledgling trying to get some features that Mosaic (or the looming competitor) didn't have.&amp;nbsp; Since we shipped with Win95 and a big feature for Win95 was Long File Names, so IE needed to have support for spaces in names.&amp;nbsp; Since there was no spec for the "file" protocol scheme (heck there was practically no spec for any protocol) we added automagical escaping spaces.&amp;nbsp; We happily escaped spaces all over the place, and since nobody used our browser it didnt make a whits difference.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Now IE began to mature and grew into a precocious 3-year-old, and when the powers that be noticed this, they decided that 3 was such a big number that the browser needed a new image.&amp;nbsp; That image was componentization.&amp;nbsp; The browser was taken and split in three major parts.&amp;nbsp; One part became mshtml (for rendering HTML) another shdocvw (for hosting DocObjects), and the third was wininet and urlmon (two binaries that were basically inseparable for downloading and caching content).&amp;nbsp; Unfortunately a key component from the platform was missing, so it was replicated into each of the other components.&amp;nbsp; That was an URL parsing platform.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;No one component could agree with the others about the best way to handle the wild URLs that were so plentiful.&amp;nbsp; So each component came up with slightly different rules, although very logical, based on its personal fantasies of the one true URL.&amp;nbsp; The fantasies were fairly similar but the devil is in the details and these URLs went through a lot of metamorphoses on each trip down the stack to the wire.&amp;nbsp; Now each breed of URL had its own issues with these transformations, but in the end all children must be pushed from the nest to learn to fly on their own.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Enter IE4, Nashville, Win98, the next generation of everything.&amp;nbsp; And with it the new patron saint of URL parsing.&amp;nbsp; Now someone undertook the plight of the underrepresented URLs very seriously and wished to give them the respect they deserved.&amp;nbsp; Some cried with fear, and others with joy, but none could debate the necessity of a savior.&amp;nbsp; So the little URLs were taken and given a safe place to live and be loved:&amp;nbsp; shlwapi.dll.&amp;nbsp; And the saint went amongst the browser and the browser's friends and said, "Let no one but the chosen ones touch or talk or molest these URLs, and there will be a peace among us."&amp;nbsp; Some resisted, but they were put down as heretics should be and a peace came upon the land.&amp;nbsp; Except for the one abused problem URL:&amp;nbsp; file:.&lt;/P&gt;
&lt;P&gt;No one had been quite as abused as the the little file: URL.&amp;nbsp; This URL was special because we had always used files and DOS paths (and no one at the time knew about path canonicalization attacks), everyone was quite sure what they looked like , acted like, and even tasted like.&amp;nbsp; It didn't help that the file: protocol remained in RFC limbo as a platform/OS specific protocol.&amp;nbsp; So the browser and the browser's little friends would take turns dressing a DOS path like an URL in a pink bunny suit and undressing the URL with a pair of rusty scissors, pretending it was the same DOS path they started with.&amp;nbsp; Only the simplest of URLs was able to withstand this abuse, and it soon became clear that something would have to be done, lest the little file: URLs go off on their own and be lost forever.&lt;/P&gt;
&lt;P&gt;After much praying and meditation and consultation, it was finally decided that file: URLs must have two forms, one being the well formed easily communicable URL form and the other a legacy mutant form of a DOS path.&amp;nbsp; These two forms had different purposes, and soon different personalities.&amp;nbsp; The URL form lived happily inside the browser, but any time the browser needed to talk about the file: URL with its friends, it would clone and mutate the URL into its ugly half DOS form.&lt;/P&gt;
&lt;P&gt;What this MEANS:&lt;/P&gt;
&lt;P&gt;There are two kinds of file: URLs.&amp;nbsp; The first is the well formed URL style.&amp;nbsp; This is allowed query strings, fragment IDs, escape sequences and all the other goodies that URLs are supposed to support.&amp;nbsp; We call this a healthy file: URL.&amp;nbsp; The other kind is basically a DOS path with "file://" stuck on the front.&amp;nbsp; We use this for legacy communication with outsiders only.&amp;nbsp; We call this the legacy file: URL. Examples: &lt;PRE&gt;&lt;FONT size=4&gt;
DOSPATH:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c:\windows\My Documents 100%20\foo.txt &lt;BR&gt;HEALTHY:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;file:///c:/windows/My%20Documents%20100%2520/foo.txt
&lt;BR&gt;LEGACY:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file://c:\windows\My Documents 100%20\foo.txt &lt;BR&gt;
&lt;BR&gt;DOSPATH:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; \\server\share\My Documents 100%20\foo.txt &lt;BR&gt;HEALTHY:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;file://server/share/My%20Documents%20100%2520/foo.txt &lt;BR&gt;LEGACY:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;file://\\server\share\My Documents 100%20\foo.txt &lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;NOW all of the Url* APIs in shlwapi, and thus everyone in IE4, understand the difference between these two types of URLs and act accordingly.&amp;nbsp; as long as a client of the APIs, doesn’t try to access the data directly, there is no issue whatsoever.&amp;nbsp; in other words as long as you dont have code anywhere that looks like this: &lt;PRE&gt;&lt;FONT size=4&gt;LPTSTR GetFilePath(pszUrl)
&lt;BR&gt;{
&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (0 == lstrcmpn("file://", pszUrl, sizeof("file://")))
&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return pszUrl + sizeof("file://");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NULL;&lt;BR&gt;}&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;but instead always call shlwapi like this:&lt;BR&gt;&lt;PRE&gt;&lt;FONT size=4&gt;PathCreateFromUrl(pszUrl, pszPath, cchPath, dwFlags);&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;You will always be happy and golden.&amp;nbsp; Straying from the path is straying into unknown lands.&amp;nbsp; There are of course flags that you can pass into some of the APIs that will change the form the file: URLs when they come out, but I highly recommend not using it for any reason, as it just increases the chances of creating more bizarre unsupportable behavior.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=420059" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freeassociations/archive/tags/psz/default.aspx">psz</category><category domain="http://blogs.msdn.com/freeassociations/archive/tags/ie/default.aspx">ie</category></item></channel></rss>