Author: Alex Konshin
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
http://homepages.mtgroup.ru/alexk/files/NativeApp.
Unit ntdll.pas contains only definitions for some functions and structures from NT
Native API.
1 program NativeApp;
2
3 // PURPOSE: Simple Windows NT/2000 console application that calls
4 // Native API functions
5
6 {$APPTYPE CONSOLE}
7
8 uses
9 Windows, SysUtils, ntdll;
10
11 type
12 TEnumNtObjectCallBack = function(
13 pusObjectName: PNtUnicodeString;
14 ObjectTypeName: string;
15 DirectoryHandle: THandle;
16 UserData: Pointer
17 ): Boolean; // False => stop
18
19 //-------------------------------------------------------------
20
21 function NtUnicodeStringToString(pusString: PNtUnicodeString): string;
22 var
23 asString: TNtAnsiString;
24 begin
25 Result := '';
26 if (pusString = nil) or (pusString^.Length = 0) then
27 Exit;
28 // convert with allocating
29 RtlUnicodeStringToAnsiString(@asString, pusString, True);
30 try
31 SetString(Result, asString.Buffer, asString.Length);
32 finally
33 RtlFreeAnsiString(@asString); // free allocated memory
34 end;
35 end;
36 //-------------------------------------------------------------
37 // Open any named NT object.
38 // If DirectoryHandle=0 then ObjectName must be full qualified name
39 // (start with backslash symbol),
40 // otherwise ObjectName specify relative path from this directory
41 // You must call CloseHandle to free obtained handle.
42
43 function OpenObject(ObjectName: PNtUnicodeString;
44 DirectoryHandle: THandle;
45 DesireAccess: ACCESS_MASK): THandle;
46 var
47 ObjectAttributes: TNtObjectAttributes;
48 IoStatus: TIoStatusBlock;
49 doserr: DWORD;
50 rc: NTSTATUS;
51 begin
52 InitializeObjectAttributes(@ObjectAttributes, ObjectName,
53 OBJ_CASE_INSENSITIVE, DirectoryHandle, nil);
54 rc := NtOpenFile(Result, DesireAccess, ObjectAttributes, IoStatus,
55 FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, 0);
56 if rc <> STATUS_SUCCESS then
57 begin
58 doserr := RtlNtStatusToDosError(rc);
59 SetLastError(doserr);
60 Result := INVALID_HANDLE_VALUE;
61 end;
62 end;
63 //-------------------------------------------------------------
64 // Open directory and call Treate function for all objects
65 // in this directory.
66
67 function EnumNtObjects(Path: string;
68 Treate: TEnumNtObjectCallBack;
69 UserData: Pointer): NTSTATUS;
70 const
71 BufferSize = 2048;
72 var
73 hDir: THandle;
74 doserr: DWORD;
75 DirObject: TNtObjectAttributes;
76 asDirName: TNtAnsiString;
77 usDirName: TNtUnicodeString;
78 cbBytesReturned: DWORD;
79 dwIndex: DWORD;
80 Buffer: array[0..BufferSize - 1] of Byte;
81 DirInfo: TDirectoryInformationTYpe1 absolute Buffer;
82 FileNameInfo: TFileNameInformation absolute Buffer;
83 begin
84 if not Assigned(Treate) or (Path = '') then
85 begin
86 Result := STATUS_INVALID_PARAMETER;
87 Exit;
88 end;
89 RtlInitAnsiString(@asDirName, PChar(Path));
90 RtlAnsiStringToUnicodeString(@usDirName, @asDirName, True);
91 try
92 InitializeObjectAttributes(@DirObject, @usDirName,
93 OBJ_CASE_INSENSITIVE, 0, nil);
94 hDir := 0;
95 Result := NtOpenDirectoryObject(hDir,
96 DIRECTORY_TRAVERSE or DIRECTORY_QUERY, DirObject);
97 if Result <> STATUS_SUCCESS then
98 begin
99 doserr := RtlNtStatusToDosError(Result);
100 SetLastError(doserr);
101 end
102 else
103 try
104 dwIndex := 0;
105 repeat
106 Result := NtQueryDirectoryObject(hDir,
107 @Buffer, BufferSize,
108 TDirectoryInformationClass(1), // ???
109 False, dwIndex, cbBytesReturned);
110 if Result <> 0 then
111 begin
112 if Result = STATUS_NO_MORE_DATA then
113 begin
114 Result := STATUS_SUCCESS;
115 Break;
116 end;
117 doserr := RtlNtStatusToDosError(Result);
118 SetLastError(doserr);
119 Break;
120 end;
121 until not Treate(@DirInfo.ObjectName,
122 NtUnicodeStringToString(@DirInfo.ObjectTypeName),
123 hDir, UserData);
124 finally
125 CloseHandle(hDir);
126 end;
127 finally
128 RtlFreeUnicodeString(@usDirName);
129 end;
130 end;
131
132 //=============================================================
133 // Sample for EnumNtObjects callback function
134 type
135 TUserData = record
136 DesireObjectType: PChar;
137 DesireAccess: ACCESS_MASK;
138 end;
139 PUserData = ^TUserData;
140
141 function EnumNtObjectsCallBack(pusObjectName: PNtUnicodeString;
142 ObjectTypeName: string;
143 DirectoryHandle: THandle;
144 UserData: Pointer): Boolean;
145 var
146 sObjectName: string;
147 hObject: THandle;
148 begin
149 Result := True;
150 sObjectName := NtUnicodeStringToString(pusObjectName);
151 with PUserData(UserData)^ do
152 if (DesireObjectType <> '*')
153 and (CompareText(ObjectTypeName, DesireObjectType) <> 0) then
154 Exit;
155 if (CompareText(ObjectTypeName, 'Directory') = 0)
156 //NtOpenDirectoryObject
157 or (CompareText(ObjectTypeName, 'Type') = 0)
158 or (CompareText(ObjectTypeName, 'Port') = 0)
159 or (CompareText(ObjectTypeName, 'Key') = 0) // NtOpenKey
160 or (CompareText(ObjectTypeName, 'Event') = 0) // OpenEvent
161 or (CompareText(ObjectTypeName, 'Semaphore') = 0) // OpenSemaphore
162 or (CompareText(ObjectTypeName, 'Mutant') = 0) // OpenMutex
163 or (CompareText(ObjectTypeName, 'Timer') = 0) // NtOpenTimer
164 or (CompareText(ObjectTypeName, 'Section') = 0) // NtOpenSection
165 or (CompareText(ObjectTypeName, 'SymbolicLink') = 0)
166 {// NtOpenSymbolicLinkObject } then
167 begin
168 WriteLn(ObjectTypeName, ' ', sObjectName);
169 Exit;
170 end;
171 hObject := OpenObject(pusObjectName, DirectoryHandle,
172 PUserData(UserData)^.DesireAccess);
173 if hObject = INVALID_HANDLE_VALUE then
174 begin
175 write(' NtOpenObject failed for ', sObjectName, ': ');
176 WriteLn(SysErrorMessage(GetLastError));
177 Exit;
178 end;
179 try
180 WriteLn(ObjectTypeName, ' ', sObjectName,
181 ' is opened successfully');
182
183 // do something with object here
184
185 finally
186 CloseHandle(hObject);
187 end;
188 end;
189
190 //=============================================================
191 // Application
192
193 var
194 sObjectType, sPath: string;
195 rUserData: TUserData;
196 begin
197 if (ParamCount = 0) or (ParamCount > 2) then
198 begin
199 WriteLn('(c) 20 jul 2000 Alex Konshin mailto:alexk@mtgroup.ru');
200 WriteLn;
201 WriteLn('Sample console application that use NT Native API.');
202 WriteLn;
203 WriteLn('Using:');
204 WriteLn;
205 WriteLn(' NativeApp ObjectType [Path]');
206 WriteLn;
207 WriteLn('Where:');
208 WriteLn;
209 WriteLn(' ObjectType = *(all objects), Directory, Type, Device, Mutant,');
210 WriteLn(' Section, Semaphore,...');
211 WriteLn(' (use NativeApp Type \ObjectTypes to list NT object types)');
212 WriteLn;
213 WriteLn(' Path = NT objects directory name.');
214 WriteLn;
215 WriteLn('Examples:');
216 WriteLn;
217 WriteLn(' NativeApp Device \Device');
218 WriteLn(' NativeApp Mutant \BaseNamedObjects');
219 WriteLn;
220 Exit;
221 end;
222 sObjectType := ParamStr(1);
223 sPath := ParamStr(2);
224 if sPath = '' then
225 sPath := '\';
226 with rUserData do
227 begin
228 DesireObjectType := PChar(sObjectType);
229 DesireAccess := FILE_READ_DATA; // GENERIC_READ or GENERIC_WRITE;
230 end;
231 EnumNtObjects(sPath, EnumNtObjectsCallBack, @rUserData);
232 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.
|