3 * DESCRIPTION: Object Manager Simple Explorer
4 * PROGRAMMER: David Welch
7 * Added directory enumeration.
8 * (tested under nt4sp4/x86)
10 * Added symbolic link expansion.
11 * (tested under nt4sp4/x86)
13 * Fixed entries counter. Added more
14 * error codes check. Removed wprintf,
15 * because it does not work in .17.
20 #include <ddk/ntddk.h>
26 #define MAX_DIR_ENTRY 256
37 register PCHAR a = szA;
39 while (*szU) {*szA++ = (CHAR) (0x00ff & * szU++);}
53 register PWCHAR w = szW;
55 while (*szA) {*szW++ = (WCHAR) *szA++;}
64 StatusToName (NTSTATUS Status)
66 static char RawValue [16];
70 case STATUS_BUFFER_TOO_SMALL:
71 return "STATUS_BUFFER_TOO_SMALL";
72 case STATUS_INVALID_PARAMETER:
73 return "STATUS_INVALID_PARAMETER";
74 case STATUS_OBJECT_NAME_INVALID:
75 return "STATUS_OBJECT_NAME_INVALID";
76 case STATUS_OBJECT_NAME_NOT_FOUND:
77 return "STATUS_OBJECT_NAME_NOT_FOUND";
78 case STATUS_PATH_SYNTAX_BAD:
79 return "STATUS_PATH_SYNTAX_BAD";
80 case STATUS_NO_MORE_ENTRIES:
81 return "STATUS_NO_MORE_ENTRIES";
82 case STATUS_UNSUCCESSFUL:
83 return "STATUS_UNSUCCESSFUL";
85 sprintf (RawValue, "0x%08lx", Status);
86 return (const char *) RawValue;
93 IN PUNICODE_STRING DirectoryName,
94 IN PUNICODE_STRING SymbolicLinkName,
95 IN OUT PUNICODE_STRING TargetObjectName
100 OBJECT_ATTRIBUTES oa;
102 WCHAR PathBuffer [MAX_PATH];
103 ULONG DataWritten = 0;
106 Path.Buffer = PathBuffer;
108 Path.MaximumLength = sizeof PathBuffer;
110 RtlCopyUnicodeString (& Path, DirectoryName);
111 if (L'\\' != Path.Buffer [(Path.Length / sizeof Path.Buffer[0]) - 1])
113 RtlAppendUnicodeToString (& Path, L"\\");
115 RtlAppendUnicodeStringToString (& Path, SymbolicLinkName);
117 oa.Length = sizeof (OBJECT_ATTRIBUTES);
118 oa.ObjectName = & Path;
119 oa.Attributes = 0; /* OBJ_CASE_INSENSITIVE; */
120 oa.RootDirectory = NULL;
121 oa.SecurityDescriptor = NULL;
122 oa.SecurityQualityOfService = NULL;
124 Status = NtOpenSymbolicLinkObject(
126 SYMBOLIC_LINK_QUERY, /* 0x20001 */
130 if (!NT_SUCCESS(Status))
133 "Failed to open SymbolicLink object (Status: %s)\n",
134 StatusToName (Status)
138 TargetObjectName->Length = TargetObjectName->MaximumLength;
140 TargetObjectName->Buffer,
142 TargetObjectName->MaximumLength
144 Status = NtQuerySymbolicLinkObject(
149 if (!NT_SUCCESS(Status))
152 "Failed to query SymbolicLink object (Status: %s)\n",
153 StatusToName (Status)
155 NtClose (hSymbolicLink);
158 NtClose (hSymbolicLink);
166 IN PUNICODE_STRING DirectoryNameW,
170 CHAR DirectoryNameA [MAX_PATH];
171 OBJECT_ATTRIBUTES ObjectAttributes;
173 HANDLE DirectoryHandle;
174 BYTE DirectoryEntry [MAX_DIR_ENTRY * sizeof(OBJDIR_INFORMATION)];
175 POBJDIR_INFORMATION pDirectoryEntry = (POBJDIR_INFORMATION) DirectoryEntry;
177 ULONG ReturnLength = 0;
178 ULONG EntryCount = 0;
180 /* For expanding symbolic links */
181 WCHAR TargetName [2 * MAX_PATH];
182 UNICODE_STRING TargetObjectName = {
188 /* Convert to ANSI the directory's name */
189 RawUszAsz (DirectoryNameW->Buffer, DirectoryNameA);
191 * Prepare parameters for next call.
193 InitializeObjectAttributes (
201 * Try opening the directory.
203 Status = NtOpenDirectoryObject (
208 if (!NT_SUCCESS(Status))
211 "Failed to open directory object \"%s\" (Status: %s)\n",
213 StatusToName (Status)
217 printf ("\n Directory of %s\n\n", DirectoryNameA);
219 * Enumerate each item in the directory.
221 Status = NtQueryDirectoryObject (
224 sizeof DirectoryEntry,
225 FALSE,/* ReturnSingleEntry */
226 TRUE, /* RestartScan */
230 if (!NT_SUCCESS(Status))
232 if (STATUS_NO_MORE_ENTRIES == Status)
234 NtClose (DirectoryHandle);
238 "Failed to query directory object (Status: %s)\n",
239 StatusToName (Status)
241 NtClose (DirectoryHandle);
244 while (0 != pDirectoryEntry->ObjectTypeName.Length)
246 CHAR ObjectNameA [MAX_PATH];
247 CHAR TypeNameA [MAX_PATH];
248 CHAR TargetNameA [MAX_PATH];
250 if (0 == wcscmp (L"SymbolicLink", pDirectoryEntry->ObjectTypeName.Buffer))
252 if (TRUE == ExpandSymbolicLink (
254 & pDirectoryEntry->ObjectName,
262 RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
263 RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA),
264 RawUszAsz (TargetObjectName.Buffer, TargetNameA)
270 "%-16s %s -> (error!)\n",
271 RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
272 RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA)
280 RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA),
281 RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA)
287 printf ("\n\t%d object(s)\n", EntryCount);
291 NtClose (DirectoryHandle);
293 * Recurse into, if required so.
295 if (FALSE != Recurse)
297 pDirectoryEntry = (POBJDIR_INFORMATION) DirectoryEntry;
298 while (0 != pDirectoryEntry->ObjectTypeName.Length)
300 if (0 == wcscmp (L"Directory", pDirectoryEntry->ObjectTypeName.Buffer))
302 WCHAR CurrentName [MAX_PATH];
303 UNICODE_STRING CurrentDirectory;
305 CurrentName [0] = L'\0';
306 wcscpy (CurrentName, DirectoryNameW->Buffer);
307 if (wcslen (CurrentName) > 1)
309 wcscat (CurrentName, L"\\");
311 wcscat (CurrentName, pDirectoryEntry->ObjectName.Buffer);
312 RtlInitUnicodeString (& CurrentDirectory, CurrentName);
313 ListDirectory (& CurrentDirectory, Recurse);
322 int main(int argc, char* argv[])
324 WCHAR DirectoryNameW [MAX_PATH];
325 UNICODE_STRING DirectoryName;
326 BOOL Recurse = FALSE;
329 * Check user arguments.
334 RawAszUsz (argv[1], DirectoryNameW);
337 if (strcmp (argv[1], "-r"))
341 "%s: unknown option '%s'.\n",
346 RawAszUsz (argv[2], DirectoryNameW);
352 "\nUsage: %s [-r] directory\n\n"
354 " directory a directory name in the system namespace\n\n",
360 * List the directory.
362 RtlInitUnicodeString (& DirectoryName, DirectoryNameW);
363 return (FALSE == ListDirectory (& DirectoryName, Recurse))