03044899cd0313c25a7e45d28c81dadd9ac9fac5
[reactos.git] / reactos / apps / utils / objdir / objdir.c
1 /* $Id: objdir.c,v 1.6 2001/05/01 21:43:45 ea Exp $
2 *
3 * DESCRIPTION: Object Manager Simple Explorer
4 * PROGRAMMER: David Welch
5 * REVISIONS
6 * 2000-04-30 (ea)
7 * Added directory enumeration.
8 * (tested under nt4sp4/x86)
9 * 2000-08-11 (ea)
10 * Added symbolic link expansion.
11 * (tested under nt4sp4/x86)
12 * 2001-05-01 (ea)
13 * Fixed entries counter. Added more
14 * error codes check. Removed wprintf,
15 * because it does not work in .17.
16 */
17
18 #include <ddk/ntddk.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 BYTE DirectoryEntry [32768];
25 POBJDIR_INFORMATION pDirectoryEntry = (POBJDIR_INFORMATION) DirectoryEntry;
26
27 static
28 PCHAR
29 STDCALL
30 RawUszAsz (
31 PWCHAR szU,
32 PCHAR szA
33 )
34 {
35 register PCHAR a = szA;
36
37 while (*szU) {*szA++ = (CHAR) (0x00ff & * szU++);}
38 *szA = '\0';
39 return a;
40 }
41
42
43 static
44 const char *
45 STDCALL
46 StatusToName (NTSTATUS Status)
47 {
48 static char RawValue [16];
49
50 switch (Status)
51 {
52 case STATUS_BUFFER_TOO_SMALL:
53 return "STATUS_BUFFER_TOO_SMALL";
54 case STATUS_INVALID_PARAMETER:
55 return "STATUS_INVALID_PARAMETER";
56 case STATUS_OBJECT_NAME_INVALID:
57 return "STATUS_OBJECT_NAME_INVALID";
58 case STATUS_OBJECT_NAME_NOT_FOUND:
59 return "STATUS_OBJECT_NAME_NOT_FOUND";
60 case STATUS_PATH_SYNTAX_BAD:
61 return "STATUS_PATH_SYNTAX_BAD";
62 case STATUS_NO_MORE_ENTRIES:
63 return "STATUS_NO_MORE_ENTRIES";
64 case STATUS_UNSUCCESSFUL:
65 return "STATUS_UNSUCCESSFUL";
66 }
67 sprintf (RawValue, "0x%08lx", Status);
68 return (const char *) RawValue;
69 }
70
71
72 BOOL
73 STDCALL
74 ExpandSymbolicLink (
75 IN PUNICODE_STRING DirectoryName,
76 IN PUNICODE_STRING SymbolicLinkName,
77 IN OUT PUNICODE_STRING TargetObjectName
78 )
79 {
80 NTSTATUS Status;
81 HANDLE hSymbolicLink;
82 OBJECT_ATTRIBUTES oa;
83 UNICODE_STRING Path;
84 WCHAR PathBuffer [MAX_PATH];
85 ULONG DataWritten = 0;
86
87
88 Path.Buffer = PathBuffer;
89 Path.Length = 0;
90 Path.MaximumLength = sizeof PathBuffer;
91
92 RtlCopyUnicodeString (& Path, DirectoryName);
93 if (L'\\' != Path.Buffer [(Path.Length / sizeof Path.Buffer[0]) - 1])
94 {
95 RtlAppendUnicodeToString (& Path, L"\\");
96 }
97 RtlAppendUnicodeStringToString (& Path, SymbolicLinkName);
98
99 oa.Length = sizeof (OBJECT_ATTRIBUTES);
100 oa.ObjectName = & Path;
101 oa.Attributes = 0; /* OBJ_CASE_INSENSITIVE; */
102 oa.RootDirectory = NULL;
103 oa.SecurityDescriptor = NULL;
104 oa.SecurityQualityOfService = NULL;
105
106 Status = NtOpenSymbolicLinkObject(
107 & hSymbolicLink,
108 SYMBOLIC_LINK_QUERY, /* 0x20001 */
109 & oa
110 );
111
112 if (!NT_SUCCESS(Status))
113 {
114 printf (
115 "Failed to open SymbolicLink object (Status: %s)\n",
116 StatusToName (Status)
117 );
118 return FALSE;
119 }
120 TargetObjectName->Length = TargetObjectName->MaximumLength;
121 memset (
122 TargetObjectName->Buffer,
123 0,
124 TargetObjectName->MaximumLength
125 );
126 Status = NtQuerySymbolicLinkObject(
127 hSymbolicLink,
128 TargetObjectName,
129 & DataWritten
130 );
131 if (!NT_SUCCESS(Status))
132 {
133 printf (
134 "Failed to query SymbolicLink object (Status: %s)\n",
135 StatusToName (Status)
136 );
137 NtClose (hSymbolicLink);
138 return FALSE;
139 }
140 NtClose (hSymbolicLink);
141 return TRUE;
142 }
143
144
145
146 int main(int argc, char* argv[])
147 {
148 UNICODE_STRING DirectoryNameW;
149 ANSI_STRING DirectoryNameA;
150 OBJECT_ATTRIBUTES ObjectAttributes;
151 NTSTATUS Status;
152 HANDLE DirectoryHandle;
153 ULONG Context = 0;
154 ULONG ReturnLength = 0;
155 ULONG EntryCount = 0;
156
157 /* For expanding symbolic links */
158 WCHAR TargetName [2 * MAX_PATH];
159 UNICODE_STRING TargetObjectName = {
160 sizeof TargetName,
161 sizeof TargetName,
162 TargetName
163 };
164
165 /*
166 * Check user arguments.
167 */
168 if (2 != argc)
169 {
170 fprintf (
171 stderr,
172 "Usage: %s directory\n\n"
173 " directory a directory name in the system namespace\n",
174 argv [0]
175 );
176 return EXIT_FAILURE;
177 }
178 /*
179 * Prepare parameters for next call.
180 */
181 RtlInitAnsiString (
182 & DirectoryNameA,
183 argv [1]
184 );
185 RtlAnsiStringToUnicodeString (
186 & DirectoryNameW,
187 & DirectoryNameA,
188 TRUE
189 );
190 InitializeObjectAttributes (
191 & ObjectAttributes,
192 & DirectoryNameW,
193 0,
194 NULL,
195 NULL
196 );
197 /*
198 * Try opening the directory the
199 * user requested.
200 */
201 Status = NtOpenDirectoryObject (
202 & DirectoryHandle,
203 DIRECTORY_QUERY,
204 & ObjectAttributes
205 );
206 if (!NT_SUCCESS(Status))
207 {
208 printf (
209 "Failed to open directory object (Status: %s)\n",
210 StatusToName (Status)
211 );
212 return EXIT_FAILURE;
213 }
214 printf ("\n Directory of %s\n\n", argv[1]);
215 /*
216 * Enumerate each item in the directory.
217 */
218 Status = NtQueryDirectoryObject (
219 DirectoryHandle,
220 pDirectoryEntry,
221 sizeof DirectoryEntry,
222 FALSE,/* ReturnSingleEntry */
223 TRUE, /* RestartScan */
224 & Context,
225 & ReturnLength
226 );
227 if (!NT_SUCCESS(Status))
228 {
229 printf (
230 "Failed to query directory object (Status: %s)\n",
231 StatusToName (Status)
232 );
233 NtClose (DirectoryHandle);
234 return EXIT_FAILURE;
235 }
236 while (0 != pDirectoryEntry->ObjectTypeName.Length)
237 {
238 CHAR ObjectNameA [MAX_PATH];
239 CHAR TypeNameA [MAX_PATH];
240 CHAR TargetNameA [MAX_PATH];
241
242 if (0 == wcscmp (L"SymbolicLink", pDirectoryEntry->ObjectTypeName.Buffer))
243 {
244 if (TRUE == ExpandSymbolicLink (
245 & DirectoryNameW,
246 & pDirectoryEntry->ObjectName,
247 & TargetObjectName
248 )
249 )
250 {
251
252 printf (
253 "%-16s %s -> %s\n",
254 RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
255 RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA),
256 RawUszAsz (TargetObjectName.Buffer, TargetNameA)
257 );
258 }
259 else
260 {
261 printf (
262 "%-16s %s -> (error!)\n",
263 RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
264 RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA)
265 );
266 }
267 }
268 else
269 {
270 printf (
271 "%-16s %s\n",
272 RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
273 RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA)
274 );
275 }
276 ++ EntryCount;
277 ++ pDirectoryEntry;
278
279
280 }
281 printf ("\n\t%d object(s)\n", EntryCount);
282 /*
283 * Free any resource.
284 */
285 NtClose (DirectoryHandle);
286
287 return EXIT_SUCCESS;
288 }
289
290
291 /* EOF */