Systems Internals Tips and Trivia
Copyright © 1996-1998 Mark Russinovich
Last Updated July 30, 1998

Miscellaneous NT Information

Introduction This page is an ever-expanding collection of NT information that we accumulate over time. You'll find practical tips as well useless trivia, with new items added at the top of the page.
BOOT.INI Option Reference There are number of BOOT.INI switches that are useful for driver developers that wish to test their drivers under a variety of different system configurations without having to have a seperate machine for every one. For example, limiting the amount of memory NT sees can be useful for stressing memory loads, and limiting the number of processors for testing scalability. I've compiled a complete list of the options that BOOT.INI currently supports.

/MAXMEM= This option will limit NT to using only the amount of memory you specify. The number is interpreted as MB. Example: /MAXMEM=16 would limit NT to using 16MB of the system's memory.
/BURNMEMORY= This option will cause NT to "forget" about the amount of memory specified, which limits memory like /MAXMEM. The value specified is interpreted as MB. Example: /BURNMEMORY=128 would have NT discard 128MB of the physical memory on the machine as unusable.
/ONECPU This option will have NT only enable one CPU of a multiprocessor system.
/NUMPROC= Only the number of CPUs specified will be enabled. Example: /NUMPROC=2 on a 4-way system will cause 2 of the 4 processors to be unused by NT.
/SOS Causes NT to print information about what drivers are being loaded as the system boots.
/BASEVIDEO Causes NT to use the standard VGA display driver when moving to GUI mode.
/NODEBUG Prevents kernel-mode debugging from being initialized. Overrides the specification of any of the three debug-related switches, /DEBUG, /DEBUGPORT and /BAUDRATE.
/CRASHDEBUG Its name implies otherwise, but this option is synonymous for /NODEBUG.
/DEBUG Enables kernel-mode debugging.
/DEBUGPORT= Enables kernel-mode debugging and specifies an override for the default serial port (COM1) to which a remote debugee is connected. Example: /DEBUGPORT=COM2.
/BAUDRATE= Enables kernel-mode debugging and specifies an override for the default baud rate (19200) at which a remote debugee will connect. Example: /BAUDRATE=115200.
/KERNEL=
/HAL=
These options pecify overrides of NTLDR's selection of the file named NTOSKRNL.EXE in the system root (<winnt>\system32) as the kernel's image file and of the file named HAL.DLL as the HAL image file. They are extremely useful for alternating between a checked kernel environment and a free kernel environment. If you wish to boot into a checked environment that consists solely of the checked kernel and HAL, which is typically all that is needed to test drivers, follow these steps on a system installed with the free build (retail NT):
1. Copy the checked version of the kernel from the checked build distrution CD to your <winnt>\system32 directory, naming it NTOSKCHK.EXE. If you are on a uniprocessor then copy NTOSKRNL.EXE, otherwise copy NTKRNLMP.EXE.
2. Copy the checked version of the HAL from the checked build distrution CD to your <winnt>\system32 directory, naming it HALCHK.DLL. To determine which HAL to copy, go into your <winnt>\repair directory and open setup.log in Notepad. Search for HAL.DLL and you'll find a line like "\WINNTF\system32\hal.dll = "halmps.dll","1a01c". The name to the right of the equal sign is the name of the HAL you should copy.
3. Make a copy of the default line in the system's BOOT.INI.
4. In the string description of the boot selection add something that indicates that the new selection will be for a checked build environment e.g. "Windows NT Server Version 4.0 CHECKED".
5. Add the following to the end of the new selection's line: /KERNEL=NTOSKCHK.EXE /HAL=HALCHK.DLL

You're done. Now you can select the new line to boot into a checked environment or select the pre-existing selection to boot into the free build.
/3GB This switch made its debut in NT 4.0 Service Pack 3 and is supported on all later releases of NT. It will cause the split between the user and system portions of NT's virtual address map to move from 2GB (2GB user, 2GB system) to 3GB (3GB user, 1GB system). Giving virtual memory intensive applications like database servers a larger address space can improve their performance. Note, however that for an application to take advantage of this feature two additional conditions must hold: The system must be part of the NT Enterprise suite (SP3 is not) and the application must be flagged as a 3-GB aware application.
/PCILOCK Stops Windows NT from dynamically assigning IO/IRQ resources to PCI devices and leaves the devices configured by the BIOS.
/NOSERIALMICE=[COMx | COMx,y,z...] Disables serial mouse detection of the specified COM port(s). Use this switch if you have a component other than a mouse attached to a serial port during the startup sequence. If you use /NOSERIALMICE without specifying a COM port, serial mouse detection is disabled on all COM ports.
Thanks to Jonas Fischer for pointing out the PCILOCK and NOSERIALMICE switches.
Hidden Registry Keys? A subtle but significant difference between the Win32 API and the Native API (see Inside the Native API for more information on this largely undocumented interface) is the way that names are described. In the Win32 API strings are interpreted as NULL-terminated ANSI (8-bit) or wide character (16-bit) strings. In the Native API names are counted Unicode (16-bit) strings. While this distinction is usually not important, it leaves open an interesting situation: there is a class of names that can be referenced using the Native API, but that cannot be described using the Win32 API.

How is this possible? The answer is that a name which is a counted Unicode string can explicitly include NULL characters (0) as part of the name. For example, "Key\0". To include the NULL at the end the length of the Unicode string is specified as 4. There is absolutely no way to specify this name using the Win32 API since if "Key\0" is passed as a name, the API will determine that the name is "Key" (3 characters in length) because the "\0" indicates the end of the name.

When a key (or any other object with a name such as a named Event, Semaphore or Mutex) is created with such a name any applications using the Win32 API will be unable to open the name, even though they might seem to see it. The program below, RegHide(source code is included), illustrates this point. It creates a key called "HKEY_LOCAL_MACHINE\Software\Systems Internals\Can't touch me!\0" using the Native API, and inside this key it creates a value. Then the program pauses to give you an opportunity to see if you can view the value using any Registry editor you have handy (Regedit, Regedt32 or a third-party Registry editor). Because Regedit and Regedt32 (and likely an third party Registry editor) use the Win32 API, they will see the key listed as a child of Systems Internals, but when you try to open the key you'll get an error. This is because the Registry editor will try to open "Can't touch me!" without the trailing NULL (which is interpreted as the end of the string) and won't find this name. After you've verified this exit the program and this special key will be deleted.

Download RegHide (24KB)

Fault Tolerance on Workstation?

One of the differences I highlighted in my November 1996 Windows NT Magazine article, "Inside the Difference Between Windows NT Workstation and Windows NT Server," was that fault tolerant disk configurations are only available on Server. This is because the Windows NT disk administrative program, Windisk.exe, checks to see if its running on a Workstation, and if so, does not display its Fault Tolerance menu, which contains the entries that are used to create mirrors and parity striped sets.

It turns out that whoever wrote the Workstation Resource Kit program FTEDIT was unaware of Microsoft's official policy on fault tolerance and Workstation: it appears you can use this utility to create mirrors and striped sets with parity on Workstations.

Update: several people have complained that this doesn't work, which isn't surprising since I left out an important step: the Fault-tolerant disk driver must be enabled. If you have an existing volume-set then it is already is, but if you don't, use a Registry editor to set the value of:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\FtDisk\Start

to 0. The next time you boot your workstation, the fault-tolerant drives you have created will be functional.

The Native API NT's native API are services that are core operating system services available to device drivers and user-mode applications. The Win32 subsystem relies heavily on this API, as do many Microsoft Windows NT Resource Kit utilities. There are over 200 system calls in NT's native API and only 21 of them are documented by Microsoft.
Idle Trivia Did you know that unlike all the other threads in an NT system, the idle-thread executes at an IRQL (interrupt request level) of DISPATCH_LEVEL (rather than PASSIVE_LEVEL)? See Advanced DPCs for more information.

On uniprocessor x86 systems the idle-thread actually performs a HLT (Halt) instruction, which effectively turns the CPU off to everything except for hardware interrupts.
Never-ending Quantum? In NT, as with most time-sharing operating systems, threads run in turns called quantums. Normally, a thread executes until its quantum runs out. The next time it is scheduled it starts with a full quantum. However, in NT a thread also gets its quantum refreshed every time its thread or process priority is set. This means that a thread can reset its quantum by calling SetThreadPriority (without changing its priority) before its turn runs out. If it continues to do this it will effectively have an infinite quantum. Why does NT do this? Its not clear, but it appears to be a bug.

NTOSKRNL's Main

NTOSKRNL.EXE, the core file of the kernel-mode component of Windows NT, contains the Cache Manager, the Executive, the Kernel, the Security Reference Monitor, the Memory Manager, and the Scheduler, among other things, and is in charge of getting NT up and running. You may be surprised to know that it has a standard main() that is executed when it is loaded by the OSLOADER:

//
// NTOSKRNL main
//
int main()
{
    //
    // Fire up NT!
    //
    KiSystemStartup();
    return 0;
}

Tuning Workstation for Server-like Loads

NT Workstation and NT Server have vastly different performance characteristics due to the internal tuning that the NT operating system, which is identical on both, performs. Most tuning parameters are inaccessible, but a few are located in the Registry. If you are running Server and you double-click on the Server entry of the Services tab in the Control Panel's Network applet, you will get a dialog that lets you determine what type of application you want the machine to be tuned for. Choices let you select between "Minimize Memory Used", "Balance", "Maximize Usage for File Sharing", and "Maximize Usage for Network Applications". This dialog box is not presented on Workstation installations. The various selections actually change the values of two Registry values:

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\LargeSystemCache

and

HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\Size

This table (which was derived from sessions with NTRegmon) presents the settings you should select on a Workstation to achieve the same effect you would get using the dialog box were your system a Server.

Tuning Target

LargeSystemCache

Size

Minimize Memory Used

0

1

Balance

0

2

File Sharing

1

3

Network Applications

0

3