1 /* $Id: objdir.c 37749 2008-11-29 21:23:45Z sginsberg $
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 #define WIN32_NO_STATUS
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_MORE_ENTRIES
:
83 return "STATUS_MORE_ENTRIES";
84 case STATUS_ACCESS_DENIED
:
85 return "STATUS_ACCESS_DENIED";
86 case STATUS_UNSUCCESSFUL
:
87 return "STATUS_UNSUCCESSFUL";
88 case STATUS_INVALID_HANDLE
:
89 return "STATUS_INVALID_HANDLE";
91 sprintf (RawValue
, "0x%08lx", Status
);
92 return (const char *) RawValue
;
99 IN PUNICODE_STRING DirectoryName
,
100 IN PUNICODE_STRING SymbolicLinkName
,
101 IN OUT PUNICODE_STRING TargetObjectName
105 HANDLE hSymbolicLink
;
106 OBJECT_ATTRIBUTES oa
;
108 WCHAR PathBuffer
[MAX_PATH
];
109 ULONG DataWritten
= 0;
112 Path
.Buffer
= PathBuffer
;
114 Path
.MaximumLength
= sizeof PathBuffer
;
116 RtlCopyUnicodeString (& Path
, DirectoryName
);
117 if (L
'\\' != Path
.Buffer
[(Path
.Length
/ sizeof Path
.Buffer
[0]) - 1])
119 RtlAppendUnicodeToString (& Path
, L
"\\");
121 RtlAppendUnicodeStringToString (& Path
, SymbolicLinkName
);
123 oa
.Length
= sizeof (OBJECT_ATTRIBUTES
);
124 oa
.ObjectName
= & Path
;
125 oa
.Attributes
= 0; /* OBJ_CASE_INSENSITIVE; */
126 oa
.RootDirectory
= NULL
;
127 oa
.SecurityDescriptor
= NULL
;
128 oa
.SecurityQualityOfService
= NULL
;
130 Status
= NtOpenSymbolicLinkObject(
132 SYMBOLIC_LINK_QUERY
, /* 0x20001 */
136 if (!NT_SUCCESS(Status
))
139 "Failed to open SymbolicLink object (Status: %s)\n",
140 StatusToName (Status
)
144 TargetObjectName
->Length
= TargetObjectName
->MaximumLength
;
146 TargetObjectName
->Buffer
,
148 TargetObjectName
->MaximumLength
150 Status
= NtQuerySymbolicLinkObject(
155 if (!NT_SUCCESS(Status
))
158 "Failed to query SymbolicLink object (Status: %s)\n",
159 StatusToName (Status
)
161 NtClose (hSymbolicLink
);
164 NtClose (hSymbolicLink
);
172 IN PUNICODE_STRING DirectoryNameW
,
176 CHAR DirectoryNameA
[MAX_PATH
];
177 OBJECT_ATTRIBUTES ObjectAttributes
;
179 HANDLE DirectoryHandle
;
180 BYTE DirectoryEntry
[512];
181 POBJECT_DIRECTORY_INFORMATION pDirectoryEntry
= (POBJECT_DIRECTORY_INFORMATION
) DirectoryEntry
;
182 POBJECT_DIRECTORY_INFORMATION pDirectoryEntries
= (POBJECT_DIRECTORY_INFORMATION
) DirectoryEntry
;
184 ULONG ReturnLength
= 0;
185 ULONG EntryCount
= 0;
187 /* For expanding symbolic links */
188 WCHAR TargetName
[2 * MAX_PATH
];
189 UNICODE_STRING TargetObjectName
= {
195 /* Convert to ANSI the directory's name */
196 RawUszAsz (DirectoryNameW
->Buffer
, DirectoryNameA
);
198 * Prepare parameters for next call.
200 InitializeObjectAttributes (
208 * Try opening the directory.
210 Status
= NtOpenDirectoryObject (
215 if (!NT_SUCCESS(Status
))
218 "Failed to open directory object \"%s\" (Status: %s)\n",
220 StatusToName (Status
)
224 printf ("\n Directory of %s\n\n", DirectoryNameA
);
229 * Enumerate each item in the directory.
231 Status
= NtQueryDirectoryObject (
234 sizeof DirectoryEntry
,
235 FALSE
,/* ReturnSingleEntry */
236 FALSE
, /* RestartScan */
240 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NO_MORE_ENTRIES
)
243 "Failed to query directory object (Status: %s)\n",
244 StatusToName (Status
)
246 NtClose (DirectoryHandle
);
249 if (Status
== STATUS_NO_MORE_ENTRIES
)
253 pDirectoryEntry
= pDirectoryEntries
;
254 while (EntryCount
< Context
)
256 CHAR ObjectNameA
[MAX_PATH
];
257 CHAR TypeNameA
[MAX_PATH
];
258 CHAR TargetNameA
[MAX_PATH
];
260 if (0 == wcscmp (L
"SymbolicLink", pDirectoryEntry
->TypeName
.Buffer
))
262 if (TRUE
== ExpandSymbolicLink (
264 & pDirectoryEntry
->Name
,
272 RawUszAsz (pDirectoryEntry
->TypeName
.Buffer
, TypeNameA
),
273 RawUszAsz (pDirectoryEntry
->Name
.Buffer
, ObjectNameA
),
274 RawUszAsz (TargetObjectName
.Buffer
, TargetNameA
)
280 "%-16s %s -> (error!)\n",
281 RawUszAsz (pDirectoryEntry
->TypeName
.Buffer
, TypeNameA
),
282 RawUszAsz (pDirectoryEntry
->Name
.Buffer
, ObjectNameA
)
290 RawUszAsz (pDirectoryEntry
->TypeName
.Buffer
, TypeNameA
),
291 RawUszAsz (pDirectoryEntry
->Name
.Buffer
, ObjectNameA
)
298 printf ("\n\t%lu object(s)\n", EntryCount
);
302 NtClose (DirectoryHandle
);
304 * Recurse into, if required so.
306 if (FALSE
!= Recurse
)
308 pDirectoryEntry
= (POBJECT_DIRECTORY_INFORMATION
) DirectoryEntry
;
309 while (0 != pDirectoryEntry
->TypeName
.Length
)
311 if (0 == wcscmp (L
"Directory", pDirectoryEntry
->TypeName
.Buffer
))
313 WCHAR CurrentName
[MAX_PATH
];
314 UNICODE_STRING CurrentDirectory
;
316 CurrentName
[0] = L
'\0';
317 wcscpy (CurrentName
, DirectoryNameW
->Buffer
);
318 if (wcslen (CurrentName
) > 1)
320 wcscat (CurrentName
, L
"\\");
322 wcscat (CurrentName
, pDirectoryEntry
->Name
.Buffer
);
323 RtlInitUnicodeString (& CurrentDirectory
, CurrentName
);
324 ListDirectory (& CurrentDirectory
, Recurse
);
333 int main(int argc
, char* argv
[])
335 WCHAR DirectoryNameW
[MAX_PATH
];
336 UNICODE_STRING DirectoryName
;
337 BOOL Recurse
= FALSE
;
340 * Check user arguments.
345 RawAszUsz (argv
[1], DirectoryNameW
);
348 if (strcmp (argv
[1], "-r"))
352 "%s: unknown option '%s'.\n",
357 RawAszUsz (argv
[2], DirectoryNameW
);
363 "\nUsage: %s [-r] directory\n\n"
365 " directory a directory name in the system namespace\n\n",
371 * List the directory.
373 RtlInitUnicodeString (& DirectoryName
, DirectoryNameW
);
374 return (FALSE
== ListDirectory (& DirectoryName
, Recurse
))