In Longhorn, Win32 will no longer be the principal API. It will, of course, continue to be supported; 20-year-old DOS applications still run on the latest version of Windows, and likewise, Win32 applications will also continue to work for the foreseeable future. But just as DOS and 16-bit Windows applications were superseded by Win32 applications, so in Longhorn will Win32 become the "old way" of doing things. In Win32's place is a new API called WinFX (pronounced "Win Effects"). WinFX is a significant milestone in the history of the Windows API, as it puts .NET at the center of the platform. While Win32, the main API for previous versions of Windows, is a C-style API, WinFX is designed primarily to be used by .NET languages. In other words, it is a managed API. Moreover, it is a superset of the existing .NET Framework.
Judging by the discussions on various newsgroups and mailing lists, many seasoned Windows developers seem to have a hard time believing that Longhorn's new APIs really will be pure .NET. The topic has come up almost every day on the various WinFX Microsoft newsgroups since the API's announcement, and it seems that many people think that a .NET-only API cannot possibly exist, and that there must be a 'real' Win32 API underneath it all.
The idea that Win32 must be lurking somewhere beneath the covers presumably originates in part because of the way today's .NET Framework is implemented. Many of the classes in the Framework Class Library are wrappers on top of Win32 functionality. For example, Windows Forms puts a .NET face on classic Win32 features such as HWND, MSG, and WndProc. Likewise, the various classes in System.Net and System.Net.Sockets ultimately wrap the services provided by the Windows Sockets API in Win32.
However, there's no technical requirement for new WinFX functionality to wrap a corresponding Win32 API. Indeed, we can look to existing Windows and .NET technology to see why this need not be the case.
It is tempting for experienced Windows developers to think of Win32 as the fundamental API of Windows. All of the unmanaged language runtimes shipped by Microsoft to date rely on Win32, even though they may hide it behind some language-specific wrapper such as the standard C library, or the unique world view that is Visual Basic 6. Similarly, the .NET Frameworks that have shipped so far all rely on Win32 as well. However, Win32 is not an island.
Win32 itself relies on underlying services from the Windows kernel. If you look inside some of the DLLs that implement the Win32 API (such as User32.dll) you will find that many of the functions have very short implementations; they use the Pentium's INT instruction to make a system call that does the real work.
One of the reasons for this is that Windows NT was originally designed to support multiple 'subsystems'. Win32 was just one of these. The first versions of NT also shipped with an OS/2 subsystem and a POSIX subsystem, each of which presented a completely different API, but all of which ran on top of the same set of system services. Of course, OS/2 and POSIX are no longer especially relevant in Windows, making the subsystem support seems like a historical footnote. However, there are still good reasons for certain Win32 APIs to be implemented as little more than a system call, even if subsystems had never been invented, as there are some system services that can only be implemented in the kernel itself.
It has always been possible to bypass Win32 and use the Windows kernel services directly. However, developers rarely do this because such code is unlikely to be portable from one version of Windows to the next. Not only is this low-level API not documented, it can also differ from platform to platform. The kernel in the Windows NT, 2000, and XP product line is very different from the underlying kernel in Windows 95, 98, and ME. Each version of Windows has its own implementation of the Win32 DLLs (GDI32.dll, User32.dll, and so on) to bridge the gap between the common public Win32 API and the platform-specific, low-level system API.
For applications that need to run on more than one version of Windows (that is, most Windows applications) it makes no sense to try and use the low-level system calls. However, WinFX will be installed as part of the operating system just like Win32 is today. This means that unlike the current redistributable versions of the .NET Framework, any particular version of WinFX will not need to be able to work on multiple versions of Windows. The relationship between WinFX and the OS kernel can become much more like the relationship between, say, User32.dll and the OS kernel. (Nobody expects to be able to copy the Windows 98 version of User32.dll onto their Windows XP machine and have it work. The same will be true of the files that make up WinFX.)
Because WinFX will be a part of the OS, it will be able to have a much closer relationship with the low-level system services. In theory, WinFX could act as a peer of Win32 rather than having to be its client; it could effectively be a distinct subsystem. In practice, that's unlikely to happen any time soon for two reasons. First, where Win32 already provides the necessary services, there seems little point in WinFX reinventing the wheel. So expect those parts of the .NET Framework that are wrappers around Win32 (such as Windows Forms) to remain so for the foreseeable future. The second reason for not making WinFX an entirely independent subsystem is that P/Invoke would be tricky to implement if Win32 wasn't still there somewhere.
Nevertheless, although we are likely to carry on seeing wrappers where Win32 already provides appropriate services, there's no reason for new services to be exposed at the Win32 level and then wrapped by WinFX. For platform services that are new to Longhorn, their only public API will be in WinFX. There may be corresponding undocumented system calls used by WinFX (just as there are today for many Win32 APIs) but there is no reason for there to be an equivalent new public Win32 API; Longhorn can cut out the middle man and have WinFX make system calls directly. In the long term, we may even see Win32 relegated to an isolated subsystem just as the old 16-bit world is today, only supported for the benefit of legacy applications that still depend on it. We have seen this kind of transformation where the wrapper and the underlying API swap places once before in Windows. Remember Win32s include a set of wrappers for the Windows 3.1 API, enabling 32-bit applications to run on 16-bit systems. In some ways, the current .NET Frameworks are reminiscent of Win32s: they allow applications to use the new API even though the underlying OS is fundamentally rooted in the old way of doing things. Over time, we saw DOS and 16-bit Windows cease to be the underlying platform, while Win32 transformed from a wrapper into a native API. WinFX marks the start of a similar transition, with .NET turning from a wrapper into the native API. .NET need not be a set of wrappers any more than Win32 needs to be a set of wrappers for 16-bit versions of Windows.
The ability of WinFX to link directly to system services, bypassing Win32, is not the only way in which new Longhorn features can be exposed in WinFX but not Win32. Many features will be implemented entirely in managed code with no need for any help from lower levels of the platform at all.
There are already many examples of pure managed features in the shipping versions of .NET Framework. For example, you can make extensive use of the XML functionality in the current versions of .NET without the framework ever making a call into Win32. Likewise, although ASP.NET integrates with IIS in the Win32 world, the vast majority of the value that it adds over the unmanaged ISAPI extension mechanism is implemented in managed code. The ASP.NET page caching mechanism has no Win32 equivalent, neither do the key parts of its object model. (HttpRequest, HttpResponse, and friends may look reminiscent of the classic ASP objects, but they are not wrappers. They were designed to look very similar to the ASP object, in order to ease the transition to ASP.NET, but they are all implemented entirely in managed code.)
The same will be true for much of the new functionality in Longhorn. There will, of course, be some things which involve new platform features all the way from WinFX's public API right down to kernel mode-- the new 'Avalon' graphics model being the most obvious example. However, there will be many more features implemented entirely in managed code. For example, although Avalon relies on platform support at all levels for performance reasons, a considerable amount of its functionality will reside entirely in managed code. (It would be rather inefficient if every single interaction your code had with Avalon objects caused calls all the way down into the lowest levels of the OS.)
To view the .NET Framework as being merely a wrapper around Win32 is to ignore a large part of the benefit that it offers. Even with the versions shipping today, there is a considerable amount of functionality that is implemented entirely in managed code. This will be true to an even greater extent in WinFX on Longhorn. Moreover, where new features require support from the lower layers of the platform, WinFX will not need to have a Win32 API that it can wrap, as it will be able to use the low-level system API directly, just as Win32 does today. For anyone writing Windows applications today, the message is clear: managed code is the way of the future.
Ian Griffiths is an independent consultant specializing in medical imaging applications and digital video. He also works as an instructor, teaching courses on .NET for DevelopMentor. Ian holds a degree in computer science from Cambridge University.
Return to ONDotnet.com
Copyright © 2009 O'Reilly Media, Inc.