ntdll: Make the various directory info size functions depend on the info class.

This commit is contained in:
Alexandre Julliard 2009-11-18 17:54:06 +01:00
parent ee9b19ab5f
commit 551ddfe402
1 changed files with 30 additions and 17 deletions

View File

@ -154,8 +154,6 @@ union file_directory_info
FILE_BOTH_DIRECTORY_INFORMATION both; FILE_BOTH_DIRECTORY_INFORMATION both;
}; };
static const unsigned int max_dir_info_size = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, FileName[MAX_DIR_ENTRY_LEN] );
static int show_dot_files = -1; static int show_dot_files = -1;
/* at some point we may want to allow Winelib apps to set this */ /* at some point we may want to allow Winelib apps to set this */
@ -221,6 +219,23 @@ static inline BOOL is_ignored_file( const struct stat *st )
return FALSE; return FALSE;
} }
static inline unsigned int dir_info_size( FILE_INFORMATION_CLASS class, unsigned int len )
{
switch (class)
{
case FileBothDirectoryInformation:
return (FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, FileName[len] ) + 3) & ~3;
default:
assert(0);
}
}
static inline unsigned int max_dir_info_size( FILE_INFORMATION_CLASS class )
{
return dir_info_size( class, MAX_DIR_ENTRY_LEN );
}
/*********************************************************************** /***********************************************************************
* get_default_com_device * get_default_com_device
* *
@ -990,7 +1005,7 @@ static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK
if (!show_dot_files && long_name[0] == '.' && long_name[1] && (long_name[1] != '.' || long_name[2])) if (!show_dot_files && long_name[0] == '.' && long_name[1] && (long_name[1] != '.' || long_name[2]))
attributes |= FILE_ATTRIBUTE_HIDDEN; attributes |= FILE_ATTRIBUTE_HIDDEN;
total_len = (FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName[long_len]) + 3) & ~3; total_len = dir_info_size( class, long_len );
if (io->Information + total_len > max_length) if (io->Information + total_len > max_length)
{ {
total_len = max_length - io->Information; total_len = max_length - io->Information;
@ -1082,7 +1097,7 @@ static int read_directory_vfat( int fd, IO_STATUS_BLOCK *io, void *buffer, ULONG
if (restart_scan) lseek( fd, 0, SEEK_SET ); if (restart_scan) lseek( fd, 0, SEEK_SET );
if (length < max_dir_info_size) /* we may have to return a partial entry here */ if (length < max_dir_info_size(class)) /* we may have to return a partial entry here */
{ {
off_t old_pos = lseek( fd, 0, SEEK_CUR ); off_t old_pos = lseek( fd, 0, SEEK_CUR );
@ -1132,7 +1147,7 @@ static int read_directory_vfat( int fd, IO_STATUS_BLOCK *io, void *buffer, ULONG
last_info = info; last_info = info;
if (single_entry) break; if (single_entry) break;
/* check if we still have enough space for the largest possible entry */ /* check if we still have enough space for the largest possible entry */
if (io->Information + max_dir_info_size > length) break; if (io->Information + max_dir_info_size(class) > length) break;
} }
if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) == -1) break; if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) == -1) break;
} }
@ -1169,7 +1184,7 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
} }
if (restart_scan) lseek( fd, 0, SEEK_SET ); if (restart_scan) lseek( fd, 0, SEEK_SET );
else if (length < max_dir_info_size) /* we may have to return a partial entry here */ else if (length < max_dir_info_size(class)) /* we may have to return a partial entry here */
{ {
old_pos = lseek( fd, 0, SEEK_CUR ); old_pos = lseek( fd, 0, SEEK_CUR );
if (old_pos == -1 && errno == ENOENT) if (old_pos == -1 && errno == ENOENT)
@ -1209,8 +1224,7 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
/* make sure we have enough room for both entries */ /* make sure we have enough room for both entries */
if (fake_dot_dot) if (fake_dot_dot)
{ {
static const ULONG min_info_size = (FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName[1]) + const ULONG min_info_size = dir_info_size( class, 1 ) + dir_info_size( class, 2 );
FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName[2]) + 3) & ~3;
if (length < min_info_size || single_entry) if (length < min_info_size || single_entry)
{ {
FIXME( "not enough room %u/%u for fake . and .. entries\n", length, single_entry ); FIXME( "not enough room %u/%u for fake . and .. entries\n", length, single_entry );
@ -1226,7 +1240,7 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
last_info = info; last_info = info;
/* check if we still have enough space for the largest possible entry */ /* check if we still have enough space for the largest possible entry */
if (last_info && io->Information + max_dir_info_size > length) if (last_info && io->Information + max_dir_info_size(class) > length)
{ {
lseek( fd, 0, SEEK_SET ); /* reset pos to first entry */ lseek( fd, 0, SEEK_SET ); /* reset pos to first entry */
res = 0; res = 0;
@ -1248,7 +1262,7 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
break; break;
} }
/* check if we still have enough space for the largest possible entry */ /* check if we still have enough space for the largest possible entry */
if (single_entry || io->Information + max_dir_info_size > length) if (single_entry || io->Information + max_dir_info_size(class) > length)
{ {
if (res > 0) lseek( fd, de->d_off, SEEK_SET ); /* set pos to next entry */ if (res > 0) lseek( fd, de->d_off, SEEK_SET ); /* set pos to next entry */
break; break;
@ -1372,8 +1386,7 @@ static int read_directory_getdirentries( int fd, IO_STATUS_BLOCK *io, void *buff
/* make sure we have enough room for both entries */ /* make sure we have enough room for both entries */
if (fake_dot_dot) if (fake_dot_dot)
{ {
static const ULONG min_info_size = (FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName[1]) + const ULONG min_info_size = dir_info_size( class, 1 ) + dir_info_size( class, 2 );
FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName[2]) + 3) & ~3;
if (length < min_info_size || single_entry) if (length < min_info_size || single_entry)
{ {
FIXME( "not enough room %u/%u for fake . and .. entries\n", length, single_entry ); FIXME( "not enough room %u/%u for fake . and .. entries\n", length, single_entry );
@ -1392,7 +1405,7 @@ static int read_directory_getdirentries( int fd, IO_STATUS_BLOCK *io, void *buff
restart_info_pos = io->Information; restart_info_pos = io->Information;
/* check if we still have enough space for the largest possible entry */ /* check if we still have enough space for the largest possible entry */
if (last_info && io->Information + max_dir_info_size > length) if (last_info && io->Information + max_dir_info_size(class) > length)
{ {
lseek( fd, 0, SEEK_SET ); /* reset pos to first entry */ lseek( fd, 0, SEEK_SET ); /* reset pos to first entry */
res = 0; res = 0;
@ -1426,7 +1439,7 @@ static int read_directory_getdirentries( int fd, IO_STATUS_BLOCK *io, void *buff
goto restart; goto restart;
} }
/* if we have to return but the buffer contains more data, restart with a smaller size */ /* if we have to return but the buffer contains more data, restart with a smaller size */
if (res > 0 && (single_entry || io->Information + max_dir_info_size > length)) if (res > 0 && (single_entry || io->Information + max_dir_info_size(class) > length))
{ {
lseek( fd, (unsigned long)restart_pos, SEEK_SET ); lseek( fd, (unsigned long)restart_pos, SEEK_SET );
size = (char *)de - data; size = (char *)de - data;
@ -1444,7 +1457,7 @@ static int read_directory_getdirentries( int fd, IO_STATUS_BLOCK *io, void *buff
if (size < initial_size) break; /* already restarted once, give up now */ if (size < initial_size) break; /* already restarted once, give up now */
size = min( size, length - io->Information ); size = min( size, length - io->Information );
/* if size is too small don't bother to continue */ /* if size is too small don't bother to continue */
if (size < max_dir_info_size && last_info) break; if (size < max_dir_info_size(class) && last_info) break;
restart_last_info = last_info; restart_last_info = last_info;
restart_info_pos = io->Information; restart_info_pos = io->Information;
restart: restart:
@ -1530,7 +1543,7 @@ static void read_directory_readdir( int fd, IO_STATUS_BLOCK *io, void *buffer, U
} }
if (single_entry) break; if (single_entry) break;
/* check if we still have enough space for the largest possible entry */ /* check if we still have enough space for the largest possible entry */
if (io->Information + max_dir_info_size > length) break; if (io->Information + max_dir_info_size(class) > length) break;
} }
} }
@ -1638,7 +1651,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event,
switch (info_class) switch (info_class)
{ {
case FileBothDirectoryInformation: case FileBothDirectoryInformation:
if (length < sizeof(FILE_BOTH_DIR_INFORMATION)) return io->u.Status = STATUS_INFO_LENGTH_MISMATCH; if (length < dir_info_size( info_class, 1 )) return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
break; break;
default: default:
FIXME( "Unsupported file info class %d\n", info_class ); FIXME( "Unsupported file info class %d\n", info_class );