Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles

Designing testability into your app means smaller tests that are cheaper to create, easier to understand, faster to run, and much simpler to debug.

Jeremy Miller

MSDN Magazine December 2008

...

Read more!

Windows Communication Foundation (WCF) provides an easy role-based system and a more powerful and complex claims-based API for implementing authorization in services.

Dominick Baier and Christian Weyer

MSDN Magazine October 2008

...

Read more!

This month we explain how pseudo variables and format specifiers provide a wealth of information for use in debugging.

Kenny Kerr

MSDN Magazine December 2008

...

Read more!

This month's column explains how to use Windows HTTP Services, or WinHTTP, the new, powerful API for implementing HTTP clients.

Kenny Kerr

MSDN Magazine August 2008

...

Read more!

Bryan Sullivan discusses the new SDL for Web applications and Agile projects with more compressed release cycles.

Bryan Sullivan

MSDN Magazine November 2008

...

Read more!

Also by this Author

The Win32 Portable Executable File Format (PE) was designed to be a standard executable format for use on all versions of the operating systems on all supported processors. Since its introduction, the PE format has undergone incremental changes, and the introduction of 64-bit Windows has required a few more. Part 1 of this series presented an overview and covered RVAs, the data directory, and the headers. This month in Part 2 the various sections of the executable are explored. The discussion includes the exports section, export forwarding, binding, ...

Read more!

The Microsoft .NET platform uses metadata and assemblies to store information about components, enabling cross-language programming and resolving the infamous DLL Hell problem. This article describes the use of metadata for easy linking and loading of assemblies, the relationship between metadata and concepts such as IDL and type libraries, and the metadata hierarchy. The process of reading metadata from assemblies for easy versioning is also described. Although Microsoft provides the MSIL disassembler, IDLASM, and MetaInfo.exe for accessing ...

Read more!

Matt Pietrek

MSDN Magazine November 2000

...

Read more!

Matt Pietrek

MSDN Magazine September 2001

...

Read more!

Matt Pietrek

MSDN Magazine March 2002

...

Read more!

Popular Articles

This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

David Callahan

MSDN Magazine October 2008

...

Read more!

We take a look at planned support for parallel programming for both managed and native code in the next version of Visual Studio.

Stephen Toub and Hazim Shafi

MSDN Magazine October 2008

...

Read more!

ADO.NET Data Services provide Web-accessible endpoints that allow you to filter, sort, shape, and page data without having to build that functionality yourself.

Shawn Wildermuth

MSDN Magazine September 2008

...

Read more!

We introduce you to the benefits of building composite applications with the Composite Application Guidance for WPF from Microsoft patterns & practices.

Glenn Block

MSDN Magazine September 2008

...

Read more!

One-time passwords offer solutions to dictionary attacks, phishing, interception, and lots of other security breaches. Here's how it all works.

Dan Griffin

MSDN Magazine May 2008

...

Read more!

Our Blog

Every month, the CLR team gives us insight into the core of managed code, .NET programming best practices, technologies underlying the CLR and .NET Framework, and other tips and suggestions.

In the December 2008 issue of MSDN Magazine, Erika Fuentes and Eric Eilebrecht cover some common issues developers encounter when tuning ...

Read more!

Silverlight and SharePoint provide a simple, yet powerful, infrastructure for building intranet and extranet applications with sophisticated user interface designs and interactions.

In the November 2008 issue of MSDN Magazine, Steve Fox and Paul Stubbs demonstrate how to build a SharePoint Web Part as a wrapper for a Silverlight application.

...

Read more!

Because Windows Workflow Foundation (WF) is based on a runtime that manages the execution of workflows and activities, testing must, in almost all cases, involve the use of the runtime – and this can introduce some interesting challenges.

In the November 2008 issue of MSDN Magazine, Matt Milner presents some techniques for unit testing ...

Read more!

It’s helpful to think about secure design from a more holistic perspective by using threat models to drive your security engineering process.

In the November 2008 issue of MSDN Magazine, Michael Howard proposes using the threat model to help drive other SDL security requirements, primarily code review priority, fuzz testing priority, ...

Read more!

Visual Studio 2008 Team Foundation Server Build (better known as Team Build) is a core feature of Team Foundation Server 2008. Microsoft designed Team Build to be an industrial-strength build automation tool.

In the November 2008 issue of MSDN Magazine, Brian A. Randell introduces you to Team Build 2008 and walks you through the process ...

Read more!

New information has been added to this article since publication.
Refer to the Editor's Update below.

Windows Server 2003
Discover Improved System Info, New Kernel, Debugging, Security, and UI APIs
Matt Pietrek
Code download available at: WindowsServer2003.exe (1,024 KB)
Browse the Code Online

This article assumes you're familiar with Windows, .NET, and C++
Level of Difficulty 1 2 3
SUMMARY
There's a lot to say about Windows Server 2003. First of all, it's the first operating system with built-in .NET Framework support, and it's the first 64-bit OS from Microsoft. But wait, there's more! There are lots of new features and APIs in this version as well. For instance, Windows Server 2003 features Hot Add Memory and a number of other arcane new tidbits. There are new APIs for handling threads, directories, and files, and new features like the low fragmentation heap for managing memory and system information. There's vectored exception handling and new UI APIs as well.
OS internals expert Matt Pietrek takes a look at the additions he finds most interesting and useful so you'll have a good place to start when you dive into Windows Server 2003.
I really am too young to be saying this, but I remember the good old days when developers eagerly awaited the release of a new version of Windows®. What new goodies might it contain, and what cool things could you do with them? With the advent of the Microsoft® .NET Framework, it's become fashionable in some circles to pretend that Windows is static and not worthy of discussion. Some people seem to think it doesn't matter which version of Windows you're running underneath.
As you might guess, I'm not in that group. While I'm as big a fan of Microsoft .NET as the next person, I still eagerly scan header files and compare the exports of system DLLs from each new version of Windows. I want to know what the fine folks on the Microsoft Windows team have been up to.
The latest and greatest operating system from Microsoft is Windows Server™ 2003, which is in its release candidate phase as I write this. In this article, I'll examine what new goodies are available in Windows Server 2003 for application-level programmers. However, before diving into the new APIs, there's some background information that helps put all this in context.
Let's first establish what "new" means. Windows Server 2003 is intended to replace the Windows 2000 Server family (Server, Advanced Server, and Datacenter Server.) As such, many of the OS features that originally appeared in Windows XP technically fall into the "new" category for the purposes of this article.
Actually, the majority of the new APIs (relative to Windows 2000) first appeared in Windows XP, rather than in Windows Server 2003. There's a good reason for that. Many moons ago, the successor to Windows 2000 was codenamed Whistler, and its betas included both workstation and server versions. In 2001, Microsoft decided that the server version needed to bake a bit longer, and so released the consumer and workstation versions as Windows XP. The intention was that the server versions would be released shortly thereafter. As you now know, that delay turned into a year and a half. Some of this time can be accounted for by the Microsoft Trustworthy Computing Initiative, wherein developers at Microsoft stopped new development in order to look for security issues in their code.
The key point is that up to a certain date, both the workstation and server versions of Whistler were essentially feature complete and used the same code base. The time between the release of Windows XP and Windows Server 2003 was primarily spent making it as robust as possible. Thus, it's not at all surprising that many of the new Windows Server 2003 features and APIs are also available in Windows XP.
The version numbers used in the Platform SDK header files give evidence of how little the public interface to the OS (that is, the APIs) has changed since Windows XP. To enable Windows XP (and later) APIs, you define _WIN32_WINNT to 0x0501 (that is, Windows XP is internally thought of as Windows 5.01.) For Windows Server 2003, the required #define value for _WIN32_WINNT has only been bumped to 0x0502. You'll see _WIN32_WINNT #defines used in the sample programs later.
Windows Server 2003 may hold the record for the most number of name changes during its incubation. It started out codenamed Whistler and then became "Windows 2002 Server." Subsequently, the .NET initiative permeated all things Microsoft, and it was rechristened "Windows .NET Server." After another delay, the name changed to "Windows .NET Server 2003." Finally, wiser heads prevailed, and the name became "Windows Server 2003." It wouldn't surprise me if I missed a name change in there somewhere.
[ Editor's Update - 2/15/2004: Windows Server 2003 only includes the .NET Framework 1.1, although version 1.0 can be installed on it manually.] Since .NET has been covered so extensively in MSDN® Magazine and elsewhere, I won't count the .NET Framework as a new API for the purposes of this article.
Besides being the first system with built-in support for the .NET Framework, Windows Server 2003 also holds the distinction of being the first Microsoft 64-bit server OS. Windows XP Professional has a 64-bit version, but the demand for 64-bit Itanium-based workstations hasn't been that great so far. With a 64-bit server OS finally available, companies with huge databases will probably start the transition to 64-bit Windows. A 64-bit version of SQL Server™ is slated to ship alongside the 64-bit versions of Windows Server 2003.
Windows Server 2003 will ship in six configurations initially. For the Intel x86 CPU, the low end is the Web Edition server for basic Web Services. Next up the ladder is the Standard Edition, intended as a departmental server. Up a notch from that is the Enterprise Edition, targeted at medium to large enterprises. Finally, for massive database systems operating on up to 32 processors there's the Datacenter Edition. The remaining two configurations are the 64-bit Itanium versions of both Enterprise Edition and Datacenter Edition.
As an interesting aside, the 64-bit versions of Windows Server 2003 won't include the .NET Framework. Apparently, the 64-bit version of .NET isn't yet ready to ship, so it will be included in a later version.
There are lots of new features in Windows Server 2003 that I won't go into any detail on, but are still worth mentioning, just for their coolness. For example, Internet Information Services (IIS) is now at version 6.0. It has had a major architectural change and big performance gains are attained by doing more work with a kernel-mode listener. If desired, you can run it in the three IIS 5.0 protection levels as well.
Other exotic new features in Windows Server 2003 include, but are not limited to, Volume Shadow Copy, Hot Add Memory, and Non-Uniform Memory Access (NUMA) support.
The Volume Shadow Copy service provides a way to do complete backups, even on files that are open at the time of the backup. While backups aren't my favorite topic, I think it's pretty cool how this functionality was implemented transparently using drivers. Volume Shadow Copy, as well as many other additions, are covered in the article "Windows XP: Kernel Improvements Create a More Robust, Powerful, and Scalable OS," by Mark Russinovich and David Solomon in the December 2001 issue.
Hot Add Memory is one of those totally exotic features that make you wonder what those wacky hardware guys will dream up next. It's the ability to add RAM to a system while it's running. The OS automatically detects and starts using the RAM when you plug it in. For this to work, however, you need to be running a system designed to support it. In the Microsoft documentation, you'll find the Surgeon General's warning to not just blindly add RAM to any old system while it's turned on—bad things will happen.
NUMA is a high-end technology used in enterprise-class multiprocessor systems. The idea is that memory and processors are grouped together into cells. A processor accessing memory within its cell can access that memory faster than memory in another cell. The NUMA support in Windows causes the scheduler to attempt to keep related processes running in the same cell.
Before jumping into the blood and guts of new APIs in Windows Server 2003, there's one obligatory disclaimer I need to add. What follows is subjective and not comprehensive. I went through hundreds of header files and beta documentation pages and culled what I thought was most interesting. I had to make a lot of tough choices as to what to include and what to leave out. Generally, for me to select a feature to include here, it had to be a user-mode API that's not completely esoteric or tied to one particular program. There's lots of new functionality at the device driver level, but that's outside the scope of this article.

New KERNEL APIs
I'll begin the tour with kernel-level functionality. You might think that this means KERNEL32 (I'll get to that soon enough). True system programming fanatics know that NTDLL is the real guts of the user-mode kernel. I've compared the exports from the Windows Server 2003 version of NTDLL.DLL to the Windows 2000 version. As you might expect, lots of APIs were added and a few have disappeared. Big deal, they're all undocumented, right? Not so fast!
As I was comparing all those .H files between different versions of the Platform SDK, I came across a very interesting file in the October 2002 version. It's named WINTERNL.H. This is definitely a file to hold on to. It could disappear in future Platform SDKs. At the top of WINTERNL.H is a big three-paragraph warning about how all the data structures and APIs are subject to change and intended for use only by Windows core components. (Not like we haven't seen this before, eh?)
Anyhow, so what goodies are in WINTERNL.H? Unfortunately, not as many as you'd like. But there are tantalizing hints of well-known, yet still undocumented data structures. For example, you'll see both the Process Environment Block (PEB) and Thread Environment Block (TEB) defined. However, most of the fields are listed as reserved. Likewise, the structures and prototypes necessary to call NtQueryInformationProcess and NtQueryInformationThread are there. However, there are a variety of books and Web sites that provide many more details about these APIs and structures than WINTERNL.H does. Admittedly, nothing in this file is new in Windows Server 2003. However, the SDK that accompanies Windows Server 2003 is where this file first appeared.
Why am I making a big fuss about this? It's significant because Microsoft is finally admitting that there are lots of interesting things that aren't documented. A few other APIs in WINTERNL.H are worth noting: NtCreateFile, NtOpenFile, NtClose, and NtWaitForSingleObject. These APIs are the guts of the user mode implementation of common KERNEL32 APIs. Likewise, RtlUnwind is a key API used in structured exception handling (SEH), as described in my January 1997 article in Microsoft Systems Journal "A Crash Course on the Depths of Win32® Structured Exception Handling". It's highly unlikely that RtlUnwind will change. If it did, a very large percentage of existing applications would fall flat on their faces.

Processes, Threads, and Fibers, Oh My!
Moving on to KERNEL32 land, my first group of APIs, shown in Figure 1, relate to processes and threads. With one exception, they all retrieve some piece of information about a process or thread. GetThreadId takes a thread handle and returns the associated thread ID. It's a similar story for GetProcessId. It's hard to believe these functions weren't in the Win32 API 10 years ago! IsWow64Process tells you if the calling process is a 32-bit process running under 64-bit Windows.

GetProcessHandleCount
IsProcessInJob
IsWow64Process
CreateJobSet
GetProcessIdOfThread
GetThreadId
GetProcessId
GetThreadIOPendingFlag
GetCurrentProcessorNumber
SetProcessWorkingSetSizeEx
GetProcessWorkingSetSizeEx
RestoreLastError
GetProcessHandleCount returns the number of handles that the specified process has open. It's the same value seen in the Performance Monitor data or in the Task Manager. RestoreLastError is an enigma. It's code is identical to SetLastError. It's unclear to me why it was made into a separate API.
To demonstrate some of these new APIs, check out the ProcessesAndThreads program in Figure 2. The code is self-explanatory, so I won't delve into it here. To build it (and the other sample programs), you will need at least the October 2002 Platform SDK, with its Include and Lib directories at the head of the compiler and linker's directory search order. If you're running Windows XP, you can build it to use just the Windows XP subset of the APIs. Simply uncomment the #define W2K3SERVER line near the top and rebuild.
//-------------------------------------------------------------------
// Matt Pietrek
// MSDN Magazine, 2003
// Program: ProcessesAndThreads
// Purpose: A demonstration of the Windows XP/Windows Server 2003 Process/
// Thread APIs
//-------------------------------------------------------------------
#include "stdafx.h"

// comment out to get just the XP APIs
#define W2K3SERVER  1

int main(int argc, char* argv[])
{
    DWORD dwThreadID = GetCurrentThreadId();
    DWORD dwProcessID = GetCurrentProcessId();
    printf( "ProcessId: %X  ThreadId: %X\n", dwProcessID, dwThreadID );

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID );
    if ( !hProcess )
    {
        printf( "unable to open process\n" );
        return 0;
    }

    // Show OpenThread()
    HANDLE hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, dwThreadID );
    printf( "hProcess: %IX  hThread: %IX\n", hProcess, hThread );

    // Show GetProcessHandleCount()
    DWORD dwHandleCount;
    GetProcessHandleCount( hProcess, &dwHandleCount );
    printf( "Handle Count: %u\n", dwHandleCount );

    // Show IsProcessInJob()
    BOOL bIsInJob;
    IsProcessInJob( hProcess, NULL, &bIsInJob );
    printf( "IsProcessInJob: %s\n", bIsInJob ? "true" : "false" );

    // Show GetProcessId()
    printf( "Process ID from hProcess: %X\n", GetProcessId( hProcess ) );

    // Show IsWow64Process
    BOOL bIsWow64Process;
    IsWow64Process( hProcess, &bIsWow64Process );
    printf( "IsWow64Process: %s\n", bIsWow64Process ? "true" : "false" );

    BOOL bIOIsPending;
    GetThreadIOPendingFlag( hThread, &bIOIsPending );
    printf( "IoIsPending: %s\n", bIOIsPending ? "true" : "false" );

#ifdef W2K3SERVER
    // Show GetProcessWorkingSetSizeEx()
    DWORD wsFlags;
    SIZE_T wsSizeMin, wsSizeMax;
    GetProcessWorkingSetSizeEx( hProcess, &wsSizeMin, &wsSizeMax, 
                                &wsFlags );
    printf( "Working Set: min:%IX  max:%IX  flags:%X\n",
            wsSizeMin, wsSizeMax, wsFlags );

    // Show GetProcessIdOfThread()
    DWORD dwProcessIdFromThread = GetProcessIdOfThread( hThread );
    printf("Process ID obtained from thread ID: %X\n", 
           dwProcessIdFromThread);

    // Show GetThreadId();
    printf("Thread ID obtained from thread handle: 
           %X\n",GetThreadId(hThread));

#endif

    return 0;
}
In addition to threading support, Windows Server 2003 adds some new Fiber APIs, shown in Figure 3. The big news here is the addition of fiber local storage (FLS). The APIs are used identically to their thread local storage (TLS) counterparts. A slot is allocated via the FlsAlloc function. To set or retrieve values, use the FlsGetValue and FlsSetValue function. When you are done with the slot, you call FlsFree.

FlsAlloc
FlsGetValue
FlsSetValue
FlsFree
ConvertFiberToThread
ConvertThreadToFiberEx
CreateFiberEx
Just for grins, I looked into the implementation of the FLS functions. At offset 0xFB4 in the Thread Environment Block is a pointer to a data structure. Eight bytes into this structure is an array of 128 slots. These slots are conceptually the same as the TLS slots. As the thread switches from fiber to fiber, the pointer at offset 0xFB4 is updated accordingly.
The ConvertFiberToThread API undoes the effect of ConvertThreadToFiber. Once called, no more fiber functions can be called on the thread. The remaining two APIs listed in Figure 3 are just "Ex"-tended versions of existing APIs. CreateFiberEx is just like CreateFiber, but with the ability to specify the stack reserve size. ConvertThreadToFiberEx is interesting, though. In the original fiber implementation, the floating point, MMX, and SSE registers weren't saved and restored across fiber switches to improve performance. The new API lets you specify that these registers need to be saved and restored as well.

Vectored Exception Handling
Perhaps the most exciting addition to KERNEL32 is vectored exception handling (VEH), which provides additional flexibility in how to process exceptions. I covered vectored exception handling in depth in my September 2001 Under The Hood column in MSDN Magazine, so I'll just give a brief synopsis here along with an illustration of the process in Figure 4.
Figure 4 Vectored Exception Handling 
Traditional structured exception handling (SEH) with its __try/__except mechanisms is inherently thread specific. Exceptions can only be handled by the thread that set up a handler. (The compiler and OS handle all the messy details of this and expose the relatively simple __try/__except syntax to you.) More importantly, with SEH you might set up a handler, only to have the exception grabbed first by another handler that doesn't know how to deal with the exception properly.
Vectored exception handling works more like a traditional notification callback scheme. To handle exceptions, call the AddVectoredExceptionHandler API, passing it the address of your exception callback function. When an exception occurs, the callback function receives a pointer to an EXCEPTION_POINTERS structure. This is the same structure that SEH callbacks can receive via the GetExceptionInformation API. From fields in the EXCEPTION_POINTERS structure, you can learn the exception code (for instance, 0xC0000005) and the register values (via the included CONTEXT structure).
The VEH callback chooses to either handle the exception or chain it onto the next handler in the list. It determines what happens by returning the appropriate value from the callback. Each process has a linked list of VEH callbacks. As part of processing an exception, the OS walks the VEH list and calls the handlers. To remove a handle from the list, use the RemoveVectoredExceptionHandler API.
How does vectored exception handling coexist with SEH? Good question! Immediately before walking the SEH chain, the system walks the vectored exception handler list. Put another way, VEH handlers have priority over SEH handlers. To see vectored exception handling in action, check out the VEHDemo program in Figure 5. VEHDemo installs a couple of vectored exception handlers and uses a structured exception handler to show how VEH and SEH work together. The resulting output from running the VEHDemo program is shown in Figure 6.
In VectoredExceptionHandler, EIP =00411BBA
In VectoredExceptionHandler, EIP =00411BBA
In VectoredExceptionHandler, EIP =00411BBA
In SecondVectoredExceptionHandler - handling it
In VectoredExceptionHandler, EIP =00411BBB
In VectoredExceptionHandler, EIP =00411BBB
In VectoredExceptionHandler, EIP =00411BBB
In SecondVectoredExceptionHandler - NOT handling it
Caught the exception in Function1
//-------------------------------------------------------------------
// Matt Pietrek
// MSDN Magazine, 2003
// Program: VEHDemo
// Purpose: A demonstration of Vectored Exception Handling
//-------------------------------------------------------------------

#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

LONG
WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
    // Stupid handler that does nothing except print out the faulting EIP
    printf( "In VectoredExceptionHandler, EIP =%p\n",
            (PVOID)(DWORD_PTR)ExceptionInfo->ContextRecord->Eip );

    // Don't handle the exception here.  Let normal processing continue
    return EXCEPTION_CONTINUE_SEARCH;
}

LONG
WINAPI SecondVectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
    // If the faulting EIP points to a HLT instruction, just skip past
    // it, to show us "Handling" an exception
    if ( *(PBYTE)ExceptionInfo->ContextRecord->Eip == 0xF4 )
    {
        printf( "In SecondVectoredExceptionHandler - handling it\n" );
        ExceptionInfo->ContextRecord->Eip++;
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    else    // For everything else, we won't handle the exception here
    {
        printf("In SecondVectoredExceptionHandler - NOT handling it\n");
        return EXCEPTION_CONTINUE_SEARCH;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    // Add a vectored exception handler.  In fact, add the same
    // handler 3 times, to prove that they handlers are stored
    // in a linked list.  This handler always returns "keep looking"
    AddVectoredExceptionHandler( 1, VectoredExceptionHandler );
    AddVectoredExceptionHandler( 1, VectoredExceptionHandler );
    AddVectoredExceptionHandler( 1, VectoredExceptionHandler );

    // And a second vectored handler that knows how to handle a HLT
    // caused exception, but nothing else
    AddVectoredExceptionHandler( 0, SecondVectoredExceptionHandler );

    __try
    {
        __asm   HLT         // Cause a privileged instruction fault
        *(int *)0 = 0;      // Access Violate by dereferencing NULL ptr
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {   // This handler will catch the *(int *)0 = 0 fault
        printf( "Caught the exception in Function1\n" );
    }

    return 0;
}

Directories and Files
A few new APIs have been added in the File and Directory category, shown in Figure 7. SetDllDirectory adds an arbitrary set of directories that will be searched when the system looks for a DLL. The system searches the specified path(s) after the application load directory but before anywhere else, such as the system directory. The documentation for SetDllDirectory describes the exact search order and makes for interesting reading. GetDllDirectory returns whatever value has been previously set by calling SetDllDirectory. GetSystemWow64Directory is used for finding the 32-bit system directory when on a 64-bit system.

GetDllDirectory / SetDllDirectory
NeedCurrentDirectoryForExePath
GetSystemWow64Directory
SetFileShortName
CheckNameLegalDOS8Dot3
SetFileValidData
GetVolumePathNamesForVolumeName
FindFirstStream / FindNextStream
ReOpenFile
A little-known fact about the NTFS file system is that it supports multiple streams in a file. This is tricky to explain in a limited space, but the gist is that multiple files can be collectively referred to by a single file name. Most files only have a single default stream associated with them, and that's what most Win32 APIs report about. To create a stream other than the default stream, simply append a colon (:), followed by the stream name. For instance, you could use Notepad to create a file/stream called abc.txt:MyStream. In the Windows Explorer window, you'll see a zero-byte abc.txt file. However, the abc.txt:MyStream exists. The normal Win32 APIs simply don't report any information about it.
In Windows Server 2003, this situation is remedied somewhat. The FindFirstStream and FindNextStream APIs enumerate through all the streams in a file. To demonstrate their use, I wrote the FindFirstStream program shown in Figure 8. To use it, simply pass it a file name. If there are any streams beyond the default unnamed stream, it lists them all. Here is the output for a file, a.txt, with three streams—abc, def, and ghi:
a.txt:abc:$DATA
a.txt:def:$DATA
a.txt:ghi:$DATA
//-------------------------------------------------------------------
// Matt Pietrek
// MSDN Magazine, 2003
// Program: FindFirstStream
// Purpose: A demonstration of the Windows XP/Windows Server 2003 File 
// Stream APIs
//-------------------------------------------------------------------
#include "stdafx.h"

int main(int argc, char * argv[])
{
    if ( argc != 2 )
        return 0;

    WIN32_FIND_STREAM_DATA streamData;

    wchar_t wszFileName[512];
    mbstowcs( wszFileName, argv[1], 0xFFFFFFFF );
    HANDLE h = FindFirstStreamW( wszFileName, FindStreamInfoStandard,
                                &streamData, 0 );
    if ( h == (HANDLE)ERROR_INVALID_HANDLE )
    {
        // printf( "unable to being stream enum for file %s\n", argv[1] );
        return 0;
    }
    while ( 1 )
    {
        if ( !FindNextStreamW( h, &streamData ) )
            break;
        printf( "%ls%ls\n", wszFileName, streamData.cStreamName );
    }

    // Do we need to close the stream handle???

    return 0;
}
The ReOpenFile API is used for taking an existing file handle and getting another handle that has a different set of access rights. A typical use is where you have code that has only a file handle and doesn't know the associated file name. If your code needs access rights or a sharing mode different than the existing handle has, ReOpenFile provides a way to attempt to obtain those rights. Of course, ReOpenFile ensures that the newly requested access rights and sharing mode are legal. It also lets you guard against pipe impersonation attacks.
CheckNameLegalDOS8Dot3 has one of those fluky API names. This API is useful for checking if a file name can be used on a file allocation table (FAT) file system volume.
You may recall that with the advent of long file names (beyond 8.3), the OS needed a way to refer to the file using standard 8.3 conventions. The system has an algorithm for mapping between the long and short versions of the name. These files are easily picked out because the short version ends with a tilde (~), followed by a number (for instance, "foobar~1.txt"). The new SetFileShortName API allows you to override the system's default short file name. To use it however, the target file needs to be on an NTFS volume.

Memory and System Information
In the memory allocation arena, Windows Server 2003 and Window XP have a feature called the low-fragmentation heap. This heap algorithm avoids fragmentation by allocating all blocks from 128 predetermined different block-size ranges, called buckets. When an application needs to allocate memory from the heap, the heap chooses the bucket that's able to hold the requested block with the least wasted space. The system uses the traditional heap for blocks greater than 16KB. To use the low-fragmentation heap, call HeapSetInformation, passing it the appropriate heap handle and flag value. All heaps default to "normal" Win32 heap behavior until HeapSetInformation is called. To determine which behavior a heap is using, call the HeapQueryInformation API.
In the area of system information, there's a motley collection of new interfaces, as you can see in Figure 9. GetSystemRegistryQuota provides you with the current size of the registry, as well as the maximum allowed size. GetSystemTimes returns the length of time that all processors have spent in the idle state, in kernel mode, and in user mode.

GetLargePageMinimum
GetSystemRegistryQuota
GetSystemTimes
GetNativeSystemInfo
TzSpecificLocalTimeToSystemTime
SetFirmwareEnvironmentVariable
GetFirmwareEnvironmentVariable
CreateMemoryResourceNotification
QueryMemoryResourceNotification
GetLogicalProcessorInformation
The GetNativeSystemInfo is intended for 32-bit programs running under 64-bit Windows. It returns a SYSTEM_INFO structure filled in as if it were called from a native 64-bit program. For instance, running an x86 program on an Itanium machine, the SYSTEM_INFO.dwPageSize would be 8192 bytes, rather than the 4096 bytes that you'd get from calling GetSystemInfo. The SystemInfo program in Figure 10 shows GetSystemInfo being used, as well as a few of the other new system information APIs.
//-------------------------------------------------------------------
// Matt Pietrek
// MSDN Magazine, 2003
// Program: SystemInfo
// Purpose: A demo of the Windows XP/Windows Server 2003 System Info APIs
//-------------------------------------------------------------------
#include "stdafx.h"

// Uncomment to get Windows Server 2003 APIs as well
// #define W2K3SERVER   1

int main(int argc, char * argv[])
{
    // Show GetSystemRegistryQuota();
    DWORD dwQuotaAllowed, dwQuotaUsed;
    GetSystemRegistryQuota( &dwQuotaAllowed, &dwQuotaUsed );
    printf( "Quota allowed: %uK, Quota used: %uK\n",
            dwQuotaAllowed/1024, dwQuotaUsed / 1024 );

    // Show GetSystemTimes()
    FILETIME IdleTime;
    FILETIME KernelTime;
    FILETIME UserTime;
    GetSystemTimes( &IdleTime, &KernelTime, &UserTime );

    const DWORD filetimeDivisor = 1000000000 / 100;

    printf( "IdleTime:   %I64u seconds\n",
        *(PDWORD64)&IdleTime / filetimeDivisor );

    printf( "KernelTime: %I64u seconds\n",
        *(PDWORD64)&KernelTime / filetimeDivisor );

    printf( "UserTime:   %I64u seconds\n",
        *(PDWORD64)&UserTime / filetimeDivisor );

    // Show GetNativeSystemInfo().  If you're running in a WOW session
    // (e.g., an X86 app running on IA64), it'll return the capabilities
    // of the actual OS, not the WOW info.  If not running in WOW, you'll
    // get the same info as GetSystemInfo
    SYSTEM_INFO sysInfo;
    GetNativeSystemInfo( &sysInfo );
    printf( "Native System Info - Processor type: %u  page size: %X\n",
            sysInfo.dwProcessorType, sysInfo.dwPageSize );

#ifdef W2K3SERVER
    printf( "Large Page Minimum size: %IX\n", GetLargePageMinimum() );
#endif
    return 0;
}
GetLogicalProcessorInformation returns information that is pertinent both to NUMA systems and to Intel's Hyperthreaded CPUs (wherein a single CPU has multiple execution units). The API returns an array of SYSTEM_LOGICAL_PROCESSOR_INFORMATION structures.
The CreateMemoryResourceNotification is a way for applications to receive a notification when the available physical memory is running low without having to constantly poll the value. The API creates a handle that can be passed to the WaitForXxx family of functions. The handle is signaled when free memory drops below a threshold. According to the documentation, the threshold is 32MB per 4GB of memory on the system. You can also check the memory status directly using the QueryMemoryResourceNotification. The system can also notify you when available free physical memory is high, but I doubt this will be a heavily used capability.

Debug APIs
In the realm of debugging, there's a small set of new APIs. The most exciting has to be DebugSetProcessKillOnExit. Up until now, if you were acting as a debugger for another process, there was no way to stop acting as a debugger. You simply couldn't detach from a process being debugged. When you act as a debugger for another process, one of your threads is the debug thread, and processes all the debug notification messages. Normally, if this thread terminates, the debuggee process terminates as well. The DebugSetProcessKillOnExit API changes this behavior. By passing FALSE, you tell the system to stop requiring the debug thread to process messages for the debuggee.
In a related vein, you'll find DebugActiveProcessStop, which tells the system to detach the specified process from whatever process is debugging it. It can only be called by the thread that called DebugActiveProcess or CreateProcess. Since a debugger thread can conceivably debug multiple processes at the same time, DebugActiveProcessStop needs the parameter that indicates which process to detach from.
The DebugBreakProcess is just like DebugBreak, except that it applies to the specified process rather than to the current thread. The API works by creating a thread in the target process, much like CreateRemoteThread does. The newly created thread invokes a breakpoint instruction, which causes the normal SEH mechanism to take over. For developers, this usually means that the Just-In-Time debugging dialog comes up.
The final new debugging API is CheckRemoteDebuggerPresent. It's similar to the IsDebuggerPresent API in that it tells you if a process is running under the control of a debugger process. IsDebuggerPresent tells you if your process is being debugged, while CheckRemoteDebuggerPresent lets you query about any process for which you have a handle.

Side-by-side Execution
Much has been made of the side-by-side installation and execution feature in the .NET Framework. However, these same capabilities are built into Windows Server 2003 and Windows XP. The key to these capabilities are the new activation context (ActCtx) APIs, shown in Figure 11.

CreateActCtx
AddRefActCtx
ReleaseActCtx
ActivateActCtx
DeactivateActCtx
GetCurrentActCtx
QueryActCtx
ZombifyActCtx
FindActCtxSectionString
FindActCtxSectionGuid
An activation context is a set of system-managed data structures that contain information used to cause an application to use a particular DLL version or COM object instance, based upon a manifest file. Manifest files use the XML format (no surprise there!) and look very similar to .NET manifests. The use of activation contexts could easily be an article on its own, so I'll defer to the SDK documentation. However, it's interesting to note that certain system DLLs are enabled for side-by-side execution, with their corresponding .H files now using the activation context APIs. For a prime example, examine a recent version of COMMCTRL.H. There are a ton of inline functions with names like IsolationAwareImageList_Add. These inline functions show the activation context APIs in action. You'll also see some clever tricks with C++ macros to keep existing code compiling without any changes.
There's one final Kernel32 API that doesn't fit nicely into any other category. GetModuleHandleEx should have been included in the Win32 API years ago. The key capability it adds is finding an HMODULE when given an address within that module. If you've ever written debugging or diagnostic code, you've probably been in the situation where you had a code address and needed to determine which DLL it came from. It was possible to accomplish this in an awkward way using VirtualQuery, but GetModuleHandleEx is much more elegant.
Unlike its predecessor API (GetModuleHandle), GetModuleHandleEx affects the module's reference count, unless you explicitly tell it not to. Depending on the specified flags, it can increment the reference count, leave it unchanged, or pin the DLL in memory for the lifetime of the process. The GET_MODULE_HANDLE_EX_FLAG_PIN flag addresses one of my nagging concerns. Let's say you called GetModuleHandle to retrieve a module handle. In a multithreaded program, it's possible that another thread could unload the DLL and load another DLL at the exact same address. All this can happen between the time the first thread gets the HMODULE and when it starts using it. By pinning the module in memory, you're guaranteeing that the HMODULE you get will be valid when you use it later.