[v4 2/3] ntdll: Implement FileIdInformation class support in NtQueryInformationFile (resend).

Sebastian Lackner sebastian at fds-team.de
Fri Feb 10 12:31:57 CST 2017


On 07.02.2017 16:11, Jonathan Doron wrote:
> Signed-off-by: Jonathan Doron <jond at wizery.com>
> ---
>  configure.ac            |  2 +-
>  dlls/ntdll/file.c       | 28 ++++++++++++++++++++++-
>  dlls/ntdll/tests/file.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++
>  include/winternl.h      |  9 ++++++++
>  4 files changed, 97 insertions(+), 2 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index c6d63b2..f66bf44 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2262,7 +2262,7 @@ fi
>  dnl **** FIXME: what about mixed cases, where we need two of them? ***
>  
>  dnl Check for statfs members
> -AC_CHECK_MEMBERS([struct statfs.f_bfree, struct statfs.f_bavail, struct statfs.f_frsize, struct statfs.f_ffree, struct statfs.f_favail, struct statfs.f_namelen],,,
> +AC_CHECK_MEMBERS([struct statfs.f_bfree, struct statfs.f_bavail, struct statfs.f_frsize, struct statfs.f_ffree, struct statfs.f_favail, struct statfs.f_namelen, struct statfs.f_fsid.__val],,,
>  [#include <sys/types.h>
>  #ifdef HAVE_SYS_PARAM_H
>  # include <sys/param.h>
> diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
> index a6c1098..c6ff371 100644
> --- a/dlls/ntdll/file.c
> +++ b/dlls/ntdll/file.c
> @@ -2377,7 +2377,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
>          0,                                             /* FileRenameInformationBypassAccessCheck */
>          0,                                             /* FileLinkInformationBypassAccessCheck */
>          0,                                             /* FileVolumeNameInformation */
> -        0,                                             /* FileIdInformation */
> +        sizeof(FILE_ID_INFORMATION),                   /* FileIdInformation */
>          0,                                             /* FileIdExtdDirectoryInformation */
>          0,                                             /* FileReplaceCompletionInformation */
>          0,                                             /* FileHardLinkFullIdInformation */
> @@ -2619,6 +2619,32 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
>              }
>          }
>          break;
> +    case FileIdInformation:
> +        {
> +            FILE_ID_INFORMATION *info = ptr;
> +            memset(info, 0, sizeof(*info));
> +            if (fstat(fd, &st) == -1)
> +            {
> +                io->u.Status = FILE_GetNtStatus();
> +            }
> +            else
> +            {
> +#if defined(linux) && defined(HAVE_FSTATFS) && defined(HAVE_STRUCT_STATFS_F_FSID___VAL)
> +                struct statfs volstats;
> +                if (fstatfs(fd, &volstats) == -1)
> +                {
> +                    io->u.Status = FILE_GetNtStatus();
> +                    break;
> +                }
> +
> +                memcpy(&info->VolumeSerialNumber,
> +                       &volstats.f_fsid.__val,
> +                       min(sizeof(info->VolumeSerialNumber), sizeof(volstats.f_fsid.__val)));

I didn't think about this earlier, but if you are planning to use memcpy anyway,
wouldn't it be easier to just copy f_fsid directly, instead of f_fsid.__val?
When you do not make any assumptions about f_fsid it would work on all platforms.

> +#endif
> +                ((LARGE_INTEGER *)&info->FileId)->QuadPart = st.st_ino;
> +            }
> +        }
> +        break;
>      default:
>          FIXME("Unsupported class (%d)\n", class);
>          io->u.Status = STATUS_NOT_IMPLEMENTED;
> diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
> index 57d7df9..00856ab 100644
> --- a/dlls/ntdll/tests/file.c
> +++ b/dlls/ntdll/tests/file.c
> @@ -1444,6 +1444,65 @@ static void test_file_basic_information(void)
>      CloseHandle( h );
>  }
>  
> +static void test_file_id_information(void)
> +{
> +    IO_STATUS_BLOCK io;
> +    FILE_ID_INFORMATION fid1, fid2;
> +    HANDLE h = INVALID_HANDLE_VALUE;
> +    NTSTATUS res;
> +    char path[MAX_PATH], buffer[MAX_PATH];
> +
> +    /* Generate a temp file name */

Not all of these steps need an explanation, so you could remove some of
the comments for things which are obvious.

> +    GetTempPathA(MAX_PATH, path);
> +    GetTempFileNameA(path, "foo", 0, buffer);
> +
> +    /* Create the temp file */
> +    h = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
> +    ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
> +
> +    /* Query the temp file unique id */
> +    memset(&fid1, 0, sizeof(fid1));
> +    res = pNtQueryInformationFile(h, &io, &fid1, sizeof fid1, FileIdInformation);

Here you are mixing two styles for sizeof, one with "()" and one without.
The same also applies to a couple of other places below.

> +    if ((res == STATUS_NOT_IMPLEMENTED) || (res == STATUS_INVALID_INFO_CLASS))

The extra "()" is not really necessary.

> +    {
> +        CloseHandle(h);
> +        DeleteFileA(buffer);
> +        win_skip("FileIdInformation not supported\n");
> +        return;
> +    }
> +
> +    ok(res == STATUS_SUCCESS, "can't get fid1, res %x\n", res);
> +
> +    CloseHandle(h);
> +
> +    /* Open the file again */
> +    h = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
> +    ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
> +
> +    /* Query again the temp file unique id */
> +    memset(&fid2, 0, sizeof(fid2));
> +    res = pNtQueryInformationFile(h, &io, &fid2, sizeof fid2, FileIdInformation);
> +    ok(res == STATUS_SUCCESS, "can't get fid2, res %x\n", res);
> +
> +    /* Verify we got the same unique id for the file */
> +    ok(memcmp(&fid1, &fid2, sizeof fid1) == 0, "file id is not unique\n");
> +
> +    CloseHandle(h);
> +
> +    h = create_temp_file(0);
> +    ok(h != NULL, "error creating new file %d\n", GetLastError());
> +
> +    memset(&fid2, 0, sizeof(fid2));
> +    res = pNtQueryInformationFile(h, &io, &fid2, sizeof fid2, FileIdInformation);
> +    ok(res == STATUS_SUCCESS, "can't get new fid2, res %x\n", res);
> +
> +    /* Verify we got the different unique id for the new file */
> +    ok(memcmp(&fid1, &fid2, sizeof fid1) != 0, "file id is not unique\n");
> +
> +    CloseHandle(h);
> +    DeleteFileA(buffer);
> +}
> +
>  static void test_file_all_information(void)
>  {
>      IO_STATUS_BLOCK io;
> @@ -4262,4 +4321,5 @@ START_TEST(file)
>      test_file_disposition_information();
>      test_query_volume_information_file();
>      test_query_attribute_information_file();
> +    test_file_id_information();
>  }
> diff --git a/include/winternl.h b/include/winternl.h
> index 891b6a7..2f2ea86 100644
> --- a/include/winternl.h
> +++ b/include/winternl.h
> @@ -571,6 +571,15 @@ typedef struct _FILE_INTERNAL_INFORMATION {
>      LARGE_INTEGER IndexNumber;
>  } FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
>  
> +typedef struct _FILE_ID_128 {
> +    UCHAR Identifier[16];
> +} FILE_ID_128, *PFILE_ID_128;
> +
> +typedef struct _FILE_ID_INFORMATION {
> +    ULONGLONG VolumeSerialNumber;
> +    FILE_ID_128 FileId;
> +} FILE_ID_INFORMATION, *PFILE_ID_INFORMATION;
> +
>  typedef struct _FILE_EA_INFORMATION {
>      ULONG EaSize;
>  } FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
> -- 2.9.3
> 




More information about the wine-devel mailing list