Title: NT Native API
Question: NT Native API is basic API in Windows NT/2000.
All other API (Win32 is included) are use this API.
But functions from ntdll.dll are poorely documented.
Answer:
You can download full source code (ntdll.pas is included)
http://homepages.mtgroup.ru/alexk/files/NativeApp.zip
Unit ntdll.pas contains only definitions for some functions and structures from NT Native API.
program NativeApp;
// PURPOSE: Simple Windows NT/2000 console application that calls
// Native API functions
{$APPTYPE CONSOLE}
uses
Windows, SysUtils, ntdll;
type
TEnumNtObjectCallBack = function (
pusObjectName : PNtUnicodeString;
ObjectTypeName : String;
DirectoryHandle : THandle;
UserData : Pointer
) : Boolean; // False = stop
//-------------------------------------------------------------
function NtUnicodeStringToString( pusString: PNtUnicodeString ): String;
var asString: TNtAnsiString;
begin
Result := '';
if (pusString=nil)or(pusString^.Length=0) then Exit;
// convert with allocating
RtlUnicodeStringToAnsiString(@asString,pusString,True);
try
SetString(Result,asString.Buffer,asString.Length);
finally
RtlFreeAnsiString(@asString); // free allocated memory
end;
end;
//-------------------------------------------------------------
// Open any named NT object.
// If DirectoryHandle=0 then ObjectName must be full qualified name
// (start with backslash symbol),
// otherwise ObjectName specify relative path from this directory
// You must call CloseHandle to free obtained handle.
function OpenObject( ObjectName : PNtUnicodeString;
DirectoryHandle : THandle;
DesireAccess : ACCESS_MASK ) : THandle;
var ObjectAttributes : TNtObjectAttributes;
IoStatus : TIoStatusBlock;
doserr : DWORD;
rc : NTSTATUS;
begin
InitializeObjectAttributes( @ObjectAttributes, ObjectName,
OBJ_CASE_INSENSITIVE, DirectoryHandle, nil );
rc := NtOpenFile( Result, DesireAccess, ObjectAttributes, IoStatus,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, 0 );
if rcSTATUS_SUCCESS then
begin
doserr := RtlNtStatusToDosError(rc);
SetLastError(doserr);
Result := INVALID_HANDLE_VALUE;
end;
end;
//-------------------------------------------------------------
// Open directory and call Treate function for all objects
// in this directory.
function EnumNtObjects( Path : String;
Treate : TEnumNtObjectCallBack;
UserData : Pointer ) : NTSTATUS;
const BufferSize = 2048;
var hDir : THandle;
doserr : DWORD;
DirObject : TNtObjectAttributes;
asDirName : TNtAnsiString;
usDirName : TNtUnicodeString;
cbBytesReturned : DWORD;
dwIndex : DWORD;
Buffer : Array [0..BufferSize-1] of Byte;
DirInfo : TDirectoryInformationTYpe1 absolute Buffer;
FileNameInfo : TFileNameInformation absolute Buffer;
begin
if not Assigned(Treate) or (Path='') then
begin
Result := STATUS_INVALID_PARAMETER;
Exit;
end;
RtlInitAnsiString( @asDirName, PChar(Path) );
RtlAnsiStringToUnicodeString(@usDirName,@asDirName,True);
try
InitializeObjectAttributes( @DirObject, @usDirName,
OBJ_CASE_INSENSITIVE, 0, nil );
hDir := 0;
Result := NtOpenDirectoryObject( hDir,
DIRECTORY_TRAVERSE or DIRECTORY_QUERY, DirObject );
if ResultSTATUS_SUCCESS then
begin
doserr := RtlNtStatusToDosError(Result);
SetLastError(doserr);
end
else
try
dwIndex := 0;
repeat
Result := NtQueryDirectoryObject(hDir,
@Buffer,BufferSize,
TDirectoryInformationClass(1), // ???
False,dwIndex,cbBytesReturned);
if Result0 then
begin
if Result=STATUS_NO_MORE_DATA then
begin
Result := STATUS_SUCCESS;
Break;
end;
doserr := RtlNtStatusToDosError(Result);
SetLastError(doserr);
Break;
end;
until not Treate( @DirInfo.ObjectName,
NtUnicodeStringToString(@DirInfo.ObjectTypeName),
hDir, UserData );
finally
CloseHandle(hDir);
end;
finally
RtlFreeUnicodeString(@usDirName);
end;
end;
//=============================================================
// Sample for EnumNtObjects callback function
type
TUserData = record
DesireObjectType : PChar;
DesireAccess : ACCESS_MASK;
end;
PUserData = ^TUserData;
function EnumNtObjectsCallBack( pusObjectName : PNtUnicodeString;
ObjectTypeName : String;
DirectoryHandle : THandle;
UserData : Pointer ) : Boolean;
var sObjectName : String;
hObject : THandle;
begin
Result := True;
sObjectName := NtUnicodeStringToString(pusObjectName);
with PUserData(UserData)^ do
if (DesireObjectType'*')
and (CompareText(ObjectTypeName,DesireObjectType)0)
then Exit;
if(CompareText(ObjectTypeName,'Directory')=0)
//NtOpenDirectoryObject
or (CompareText(ObjectTypeName,'Type')=0)
or (CompareText(ObjectTypeName,'Port')=0)
or (CompareText(ObjectTypeName,'Key')=0) // NtOpenKey
or (CompareText(ObjectTypeName,'Event')=0) // OpenEvent
or (CompareText(ObjectTypeName,'Semaphore')=0) // OpenSemaphore
or (CompareText(ObjectTypeName,'Mutant')=0) // OpenMutex
or (CompareText(ObjectTypeName,'Timer')=0) // NtOpenTimer
or (CompareText(ObjectTypeName,'Section')=0) // NtOpenSection
or (CompareText(ObjectTypeName,'SymbolicLink')=0)
// NtOpenSymbolicLinkObject
then
begin
WriteLn(ObjectTypeName,' ',sObjectName);
Exit;
end;
hObject := OpenObject( pusObjectName, DirectoryHandle,
PUserData(UserData)^.DesireAccess);
if hObject=INVALID_HANDLE_VALUE then
begin
Write(' NtOpenObject failed for ',sObjectName,': ');
WriteLn(SysErrorMessage(GetLastError));
Exit;
end;
try
WriteLn( ObjectTypeName,' ',sObjectName,
' is opened successfully');
// do something with object here
finally
CloseHandle(hObject);
end;
end;
//=============================================================
// Application
var sObjectType, sPath : String;
rUserData : TUserData;
begin
if (ParamCount=0) or (ParamCount2) then
begin
WriteLn('(c) 20 jul 2000 Alex Konshin mailto:alexk@mtgroup.ru');
WriteLn;
WriteLn('Sample console application that use NT Native API.');
WriteLn;
WriteLn('Using:');
WriteLn;
WriteLn(' NativeApp ObjectType [Path]');
WriteLn;
WriteLn('Where:');
WriteLn;
WriteLn(' ObjectType = *(all objects), Directory, Type, Device, Mutant,');
WriteLn(' Section, Semaphore,...');
WriteLn(' (use NativeApp Type \ObjectTypes to list NT object types)');
WriteLn;
WriteLn(' Path = NT objects directory name.');
WriteLn;
WriteLn('Examples:');
WriteLn;
WriteLn(' NativeApp Device \Device');
WriteLn(' NativeApp Mutant \BaseNamedObjects');
WriteLn;
Exit;
end;
sObjectType := ParamStr(1);
sPath := ParamStr(2);
if sPath='' then sPath := '\';
with rUserData do
begin
DesireObjectType := PChar(sObjectType);
DesireAccess := FILE_READ_DATA; // GENERIC_READ or GENERIC_WRITE;
end;
EnumNtObjects( sPath, EnumNtObjectsCallBack, @rUserData );
end.
Links for more informations:
http://www.sysinternals.com/ntdll.htm
http://www.sysinternals.com/winobj.htm
Books:
http://www.amazon.com/exec/obidos/ASIN/1578701996/systemsinternals
See also Zw*, Rtl* functions descriptions in Win2000 DDK.