From - Tue Sep 16 08:07:08 1997 Path: news.mitre.org!blanket.mitre.org!philabs!newsjunkie.ans.net!newsfeeds.ans.net!news-w.ans.net!newsfeeds.ans.net!iagnet.net!newsfeed.internetmci.com!192.220.251.22!netnews.nwnet.net!wrq.com!not-for-mail From: Kelly Lopez File Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode Subject: Re: How to Get a Directory listing from NTKernel mode Date: Mon, 15 Sep 1997 14:54:25 -0700 Organization: WRQ, Inc. Lines: 266 Message-ID: <341DAE91.499E@wrq.com> References: <01bcc1f7$b2022860$7cc4c2d0@YOUNG3> Reply-To: kellyf@nospam.wrq.com NNTP-Posting-Host: 150.215.100.61 Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Mailer: Mozilla 3.01 (Win95; I) To: Russell Young Russell Young wrote: > > Does anyone know how to get a directory listing it NT-Kernel mode? The > ZwCreateFile has access flags of FILE_LIST_DIRECTROY and FILE_TRAVERSE that > indicate they are for listing a directory. And I have been successful in > opening the directory, but what do you do with the handle after you open > the directory? I can not get ZwReadFile to use the handle (did not > supprise me) and I don't see any other API's that might work. Any Ideas? > Russell Young Russell, directory listing require an undocumented ZwXXX call: NTSTATUS ZwQueryDirectoryFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan ); // NtQueryDirectoryFile return types: // // FILE_DIRECTORY_INFORMATION // FILE_FULL_DIR_INFORMATION // FILE_BOTH_DIR_INFORMATION // FILE_NAMES_INFORMATION // typedef struct _FILE_DIRECTORY_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; WCHAR FileName[1]; } FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; typedef struct _FILE_FULL_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; WCHAR FileName[1]; } FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; typedef struct _FILE_BOTH_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; CCHAR ShortNameLength; WCHAR ShortName[12]; WCHAR FileName[1]; } FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; typedef struct _FILE_NAMES_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; ULONG FileNameLength; WCHAR FileName[1]; } FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION; Here's a snippet of code that will do a dir listing: NTSTATUS Dir(int argc, char *argv[]) { NTSTATUS Status; HANDLE Handle=NULL; ACCESS_MASK DesiredAccess=FILE_READ_DATA; OBJECT_ATTRIBUTES ObjectAttributes; ULONG FileAttributes=FILE_ATTRIBUTE_DIRECTORY; ULONG ShareAccess=FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; ULONG CreateDisposition=FILE_OPEN; ULONG CreateOptions=FILE_DIRECTORY_FILE; ANSI_STRING AnsiString; UNICODE_STRING UnicodeString; WCHAR UnicodeStringBuffer[MAX_FILE_LENGTH]; char FileName[MAX_FILE_LENGTH]; PBYTE Info; PFILE_BOTH_DIR_INFORMATION DirInfo; IO_STATUS_BLOCK IoStatus; IoStatus.Status = 0; IoStatus.Information = 0; // // Get the name of the file // strcpy(FileName, "\\DosDevices\\"); strcat(FileName, argv[2]); // <-- your file name here printf("RtlInitAnsiString %s...", FileName); RtlInitAnsiString(&AnsiString, FileName); PrintStatus(STATUS_SUCCESS, NULL); // setup our unicode string UnicodeString.MaximumLength = MAX_FILE_LENGTH*2; UnicodeString.Buffer = UnicodeStringBuffer; printf("RtlAnsiStringToUnicodeString..."); ObjectAttributes.ObjectName = &UnicodeString; Status = RtlAnsiStringToUnicodeString(ObjectAttributes.ObjectName, &AnsiString, FALSE); PrintStatus(Status, NULL); // // Open the file // printf("ZwCreateFile..."); ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); ObjectAttributes.RootDirectory = NULL; ObjectAttributes.Attributes = 0; ObjectAttributes.SecurityDescriptor = NULL; ObjectAttributes.SecurityQualityOfService = NULL; Status = ZwCreateFile( &Handle, DesiredAccess, &ObjectAttributes, &IoStatus, NULL, // AllocationSize FileAttributes, ShareAccess, CreateDisposition, CreateOptions, NULL, // EaBuffer 0); // EaLength PrintStatus(Status, &IoStatus); if (!NT_SUCCESS(Status)) goto CleanUp; // // allocate a large buffer that is 256 bytes long. // Info = (PBYTE)malloc(MAX_DIR_INFO_LENGTH); RtlInitUnicodeString(&UnicodeString, L"*"); printf("ZwQueryDirectoryFile..."); // you will probably need to use an event - without // one you might see "status_pending" returned. Status = ZwQueryDirectoryFile( Handle, NULL, ApcRoutine, NULL, &IoStatus, Info, MAX_DIR_INFO_LENGTH, FileBothDirectoryInformation, FALSE, &UnicodeString, TRUE); PrintStatus(Status, &IoStatus); if (!NT_SUCCESS(Status)) goto CleanUp; printf("\n"); DirInfo = (PFILE_BOTH_DIR_INFORMATION)Info; while(DirInfo) { DumpDirInfo(DirInfo, TRUE); if (DirInfo->NextEntryOffset) Info += DirInfo->NextEntryOffset; else Info = 0; DirInfo = (PFILE_BOTH_DIR_INFORMATION)Info; } printf("\n"); CleanUp: if (Handle) { printf("NtClose (%X)...", Handle); Status = NtClose( Handle); PrintStatus(Status, NULL); } return(0); } //-------------------------------------------------------- // DumpDirInfo //-------------------------------------------------------- void DumpDirInfo( PFILE_BOTH_DIR_INFORMATION DirInfo, BOOLEAN Full ) { PWCHAR Null; WCHAR Save; Null = (PWCHAR)((PBYTE)DirInfo->FileName + DirInfo->FileNameLength); Save = *Null; *Null = 0; if (Full) { printf("\n"); printf("NextEntryOffset = %d\n", DirInfo->NextEntryOffset); printf("FileIndex = %X\n", DirInfo->FileIndex); printf("CreationTime = %X\n", DirInfo->CreationTime.LowPart); printf("LastAccessTime = %X\n", DirInfo->LastAccessTime.LowPart); printf("LastWriteTime = %X\n", DirInfo->LastWriteTime.LowPart); printf("EndOfFile = %X\n", DirInfo->EndOfFile.LowPart); printf("AllocationSize = %X\n", DirInfo->AllocationSize.LowPart); printf("FileAttributes = %X\n", DirInfo->FileAttributes); printf("ShortName = %.12S\n", DirInfo->ShortName); printf("FileName = %S\n", DirInfo->FileName); } else { printf("%-32S %-16.12S %08X %08X\n", DirInfo->FileName, DirInfo->ShortName, DirInfo->FileAttributes, DirInfo->FileIndex); } *Null = Save; } -- Hope this helps. KellyF