2011. január 12., szerda
NT Native API
Problem/Question/Abstract:
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 rc <> STATUS_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 Result <> STATUS_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 Result <> 0 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 (ParamCount > 2) 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.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése