1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * DESCRIPTION: Object Manager Simple Explorer
3*c2c66affSColin Finck * PROGRAMMER: David Welch
4*c2c66affSColin Finck * REVISIONS
5*c2c66affSColin Finck * 2000-04-30 (ea)
6*c2c66affSColin Finck * Added directory enumeration.
7*c2c66affSColin Finck * (tested under nt4sp4/x86)
8*c2c66affSColin Finck * 2000-08-11 (ea)
9*c2c66affSColin Finck * Added symbolic link expansion.
10*c2c66affSColin Finck * (tested under nt4sp4/x86)
11*c2c66affSColin Finck * 2001-05-01 (ea)
12*c2c66affSColin Finck * Fixed entries counter. Added more
13*c2c66affSColin Finck * error codes check. Removed wprintf,
14*c2c66affSColin Finck * because it does not work in .17.
15*c2c66affSColin Finck * 2001-05-02 (ea)
16*c2c66affSColin Finck * Added -r option.
17*c2c66affSColin Finck */
18*c2c66affSColin Finck
19*c2c66affSColin Finck #define WIN32_NO_STATUS
20*c2c66affSColin Finck #include <windows.h>
21*c2c66affSColin Finck #include <stdlib.h>
22*c2c66affSColin Finck #include <ntndk.h>
23*c2c66affSColin Finck #include <stdio.h>
24*c2c66affSColin Finck
25*c2c66affSColin Finck #define MAX_DIR_ENTRY 256
26*c2c66affSColin Finck
27*c2c66affSColin Finck
28*c2c66affSColin Finck static
29*c2c66affSColin Finck PCHAR
30*c2c66affSColin Finck WINAPI
RawUszAsz(PWCHAR szU,PCHAR szA)31*c2c66affSColin Finck RawUszAsz (
32*c2c66affSColin Finck PWCHAR szU,
33*c2c66affSColin Finck PCHAR szA
34*c2c66affSColin Finck )
35*c2c66affSColin Finck {
36*c2c66affSColin Finck register PCHAR a = szA;
37*c2c66affSColin Finck
38*c2c66affSColin Finck while (*szU) {*szA++ = (CHAR) (0x00ff & * szU++);}
39*c2c66affSColin Finck *szA = '\0';
40*c2c66affSColin Finck return a;
41*c2c66affSColin Finck }
42*c2c66affSColin Finck
43*c2c66affSColin Finck
44*c2c66affSColin Finck static
45*c2c66affSColin Finck PWCHAR
46*c2c66affSColin Finck WINAPI
RawAszUsz(PCHAR szA,PWCHAR szW)47*c2c66affSColin Finck RawAszUsz (
48*c2c66affSColin Finck PCHAR szA,
49*c2c66affSColin Finck PWCHAR szW
50*c2c66affSColin Finck )
51*c2c66affSColin Finck {
52*c2c66affSColin Finck register PWCHAR w = szW;
53*c2c66affSColin Finck
54*c2c66affSColin Finck while (*szA) {*szW++ = (WCHAR) *szA++;}
55*c2c66affSColin Finck *szW = L'\0';
56*c2c66affSColin Finck return w;
57*c2c66affSColin Finck }
58*c2c66affSColin Finck
59*c2c66affSColin Finck
60*c2c66affSColin Finck static
61*c2c66affSColin Finck const char *
62*c2c66affSColin Finck WINAPI
StatusToName(NTSTATUS Status)63*c2c66affSColin Finck StatusToName (NTSTATUS Status)
64*c2c66affSColin Finck {
65*c2c66affSColin Finck static char RawValue [16];
66*c2c66affSColin Finck
67*c2c66affSColin Finck switch (Status)
68*c2c66affSColin Finck {
69*c2c66affSColin Finck case STATUS_BUFFER_TOO_SMALL:
70*c2c66affSColin Finck return "STATUS_BUFFER_TOO_SMALL";
71*c2c66affSColin Finck case STATUS_INVALID_PARAMETER:
72*c2c66affSColin Finck return "STATUS_INVALID_PARAMETER";
73*c2c66affSColin Finck case STATUS_OBJECT_NAME_INVALID:
74*c2c66affSColin Finck return "STATUS_OBJECT_NAME_INVALID";
75*c2c66affSColin Finck case STATUS_OBJECT_NAME_NOT_FOUND:
76*c2c66affSColin Finck return "STATUS_OBJECT_NAME_NOT_FOUND";
77*c2c66affSColin Finck case STATUS_OBJECT_PATH_SYNTAX_BAD:
78*c2c66affSColin Finck return "STATUS_PATH_SYNTAX_BAD";
79*c2c66affSColin Finck case STATUS_NO_MORE_ENTRIES:
80*c2c66affSColin Finck return "STATUS_NO_MORE_ENTRIES";
81*c2c66affSColin Finck case STATUS_MORE_ENTRIES:
82*c2c66affSColin Finck return "STATUS_MORE_ENTRIES";
83*c2c66affSColin Finck case STATUS_ACCESS_DENIED:
84*c2c66affSColin Finck return "STATUS_ACCESS_DENIED";
85*c2c66affSColin Finck case STATUS_UNSUCCESSFUL:
86*c2c66affSColin Finck return "STATUS_UNSUCCESSFUL";
87*c2c66affSColin Finck case STATUS_INVALID_HANDLE:
88*c2c66affSColin Finck return "STATUS_INVALID_HANDLE";
89*c2c66affSColin Finck }
90*c2c66affSColin Finck sprintf (RawValue, "0x%08lx", Status);
91*c2c66affSColin Finck return (const char *) RawValue;
92*c2c66affSColin Finck }
93*c2c66affSColin Finck
94*c2c66affSColin Finck
95*c2c66affSColin Finck BOOL
96*c2c66affSColin Finck WINAPI
ExpandSymbolicLink(IN PUNICODE_STRING DirectoryName,IN PUNICODE_STRING SymbolicLinkName,IN OUT PUNICODE_STRING TargetObjectName)97*c2c66affSColin Finck ExpandSymbolicLink (
98*c2c66affSColin Finck IN PUNICODE_STRING DirectoryName,
99*c2c66affSColin Finck IN PUNICODE_STRING SymbolicLinkName,
100*c2c66affSColin Finck IN OUT PUNICODE_STRING TargetObjectName
101*c2c66affSColin Finck )
102*c2c66affSColin Finck {
103*c2c66affSColin Finck NTSTATUS Status;
104*c2c66affSColin Finck HANDLE hSymbolicLink;
105*c2c66affSColin Finck OBJECT_ATTRIBUTES oa;
106*c2c66affSColin Finck UNICODE_STRING Path;
107*c2c66affSColin Finck WCHAR PathBuffer [MAX_PATH];
108*c2c66affSColin Finck ULONG DataWritten = 0;
109*c2c66affSColin Finck
110*c2c66affSColin Finck
111*c2c66affSColin Finck Path.Buffer = PathBuffer;
112*c2c66affSColin Finck Path.Length = 0;
113*c2c66affSColin Finck Path.MaximumLength = sizeof PathBuffer;
114*c2c66affSColin Finck
115*c2c66affSColin Finck RtlCopyUnicodeString (& Path, DirectoryName);
116*c2c66affSColin Finck if (L'\\' != Path.Buffer [(Path.Length / sizeof Path.Buffer[0]) - 1])
117*c2c66affSColin Finck {
118*c2c66affSColin Finck RtlAppendUnicodeToString (& Path, L"\\");
119*c2c66affSColin Finck }
120*c2c66affSColin Finck RtlAppendUnicodeStringToString (& Path, SymbolicLinkName);
121*c2c66affSColin Finck
122*c2c66affSColin Finck oa.Length = sizeof (OBJECT_ATTRIBUTES);
123*c2c66affSColin Finck oa.ObjectName = & Path;
124*c2c66affSColin Finck oa.Attributes = 0; /* OBJ_CASE_INSENSITIVE; */
125*c2c66affSColin Finck oa.RootDirectory = NULL;
126*c2c66affSColin Finck oa.SecurityDescriptor = NULL;
127*c2c66affSColin Finck oa.SecurityQualityOfService = NULL;
128*c2c66affSColin Finck
129*c2c66affSColin Finck Status = NtOpenSymbolicLinkObject(
130*c2c66affSColin Finck & hSymbolicLink,
131*c2c66affSColin Finck SYMBOLIC_LINK_QUERY, /* 0x20001 */
132*c2c66affSColin Finck & oa
133*c2c66affSColin Finck );
134*c2c66affSColin Finck
135*c2c66affSColin Finck if (!NT_SUCCESS(Status))
136*c2c66affSColin Finck {
137*c2c66affSColin Finck printf (
138*c2c66affSColin Finck "Failed to open SymbolicLink object (Status: %s)\n",
139*c2c66affSColin Finck StatusToName (Status)
140*c2c66affSColin Finck );
141*c2c66affSColin Finck return FALSE;
142*c2c66affSColin Finck }
143*c2c66affSColin Finck TargetObjectName->Length = TargetObjectName->MaximumLength;
144*c2c66affSColin Finck memset (
145*c2c66affSColin Finck TargetObjectName->Buffer,
146*c2c66affSColin Finck 0,
147*c2c66affSColin Finck TargetObjectName->MaximumLength
148*c2c66affSColin Finck );
149*c2c66affSColin Finck Status = NtQuerySymbolicLinkObject(
150*c2c66affSColin Finck hSymbolicLink,
151*c2c66affSColin Finck TargetObjectName,
152*c2c66affSColin Finck & DataWritten
153*c2c66affSColin Finck );
154*c2c66affSColin Finck if (!NT_SUCCESS(Status))
155*c2c66affSColin Finck {
156*c2c66affSColin Finck printf (
157*c2c66affSColin Finck "Failed to query SymbolicLink object (Status: %s)\n",
158*c2c66affSColin Finck StatusToName (Status)
159*c2c66affSColin Finck );
160*c2c66affSColin Finck NtClose (hSymbolicLink);
161*c2c66affSColin Finck return FALSE;
162*c2c66affSColin Finck }
163*c2c66affSColin Finck NtClose (hSymbolicLink);
164*c2c66affSColin Finck return TRUE;
165*c2c66affSColin Finck }
166*c2c66affSColin Finck
167*c2c66affSColin Finck
168*c2c66affSColin Finck BOOL
169*c2c66affSColin Finck WINAPI
ListDirectory(IN PUNICODE_STRING DirectoryNameW,IN BOOL Recurse)170*c2c66affSColin Finck ListDirectory (
171*c2c66affSColin Finck IN PUNICODE_STRING DirectoryNameW,
172*c2c66affSColin Finck IN BOOL Recurse
173*c2c66affSColin Finck )
174*c2c66affSColin Finck {
175*c2c66affSColin Finck CHAR DirectoryNameA [MAX_PATH];
176*c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes;
177*c2c66affSColin Finck NTSTATUS Status;
178*c2c66affSColin Finck HANDLE DirectoryHandle;
179*c2c66affSColin Finck BYTE DirectoryEntry [512];
180*c2c66affSColin Finck POBJECT_DIRECTORY_INFORMATION pDirectoryEntry = (POBJECT_DIRECTORY_INFORMATION) DirectoryEntry;
181*c2c66affSColin Finck POBJECT_DIRECTORY_INFORMATION pDirectoryEntries = (POBJECT_DIRECTORY_INFORMATION) DirectoryEntry;
182*c2c66affSColin Finck ULONG Context = 0;
183*c2c66affSColin Finck ULONG ReturnLength = 0;
184*c2c66affSColin Finck ULONG EntryCount = 0;
185*c2c66affSColin Finck
186*c2c66affSColin Finck /* For expanding symbolic links */
187*c2c66affSColin Finck WCHAR TargetName [2 * MAX_PATH];
188*c2c66affSColin Finck UNICODE_STRING TargetObjectName = {
189*c2c66affSColin Finck sizeof TargetName,
190*c2c66affSColin Finck sizeof TargetName,
191*c2c66affSColin Finck TargetName
192*c2c66affSColin Finck };
193*c2c66affSColin Finck
194*c2c66affSColin Finck /* Convert to ANSI the directory's name */
195*c2c66affSColin Finck RawUszAsz (DirectoryNameW->Buffer, DirectoryNameA);
196*c2c66affSColin Finck /*
197*c2c66affSColin Finck * Prepare parameters for next call.
198*c2c66affSColin Finck */
199*c2c66affSColin Finck InitializeObjectAttributes (
200*c2c66affSColin Finck & ObjectAttributes,
201*c2c66affSColin Finck DirectoryNameW,
202*c2c66affSColin Finck 0,
203*c2c66affSColin Finck NULL,
204*c2c66affSColin Finck NULL
205*c2c66affSColin Finck );
206*c2c66affSColin Finck /*
207*c2c66affSColin Finck * Try opening the directory.
208*c2c66affSColin Finck */
209*c2c66affSColin Finck Status = NtOpenDirectoryObject (
210*c2c66affSColin Finck & DirectoryHandle,
211*c2c66affSColin Finck DIRECTORY_QUERY,
212*c2c66affSColin Finck & ObjectAttributes
213*c2c66affSColin Finck );
214*c2c66affSColin Finck if (!NT_SUCCESS(Status))
215*c2c66affSColin Finck {
216*c2c66affSColin Finck printf (
217*c2c66affSColin Finck "Failed to open directory object \"%s\" (Status: %s)\n",
218*c2c66affSColin Finck DirectoryNameA,
219*c2c66affSColin Finck StatusToName (Status)
220*c2c66affSColin Finck );
221*c2c66affSColin Finck return (FALSE);
222*c2c66affSColin Finck }
223*c2c66affSColin Finck printf ("\n Directory of %s\n\n", DirectoryNameA);
224*c2c66affSColin Finck
225*c2c66affSColin Finck for(;;)
226*c2c66affSColin Finck {
227*c2c66affSColin Finck /*
228*c2c66affSColin Finck * Enumerate each item in the directory.
229*c2c66affSColin Finck */
230*c2c66affSColin Finck Status = NtQueryDirectoryObject (
231*c2c66affSColin Finck DirectoryHandle,
232*c2c66affSColin Finck pDirectoryEntries,
233*c2c66affSColin Finck sizeof DirectoryEntry,
234*c2c66affSColin Finck FALSE,/* ReturnSingleEntry */
235*c2c66affSColin Finck FALSE, /* RestartScan */
236*c2c66affSColin Finck & Context,
237*c2c66affSColin Finck & ReturnLength
238*c2c66affSColin Finck );
239*c2c66affSColin Finck if (!NT_SUCCESS(Status) && Status != STATUS_NO_MORE_ENTRIES)
240*c2c66affSColin Finck {
241*c2c66affSColin Finck printf (
242*c2c66affSColin Finck "Failed to query directory object (Status: %s)\n",
243*c2c66affSColin Finck StatusToName (Status)
244*c2c66affSColin Finck );
245*c2c66affSColin Finck NtClose (DirectoryHandle);
246*c2c66affSColin Finck return (FALSE);
247*c2c66affSColin Finck }
248*c2c66affSColin Finck if (Status == STATUS_NO_MORE_ENTRIES)
249*c2c66affSColin Finck {
250*c2c66affSColin Finck break;
251*c2c66affSColin Finck }
252*c2c66affSColin Finck pDirectoryEntry = pDirectoryEntries;
253*c2c66affSColin Finck while (EntryCount < Context)
254*c2c66affSColin Finck {
255*c2c66affSColin Finck CHAR ObjectNameA [MAX_PATH];
256*c2c66affSColin Finck CHAR TypeNameA [MAX_PATH];
257*c2c66affSColin Finck CHAR TargetNameA [MAX_PATH];
258*c2c66affSColin Finck
259*c2c66affSColin Finck if (0 == wcscmp (L"SymbolicLink", pDirectoryEntry->TypeName.Buffer))
260*c2c66affSColin Finck {
261*c2c66affSColin Finck if (TRUE == ExpandSymbolicLink (
262*c2c66affSColin Finck DirectoryNameW,
263*c2c66affSColin Finck & pDirectoryEntry->Name,
264*c2c66affSColin Finck & TargetObjectName
265*c2c66affSColin Finck )
266*c2c66affSColin Finck )
267*c2c66affSColin Finck {
268*c2c66affSColin Finck
269*c2c66affSColin Finck printf (
270*c2c66affSColin Finck "%-16s %s -> %s\n",
271*c2c66affSColin Finck RawUszAsz (pDirectoryEntry->TypeName.Buffer, TypeNameA),
272*c2c66affSColin Finck RawUszAsz (pDirectoryEntry->Name.Buffer, ObjectNameA),
273*c2c66affSColin Finck RawUszAsz (TargetObjectName.Buffer, TargetNameA)
274*c2c66affSColin Finck );
275*c2c66affSColin Finck }
276*c2c66affSColin Finck else
277*c2c66affSColin Finck {
278*c2c66affSColin Finck printf (
279*c2c66affSColin Finck "%-16s %s -> (error!)\n",
280*c2c66affSColin Finck RawUszAsz (pDirectoryEntry->TypeName.Buffer, TypeNameA),
281*c2c66affSColin Finck RawUszAsz (pDirectoryEntry->Name.Buffer, ObjectNameA)
282*c2c66affSColin Finck );
283*c2c66affSColin Finck }
284*c2c66affSColin Finck }
285*c2c66affSColin Finck else
286*c2c66affSColin Finck {
287*c2c66affSColin Finck printf (
288*c2c66affSColin Finck "%-16s %s\n",
289*c2c66affSColin Finck RawUszAsz (pDirectoryEntry->TypeName.Buffer, TypeNameA),
290*c2c66affSColin Finck RawUszAsz (pDirectoryEntry->Name.Buffer, ObjectNameA)
291*c2c66affSColin Finck );
292*c2c66affSColin Finck }
293*c2c66affSColin Finck ++ pDirectoryEntry;
294*c2c66affSColin Finck ++ EntryCount;
295*c2c66affSColin Finck }
296*c2c66affSColin Finck };
297*c2c66affSColin Finck printf ("\n\t%lu object(s)\n", EntryCount);
298*c2c66affSColin Finck /*
299*c2c66affSColin Finck * Free any resource.
300*c2c66affSColin Finck */
301*c2c66affSColin Finck NtClose (DirectoryHandle);
302*c2c66affSColin Finck /*
303*c2c66affSColin Finck * Recurse into, if required so.
304*c2c66affSColin Finck */
305*c2c66affSColin Finck if (FALSE != Recurse)
306*c2c66affSColin Finck {
307*c2c66affSColin Finck pDirectoryEntry = (POBJECT_DIRECTORY_INFORMATION) DirectoryEntry;
308*c2c66affSColin Finck while (0 != pDirectoryEntry->TypeName.Length)
309*c2c66affSColin Finck {
310*c2c66affSColin Finck if (0 == wcscmp (L"Directory", pDirectoryEntry->TypeName.Buffer))
311*c2c66affSColin Finck {
312*c2c66affSColin Finck WCHAR CurrentName [MAX_PATH];
313*c2c66affSColin Finck UNICODE_STRING CurrentDirectory;
314*c2c66affSColin Finck
315*c2c66affSColin Finck CurrentName [0] = L'\0';
316*c2c66affSColin Finck wcscpy (CurrentName, DirectoryNameW->Buffer);
317*c2c66affSColin Finck if (wcslen (CurrentName) > 1)
318*c2c66affSColin Finck {
319*c2c66affSColin Finck wcscat (CurrentName, L"\\");
320*c2c66affSColin Finck }
321*c2c66affSColin Finck wcscat (CurrentName, pDirectoryEntry->Name.Buffer);
322*c2c66affSColin Finck RtlInitUnicodeString (& CurrentDirectory, CurrentName);
323*c2c66affSColin Finck ListDirectory (& CurrentDirectory, Recurse);
324*c2c66affSColin Finck }
325*c2c66affSColin Finck ++ pDirectoryEntry;
326*c2c66affSColin Finck }
327*c2c66affSColin Finck }
328*c2c66affSColin Finck return (TRUE);
329*c2c66affSColin Finck }
330*c2c66affSColin Finck
331*c2c66affSColin Finck
main(int argc,char * argv[])332*c2c66affSColin Finck int main(int argc, char* argv[])
333*c2c66affSColin Finck {
334*c2c66affSColin Finck WCHAR DirectoryNameW [MAX_PATH];
335*c2c66affSColin Finck UNICODE_STRING DirectoryName;
336*c2c66affSColin Finck BOOL Recurse = FALSE;
337*c2c66affSColin Finck
338*c2c66affSColin Finck /*
339*c2c66affSColin Finck * Check user arguments.
340*c2c66affSColin Finck */
341*c2c66affSColin Finck switch (argc)
342*c2c66affSColin Finck {
343*c2c66affSColin Finck case 2:
344*c2c66affSColin Finck RawAszUsz (argv[1], DirectoryNameW);
345*c2c66affSColin Finck break;
346*c2c66affSColin Finck case 3:
347*c2c66affSColin Finck if (strcmp (argv[1], "-r"))
348*c2c66affSColin Finck {
349*c2c66affSColin Finck fprintf (
350*c2c66affSColin Finck stderr,
351*c2c66affSColin Finck "%s: unknown option '%s'.\n",
352*c2c66affSColin Finck argv [0], argv[1]
353*c2c66affSColin Finck );
354*c2c66affSColin Finck return EXIT_FAILURE;
355*c2c66affSColin Finck }
356*c2c66affSColin Finck RawAszUsz (argv[2], DirectoryNameW);
357*c2c66affSColin Finck Recurse = TRUE;
358*c2c66affSColin Finck break;
359*c2c66affSColin Finck default:
360*c2c66affSColin Finck fprintf (
361*c2c66affSColin Finck stderr,
362*c2c66affSColin Finck "\nUsage: %s [-r] directory\n\n"
363*c2c66affSColin Finck " -r recurse\n"
364*c2c66affSColin Finck " directory a directory name in the system namespace\n\n",
365*c2c66affSColin Finck argv [0]
366*c2c66affSColin Finck );
367*c2c66affSColin Finck return EXIT_FAILURE;
368*c2c66affSColin Finck }
369*c2c66affSColin Finck /*
370*c2c66affSColin Finck * List the directory.
371*c2c66affSColin Finck */
372*c2c66affSColin Finck RtlInitUnicodeString (& DirectoryName, DirectoryNameW);
373*c2c66affSColin Finck return (FALSE == ListDirectory (& DirectoryName, Recurse))
374*c2c66affSColin Finck ? EXIT_FAILURE
375*c2c66affSColin Finck : EXIT_SUCCESS;
376*c2c66affSColin Finck }
377*c2c66affSColin Finck
378*c2c66affSColin Finck
379*c2c66affSColin Finck /* EOF */
380