Geoff Chappell - Software Analyst
This function obtains a URL for a standard location such as the start page or search page.
HRESULT _GetStdLocation ( PWSTR pszBuffer, DWORD cchBuffer, DWORD dwLocation);
The pszBuffer and cchBuffer argument describe a buffer (by address and capacity in Unicode characters, respectively) that is to receive the URL.
The dwLocation argument specifies the standard location for which the URL is sought. Supported values are:
|0x010E||get the Start Page (commonly called the home page)|
|0x010F||get the Search Page|
|0x0110||get the First Home Page (once), else the Start Page|
|0x0111||get the First Home Page, else the Start Page|
|0x0112||get the Local Page|
|0x0118||get the Search Bar|
The function returns zero for success, else an error code.
The notes immediately below describe the behaviour before the SHDOCVW version 6.0 from Windows Vista. In later versions, the function is exported but only as a forward to IEFRAME. The implementation in IEFRAME elaborates the behaviour significantly, most notably in the treatment of the First Home Page cases. The new behaviour is described in its own section (further below) as a variation of what was long established.
All the standard locations are configured together in the registry. They may each be in either of two keys, which are listed below in decreasing order of precedence:
|Values:||First Home Page
The function queries whichever of these registry values corresponds to dwLocation, defaulting to Start Page for an unsupported dwLocation. Data of any type is accepted as the URL, up to INTERNET_MAX_URL_LENGTH (0x0824) characters. The function resolves URL substitutions in whatever URL is obtained.
If a First Home Page is sought (i.e., if dwLocation is either 0x0110 or 0x0111) but a URL is not found for it, the function falls back to querying Start Page, again resolving substitutable parameters. The function thereafter behaves as if called to obtain the Start Page.
Without a URL, the function fails. The error code will be nothing more informative than E_FAIL, this being all that the function gets from URLSubRegQuery.
If querying the Start Page, including because of falling back from the First Home Page, the URL “about:home” might be problematic. The function spares the about protocol from the circular reference and uses “about:blank” instead. This defence dates from version 5.50. The obvious experiment with Windows 2000 confirms that setting “about:home” as the home page induces Internet Explorer to exhaust its stack when started.
The function copies a canonical form of the URL to the given buffer. Details of this canonicalisation (done by the undocumented ParseURLFromOutsideSource function) are beyond the scope of this article. If the canonicalisation fails, then presumably by oversight, the function does not fail even though it may leave the given buffer with undefined contents. If the canonicalised URL has the file protocol, the function converts the URL to a DOS pathname. Failure of this conversion is failure for the function, subject to the following paragraph.
If dwLocation is 0x0110 (to seek the First Home Page just once) and the function did not fall back to Start Page, the function deletes one First Home Page value from the registry. If the value is in both its eligible keys, it is deleted only from the key that has the higher precedence. Deletion is attempted even if the URL turned out to have the file protocol and conversion to a DOS pathname failed: presumably as an oversight, the function forgets the error code from that conversion and returns success.
In version 7.0 and higher, the registry values are recognised only if they have string data. This requirement comes about in two ways. As a side-effect of a code change in URLSubRegQuery, all the registry values except Start Page are permitted the REG_SZ and REG_EXPAND_SZ types, and environment variables in REG_EXPAND_SZ are expanded as part of retrieving the data. For Start Page only REG_SZ data is accepted. This is a consequence of a coding change in the function itself, so that this one registry value is queried a new way (using newly developed library code). Moreover, the Start Page value is subject to administrative control by accepting it from two extra keys:
One coding oversight that persisted throughout version 6.0 is corrected and another is side-stepped. If a URL is found and its canonicalisation into the given buffer fails, then the function fails, returning E_FAIL. If the canonicalisation has the file protocol, the function does not convert it to a DOS pathname (and thus cannot pick up an error to overlook).
All the other changes for version 7.0 are for the cases where dwLocation is 0x0110 or 0x0111. The registry value First Home Page becomes just one source of the First Home Page URL for these cases. Two others are also registry values, from the same keys, but the function may also load a hard-coded URL (in version 8.) or load from the string table in the IEFRAME resources. The following few paragraphs work through these alternatives in order of decreasing priority. Whichever first applies is the one the function uses instead of First Home Page.
First, if the current security settings for Internet Explorer are too risky, the function seeks the URL from the registry value Security Risk Page (with a fallback to Start Page). To see this case in practice with Internet Explorer 7, open Internet Options from the Control Panel, then in the Security tab select any zone, click Custom Level and then click on any radio button that is marked “not secure” in brackets. Close the dialog, dismissing all the protests, and then start Internet Explorer.
Whether the security settings are too risky is decided by the zone manager’s GetIESecurityState method. In version 7.0, this is evaluated when this function is first called with 0x0110 or 0x0111 as dwLocation, and is then remembered. In version 8.0, the evaluation is done at various times and the latest result is written to the registry, which is where this function retrieves it:
The security settings are considered too risky unless this value has non-zero data of the correct type.
In version 8.0, if the new feature known as InPrivate Browsing is on, the function selects the hard-coded URL “about:InPrivate”.
If add-ons are disabled, the function seeks the URL from the registry value Extensions Off Page (with a fallback to Start Page). The programmatic test for whether add-ons are disabled is the URLMON function CoInternetIsExtensionsOff. To turn extensions off, someone must call the URLMON function CoInternetSetExtensionsOff while FEATURE_ADDON_MANAGEMENT is not disabled. Since the latter is enabled by default for Internet Explorer, it is ordinarily possible to have Internet Explorer run without add-ons by starting IEXPLORE.EXE with its -extoff switch. This feature is important enough that Windows Vista provides two forms of user-interface support:
In version 7.0 only, the function goes to a lot of trouble about directing the user to a Microsoft web site, typically for something that Microsoft presents as completing the Internet Explorer installation. Microsoft may have intended that users be subjected to a Run Once page just the once, but what’s actually coded is that redirection persists until the first run completes. A successful run is supposed to have set two registry values. The first test for whether to show the Run Once page is therefore to look for those values. Again, each may be in either of two keys, which are listed in order of decreasing priority:
The function accepts data in a variety of types and sizes that evaluate as boolean. (Strictly speaking, the criteria are not this function’s but are those of SHRegGetBoolUSValue and would change incidentally were Microsoft ever to strengthen that function. For data of type REG_DWORD and when treating ≤ 4 bytes of REG_BINARY data as a dword, non-zero is true and zero is false. Data of REG_SZ or REG_EXPAND_SZ type is interpreted as a case-insensitive string: yes, true and 1 count as true; no, false and 0 count as false. Note that REG_BINARY is accepted even if there are fewer than 4 bytes of data. In particular, though a single non-zero byte must be interpreted as true, it seems that a single null byte might not be interpreted as false.)
If the RunOnceHasShown and RunOnceComplete values are both true, the function deems that the Run Once page has run and that it ought not run again. The function proceeds with seeking the First Home Page URL from the First Home Page registry value (with a fallback to Start Page).
An almost successful run may have set another registry value, in just one eligible key:
The function interprets the data as a FILETIME, i.e., a count of ten-millionths of seconds since the start of 1601. The function expects 8 bytes of any type but accepts fewer. If the RunOnceLastShown value is present and 3 days have not yet passed since the time represented by the data, then the function deems that the Run Once page has been shown, albeit inadequately, but need not be shown again so soon. The function proceeds with seeking the URL from the First Home Page value (with a fallback to Start Page).
The remaining decision of whether to show a Run Once page falls to a registry value that can be in any of four keys, again listed below in order of decreasing priority.
|Data:||0 to show the Run Once page;
1 to show the First Home Page;
2 to show the Welcome to Internet Explorer page
The DisableFirstRunCustomize registry value has user-interface support through the Group Policy Object Editor, as “Prevent performance of First Run Customize settings” in the Internet Explorer administrative template (shown under Windows Components).
If DisableFirstRunCustomize is 0, including by default, then the function deems that the Run Once page is to show. The URL is stored among the string resources in the MUI file for IEFRAME.DLL. The relevant string ID is 38744 if the operating system is Windows Vista or higher, else 38736. In the U.S. edition, the corresponding URLs are
If the function cannot retrieve the URL from the resources, it falls back to seeking a URL from the Start Page registry value.
If the URL is in a security zone that disallows the running of scripts, then showing the Run Once page would be essentially pointless. In recognition of this, the function sets the RunOnceHasShown and RunOnceComplete values to 1, so that the Run Once page should not be tried again. If running on Windows Vista or higher, the function then falls back to seeking a URL from the Start Page value. On earlier systems however, the function persists with the URL from the resources (but at least the Run Once page will not be tried on future calls to the function).
If DisableFirstRunCustomize is 2, then the function sets the RunOnceHasShown and RunOnceComplete values to 1, so that the Run Once page should not be tried again, but it proceeds with an alternative URL, again from the IEFRAME resources. The string ID is 38743. In the U.S. edition, the corresponding URL is
If the function cannot retrieve this URL from the resources, it falls back to seeking a URL from the Start Page registry value.
If DisableFirstRunCustomize is anything else, e.g., 1, the function sets the RunOnceHasShown and RunOnceComplete values to 1, so that the Run Once page should not be tried again, and then the function seeks the URL from the First Home Page registry value (with a fallback to Start Page).
If dwLocation is 0x0110 and the URL was found from either the First Home Page or Security Risk Page values (the latter perhaps as a coding oversight), the function deletes the First Home Page value from the HKEY_CURRENT_USER branch only.
The _GetStdLocation function is exported from:
The SHDOCVW build of version 6.0 from Windows Vista continues to export the function but only as a forward to IEFRAME.
The _GetStdLocation function exists in SHDOCVW from as far back as version 4.70, but it isn’t exported until version 5.0. The early versions work in ANSI. Except for this, the coding is so well established by version 4.71 that there is only one change until the function was moved to IEFRAME. In versions 4.71 and 4.72, ordinal 150 is instead an early implementation (in ANSI) of URLSubstitution.
Though this function dates from as long ago as 1999, it was still not documented by Microsoft as late as the January 2007 edition of the Windows Vista Software Development Kit (SDK).