1 /* $Id: objdir.c,v 1.13 2003/11/11 17:00:41 ekohl Exp $
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_OBJECT_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(DIRECTORY_BASIC_INFORMATION
)];
175 PDIRECTORY_BASIC_INFORMATION pDirectoryEntry
= (PDIRECTORY_BASIC_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%lu object(s)\n", EntryCount
);
291 NtClose (DirectoryHandle
);
293 * Recurse into, if required so.
295 if (FALSE
!= Recurse
)
297 pDirectoryEntry
= (PDIRECTORY_BASIC_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
))