The Shell used to get all the cool APIs :)

After I posted my article on the SHAutoComplete, I mentioned it to one of my co-workers.  His response “I’m not surprised – The shell gets all the cool APIs”.   And they do.

For instance, my “new favorite” Win32 API: RegGetValue began it’s life as the SHRegGetValue function.  But increasingly, many of the cool shell APIs are moving out of the shell, and that’s a good thing.

Over the past couple of releases of Windows, there have been a great number of “shell” helper APIs that have gotten “promoted” out of the shell and transformed into Win32 core APIs.  One of the reasons for that has been the ongoing Architectural Layering effort initiated by some of the teams in the Core OS Division.  I wrote about this layering process a couple of years ago, the MinWin effort that was discussed recently is another benefit of the archlayer work.

The SHRegGetValue API was one of the APIs flagged by the layering issue as being more appropriate for core OS functionality – the analysis done by the layering team showed that a number of low level components in operating system were calling into the shell DLLs because the shell helper functions provided some convenient functionality that wasn’t present in the lower layers.

As a result, a number of shell APIs were recreated as kernel32 APIs.  You can see some of them on the “What’s New in Windows Vista” page on MSDN.  They include:

There are undoubtedly others that have been migrated over time, these were just a few that I picked up in a couple of minutes of searching.

In general, this is a good thing for both the shell and the core OS teams.  The more applications clients that move away from the shell APIs and into the kernel32 equivalents, the better it will be for the entire ecosystem.

This is another example of how a relatively small change to an application (removing a dependency on shlwapi32.dll) can have significant benefits to the application – as I’ve mentioned in previous posts, each DLL you load consumes 4 private pages and takes between 500 thousand and a million cycles to load.  If you can remove that dependency, your application will thus load faster.

Comments (5)

  1. Anonymous says:

    That the shell has so many APIs that should be at lower level tells me that the shell team has been taking up the slack that some of the core teams have been leaving. As an example, most or all of the path APIs should have been part of the file system APIs, especially since a number of these functions are non-trivial when you take into account UNC paths, Unicode/native escape prefixes, slash vs. backslash and repeated slash behavior, etc. I’ve been a bit encouraged by the API additions in Windows Server 2003 and Vista, as it seems there’s some movement to fill in the missing holes in the rougher APIs, like the one for the console subsystem.

  2. Anonymous says:

    Sadly we still have to create our own wrappers around RegGetValue if we want to use it conveniently without making our code complex and unreadable. This is because, as is typical, the new API does not offer a mode which allocates memory for us.

    Having to call something twice (or if you are pedantic in a loop, in case the size changes between calls) with an allocation in between  isn’t good. I do understand that if you already have a buffer that’s probably large enough then it’s good for performance not to have an API which always allocates memory, that later must be freed, but that is actually quite rare, as is (or should be!) calling APIs like this in a tight loop, so at least having a flag which says "allocate the damn memory for me!" would be so much nicer and save us all writing our own wrappers. (Plus a corresponding way to free the memory, obviously.) In the rare cases where doing that allocation in the API matters the flag could be omitted from the call.

    Of course we may still write wrappers in order to use convenient types/containers which clean themselves up (e.g. std::wstring) but that’s C’s fault and I’m not expecting a C++ version of the Win32 API or anything; I’d just like to be able to use API functions without having to write silly wrappers that handle the common case where it feels like I (and so many other developers) am doing work that the API should do for me (us).

  3. Anonymous says:


    It’s the price win32 pays for being an API targeted to perform well for low-level C programs.  The only path to better behavior is to use a good higher-level wrapper, like your custom one or .NET.  

  4. Anonymous says:

    Give it a flag which makes auto-allocation option and it will still perform equally well for the things that need it while being far more convenient in most other cases.