Skip to content

Instantly share code, notes, and snippets.

@malkia
Created December 16, 2011 18:54
Show Gist options
  • Save malkia/1487388 to your computer and use it in GitHub Desktop.
Save malkia/1487388 to your computer and use it in GitHub Desktop.
Win32: Reading directory in one kernel call
// Not sure whether it's faster than FindFirstFile, etc. - but it does it in one kernel call
#include <windows.h>
#include <stdio.h>
// to compile:
// cl fileinfo.c setargv.obj
void fileinfo(const char*name);
int main( int argc, const char* argv[] )
{
int i;
if( argc == 1 )
printf( "fileinfo: Dumps GetFileInformationByHandleEx Information\n" );
for( i=1; i<argc; i++ ) {
fileinfo(argv[i]);
printf("\n");
}
return 0;
}
void fileinfo(const char*name)
{
int i, j;
HANDLE h = CreateFileA(
name,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL
);
if( h == INVALID_HANDLE_VALUE ) {
fprintf( stderr, "%s: error hr=%p\n", name, GetLastError() );
return;
}
for( i=0; i<256; i++ )
{
static __declspec(align(8)) unsigned char buffer1[64*1024*1024];
static __declspec(align(8)) unsigned char buffer2[64*1024*1024];
if(!GetFileInformationByHandleEx(h, (FILE_INFO_BY_HANDLE_CLASS)i, buffer1, sizeof(buffer1)) )
continue;
memset(&buffer1, 0xBA, sizeof(buffer1));
memset(&buffer2, 0xFD, sizeof(buffer2));
if(!GetFileInformationByHandleEx(h, (FILE_INFO_BY_HANDLE_CLASS)i, buffer1, sizeof(buffer1))
|| !GetFileInformationByHandleEx(h, (FILE_INFO_BY_HANDLE_CLASS)i, buffer2, sizeof(buffer2)))
continue;
for( j=0; j<sizeof(buffer1); j++ )
{
if( buffer1[j] == buffer2[j] )
continue;
if( buffer1[j] == 0xBA && buffer2[j] == 0xFD )
break;
printf( "%s: info %p differs at %p\n", name, i, j );
break;
}
switch( i ) {
case FileBasicInfo: {
PFILE_BASIC_INFO info = (PFILE_BASIC_INFO)buffer1;
printf( "%s: FILE_BASIC_INFO (%d)\n", name, i );
printf( "%s: CreationTime = %I64u\n", name, info->CreationTime.QuadPart );
printf( "%s: LastAccessTime = %I64u\n", name, info->LastAccessTime.QuadPart );
printf( "%s: LastWriteTime = %I64u\n", name, info->LastWriteTime.QuadPart );
printf( "%s: ChangeTime = %I64u\n", name, info->ChangeTime.QuadPart );
printf( "%s: FileAttributes = 0x%p\n", name, info->FileAttributes );
} break;
case FileStandardInfo: {
PFILE_STANDARD_INFO info = (PFILE_STANDARD_INFO)buffer1;
printf( "%s: FILE_STANDARD_INFO (%d)\n", name, i );
printf( "%s: AllocationSize = %I64u\n", name, info->AllocationSize.QuadPart );
printf( "%s: EndOfFile = %I64u\n", name, info->EndOfFile.QuadPart );
printf( "%s: NumberOfLinks = %d\n", name, info->NumberOfLinks );
printf( "%s: DeletePending = %d\n", name, info->DeletePending );
printf( "%s: Directory = %d\n", name, info->Directory );
} break;
case FileNameInfo: {
PFILE_NAME_INFO info = (PFILE_NAME_INFO)buffer1;
printf( "%s: FILE_NAME_INFO (%d)\n", name, i );
printf( "%s: FileNameLength = %d\n", name, info->FileNameLength );
printf( "%s: FileName = %*.*S\n", name, info->FileNameLength/2, info->FileNameLength/2, info->FileName ); // UNICODE, hence /2
} break;
case FileStreamInfo: {
int entryIndex = 0;
PFILE_STREAM_INFO info = (PFILE_STREAM_INFO)buffer1;
printf( "%s: FILE_STREAM_INFO (%d)\n", name, i );
for( ;; ) {
printf( "%s: Stream = %d\n", name, entryIndex );
printf( "%s: NextEntryOffset = 0x%p\n", name, info->NextEntryOffset );
printf( "%s: StreamNameLength = %d\n", name, info->StreamNameLength );
printf( "%s: StreamSize = %I64u\n", name, info->StreamSize.QuadPart );
printf( "%s: StreamAllocationSize = %I64u\n", name, info->StreamAllocationSize.QuadPart );
printf( "%s: StreamName = %*.*S\n", name, info->StreamNameLength/2, info->StreamNameLength/2, info->StreamName ); // UNICODE, hence /2
if( !info->NextEntryOffset )
break;
entryIndex ++;
info = (PFILE_STREAM_INFO)( (char*)info + info->NextEntryOffset );
};
} break;
case FileCompressionInfo: {
PFILE_COMPRESSION_INFO info = (PFILE_COMPRESSION_INFO)buffer1;
printf( "%s: FILE_COMPRESSION_INFO (%d)\n", name, i );
printf( "%s: CompressedFileSize = %I64u\n", name, info->CompressedFileSize.QuadPart );
printf( "%s: CompressionFormat = %d\n", name, info->CompressionFormat);
printf( "%s: CompressionUnitShift = %d\n", name, info->CompressionUnitShift);
printf( "%s: ChunkShift = %d\n", name, info->ChunkShift);
printf( "%s: ClusterShift = %d\n", name, info->ClusterShift);
printf( "%s: Reserved[3] = %d %d %d\n", name, info->Reserved[0],info->Reserved[1],info->Reserved[2]);
} break;
case FileAttributeTagInfo: {
PFILE_ATTRIBUTE_TAG_INFO info = (PFILE_ATTRIBUTE_TAG_INFO)buffer1;
printf( "%s: FILE_ATTRIBUTE_TAG_INFO (%d)\n", name, i );
printf( "%s: FileAttributes = 0x%p\n", name, info->FileAttributes);
printf( "%s: ReparseTag = 0x%p\n", name, info->ReparseTag);
} break;
case FileIdBothDirectoryInfo:
case FileIdBothDirectoryRestartInfo: {
int entryIndex = 0;
PFILE_ID_BOTH_DIR_INFO info = (PFILE_ID_BOTH_DIR_INFO)buffer1;
printf( "%s: FILE_ID_BOTH_DIR_INFO (%d) size=%p\n", name, i, j );
for( ;; ) {
printf( "%s: Entry = 0x%p %d 0x%p\n", name, (char*)info - (char*)buffer1, entryIndex, (char*)info - (char*)buffer1 + sizeof(FILE_ID_BOTH_DIR_INFO)*2 );
printf( "%s: NextEntryOffset = 0x%p\n", name, info->NextEntryOffset );
printf( "%s: FileIndex = %d\n", name, info->FileIndex );
printf( "%s: CreationTime = %I64u\n", name, info->CreationTime.QuadPart );
printf( "%s: LastAccessTime = %I64u\n", name, info->LastAccessTime.QuadPart );
printf( "%s: LastWriteTime = %I64u\n", name, info->LastWriteTime.QuadPart );
printf( "%s: ChangeTime = %I64u\n", name, info->ChangeTime.QuadPart );
printf( "%s: EndOfFile = %I64u\n", name, info->EndOfFile.QuadPart );
printf( "%s: AllocationSize = %I64u\n", name, info->AllocationSize.QuadPart );
printf( "%s: FileAttributes = 0x%p\n", name, info->FileAttributes);
printf( "%s: FileNameLength = %d\n", name, info->FileNameLength );
printf( "%s: EaSize = %d\n", name, info->EaSize );
printf( "%s: ShortNameLength = %d\n", name, info->ShortNameLength );
printf( "%s: ShortName = %*.*S\n", name, info->ShortNameLength/2, info->ShortNameLength/2, info->ShortName );
printf( "%s: FileId = %I64u\n", name, info->FileId );
printf( "%s: FileName = %*.*S\n", name, info->FileNameLength/2, info->FileNameLength/2, info->FileName ); // UNICODE, hence /2
if( !info->NextEntryOffset )
break;
entryIndex++;
info = (PFILE_ID_BOTH_DIR_INFO)( (char*)info + info->NextEntryOffset );
}
} break;
default: {
printf( "%s: UKNOWN_FILE_INFO (%d) sized %d bytes\n", name, i, j );
} break;
}
}
CloseHandle(h);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment