The NT Insider

Update: Two New System Calls in NT 4.0 SP2!
(By: The NT Insider, Vol 4, Issue 1, Jan-Feb 1997 | Published: 15-Feb-97| Modified: 30-Oct-02)

 Click Here to Download: Code Associated With This Article Zip Archive, 21KB

With NT 4.0 Service Pack 2, Microsoft quietly introduced two new Win32 calls, with corresponding support in NT 4.0's kernel-mode components (NTOSKRNL.EXE). These two calls, ReadFileScatter and WriteFileGather, provide Win32 programs with the ability to read data from an uncached file into a discontiguous buffer, and conversely, to write data to an uncached file from a discontiguous buffer. However, these new calls are not referenced from any component shipped as part of SP2.

So what are the new calls doing there, and what could have prompted Microsoft to suddenly augment the Win32 API in the second service pack to a major operating system release? The answer is also one that highlights the tight integration between the operating systems and applications groups at Microsoft: the performance of a major Microsoft application, SQL Server, is significantly enhanced by using these new services. An on-line Knowledge Base article called "Performance Enhancements for SQL Server Under Windows NT" documents the functions (That?s an article I?d look at for Win32 updates, wouldn?t you?), which are very useful for applications that perform their own data caching like SQL Server. It is widely known that in the markets that these products occupy, a performance edge held for only a short period of time can be an enormous competitive advantage, and Microsoft has allegedly given themselves just such an advantage.

To level the playing field and further document some useful APIs, we?re presenting these nifty routines for those of you that may have applications that can take advantage of them (wouldn?t it be nice if we could all get our own system calls added to NT?). In addition, we?ll cover the NT API forms of the calls, which will provide insight into the way Win32 connects to NTOSKRNL services.

This article is organized as follows:

v     The Win32 API This section describes the two new Win32 API functions in a manner similar to the Win32 SDK.

v     The NT API This section describes the three new NT kernel-mode API functions for use from a device driver, in a manner similar to the Windows NT DDK.

v      Conclusion Some notes and observations on using the new APIs.

v      Example An example of ReadFileScatter can be found at the OSR web site, http://www.osr.com.

The Win32 API

ReadFileScatter

BOOL ReadFileScatter(
HANDLE
hFile, // handle of file to read
LARGE_INTEGER lpBuffer[], // array describing buffer
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // address of number of bytes read
LPOVERLAPPED lpOverlapped // address of structure for data
);

The ReadFileScatter function reads data from a non-cached file into a possibly discontiguous buffer, which is described as an array of page-aligned virtual addresses, with each address specifying the location of one page in the buffer. SP2 supports only the asynchronous form of this call, where an overlapped I/O structure is passed as a parameter. The file must be located on a local drive.

Parameters

Parameter

Description

hFile

Identifies the file to be read. The file handle must have been opened with GENERIC_READ access, as well as with FILE_FLAG_OVERLAPPED and FILE_FLAG_NO_
BUFFERING
flags.

lpBuffer[]

This is a large integer aligned array of virtual addresses that describe the buffer being read into. Each entry in the array represents one page of the buffer and must be a page-aligned address. Enough entries must be present to describe a buffer with pages for the pages indicated by nNumberOfBytesToRead.

nNumberOfBytesToRead

Specifies the number of bytes to be read from the file. This must be page-size granular (i.e. 4096, 8192, etc.).

lpNumberOfBytesRead

In the final implementation, this parameter will be used in a manner identical to the use of the same parameter in ReadFile. In the SP2 implementation, this field must be NULL, or the function will fail.

lpOverlapped

Points to an OVERLAPPED structure. Unlike for ReadFile, in the SP2 implementation of ReadFileScatter, this parameter is required, and consequently the hFile must have been created with FILE_FLAG_OVERLAPPED. See the Win32 SDK or Visual C Help for a description of this data structure.

Return Values

If the function succeeds, the return value is non-zero. If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks

This function's API is constructed to mirror ReadFile's. However, in SP2 corners were cut with the implementation. Specifically, in ReadFile, lpOverlapped is an optional parameter and its absence will result in synchronous behavior of the call. In SP2's ReadFileScatter, lpOverlapped is mandatory and the synchronous behavior has not been implemented. To use ReadFileScatter the caller must create an event to pass in lpOverlapped, that will be signaled when the operation completes. At that time, GetOverlappedResult should be called to obtain the return status.

WriteFileGather

WriteFileGather has a prototype identical to ReadFileScatter's, and its SP2 implementation suffers the same limitations.

The NT API

Whereas it is possible for a Win32 program to obtain the addresses of ReadFileScatter and WriteFileGather, the related NT API functions are currently not accessible to device driver writers. Microsoft must release an updated NTOSKRNL.EXE which exports the functions and an NTOSKRNL.LIB that allows for linking to them. See the remarks section at the bottom for a hack that makes them accessible in an unconventional manner.

NtReadFileScatter

NTSTATUS NtReadFileScatter(
IN HANDLE FileHandle,
IN HANDLE Event, /* optional */
IN PIO_APC_ROUTINE UserApcRoutine, /* optional */
IN PVOID UserApcContext, /* optional */
OUT PIO_STATUS_BLOCK UserIosb, /* optional */
IN LARGE_INTEGER BufferDescription[],
IN ULONG BufferLength,
IN PLARGE_INTEGER ByteOffset,
IN PULONG Key /* optional */
);

Parameters

Parameter

Description

FileHandle

Handle to a file that has been opened for GENERIC_READ access and no intermediate buffering. The file must be located on a local drive.

Event

Handle to an event that will be signaled when the operation has completed.

UserApcRoutine

Points to an APC routine that will be called with the function completes. If this parameter is non-null, then Event must be null and vice versa.

UserApcContext

If an APC routine is specified, then this parameter will be passed to the routine when the operation completes.

UserIosb

Pointer to an I/O status structure that will be filled in when the operation completes.

BufferDescription

An array of large integers that describe the buffer being read into. The array must be large integer aligned, and contain virtual addresses that describe the buffer. Each entry is a large integer virtual address that specifies one page of the buffer. Note that the high DWORD of the large integers are ignored by SP2, but are present for future evolution into 64-bit NT.

BufferLength

The number of bytes to be read. This value must be an integral multiple of the system page size.

ByteOffset

Large integer offset in the file at which the read operation will begin.

Key

Passed directly to the file system, which may use it to control the order of I/O operations. No native NT file system currently honors the key parameter.

Return Value

NtReadFileScatter returns the NTSTATUS value that a lower level driver sets in the I/O status block for the request.

Comments

While the SP2 Win32 interface to this function (ReadFileScatter) is not completely implemented, NtReadFileScatter is fully implemented. The function is similar to NtReadFile, but performs the additional job of creating an MDL that describes the buffer specified in BufferDescription. The MDL is prepared using a new support function, MmProbeAndLockSelectedPages, which is described below.

NtWriteFileGather

NtWriteFileGather has the same interface as NtReadFileScatter.

MmProbeAndLockSelectedPages

VOID MmProbeAndLockSelectedPages(
IN OUT PMDL
MemoryDescriptorList,
IN LARGE_INTEGER PageList[],
IN KPROCESSOR_MODE AccessMode,
IN LOCK_OPERATION Operation
);

Probes the pages specified in PageList, making them physically resident and updating MemoryDescriptorList to describe them. This function has been added to support NtReadFileScatter and NtWriteFileGather.

Parameters

 

Parameter

Description

MemoryDescriptorList

Points to an MDL that supplies a virtual address, byte offset, and length. The physical page portion of the MDL is updated when the pages are locked in memory.

PageList

An array of large integer virtual addresses. Each virtual address must be page aligned. SP2's implementation ignores the upper 32-bits of the addresses, which are present to ease forward transition to 64-bit NT.

AccessMode

Specifies the access mode in which to probe the arguments, either KernelMode or UserMode.

Operation

Specifies the type of operation for which the caller wants the access rights probed and the pages locked, one of IoReadAccess, IoWriteAccess, or IoModifyAccess.

 

Comments

This function is a wrapper around MmProbeAndLockPages, and simply builds an MDL that describes each page specified in PageList.

Conclusion

Although SP2 does not ship with a Kernel32 .LIB file for linking to the new functions, ReadFileScatter and WriteFileGather can still be used. To obtain their entry points from a Win32 application, use the function GetProcAddress as shown below:

ReadFileScatter = (void *) GetProcAddress(GetModuleHandle( "Kernel32.dll" ),
"ReadFileScatter" );

A hack that would make the functions accessible from a device driver would be to make Zw-like function stubs in assembly language for each call that consist of system call traps with the appropriate system call numbers.

In reviewing the code for ReadFileScatter and WriteFileGather, it is interesting to note that they are only partially implemented. It appears the NT operating system group fleshed out the NT kernel implementations of the functions, while the Win32 team seems to have rushed to get the new calls into SP2 and sacrificed a full implementation in order to do so.

This article was printed from OSR Online http://www.osronline.com

Copyright 2017 OSR Open Systems Resources, Inc.