Martin Storsjo : kernel32: Implement a few more classes in GetFileInformationByHandleEx.

Alexandre Julliard julliard at wine.codeweavers.com
Thu May 21 07:24:23 CDT 2015


Module: wine
Branch: master
Commit: 68b654ad2fe18aad6b9b0d0128656753f6639442
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=68b654ad2fe18aad6b9b0d0128656753f6639442

Author: Martin Storsjo <martin at martin.st>
Date:   Wed May 20 20:44:56 2015 +0300

kernel32: Implement a few more classes in GetFileInformationByHandleEx.

---

 dlls/kernel32/file.c       | 31 +++++++++++---------
 dlls/kernel32/tests/file.c | 72 ++++++++++++++++++++++++++++++++++++++++++++--
 include/winbase.h          | 21 ++++++++++++++
 3 files changed, 107 insertions(+), 17 deletions(-)

diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c
index 006db1c..a680ab2 100644
--- a/dlls/kernel32/file.c
+++ b/dlls/kernel32/file.c
@@ -897,8 +897,6 @@ BOOL WINAPI GetFileInformationByHandleEx( HANDLE handle, FILE_INFO_BY_HANDLE_CLA
 
     switch (class)
     {
-    case FileBasicInfo:
-    case FileStandardInfo:
     case FileRenameInfo:
     case FileDispositionInfo:
     case FileAllocationInfo:
@@ -919,31 +917,36 @@ BOOL WINAPI GetFileInformationByHandleEx( HANDLE handle, FILE_INFO_BY_HANDLE_CLA
         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
         return FALSE;
 
+    case FileBasicInfo:
+        status = NtQueryInformationFile( handle, &io, info, size, FileBasicInformation );
+        break;
+
+    case FileStandardInfo:
+        status = NtQueryInformationFile( handle, &io, info, size, FileStandardInformation );
+        break;
+
     case FileNameInfo:
         status = NtQueryInformationFile( handle, &io, info, size, FileNameInformation );
-        if (status != STATUS_SUCCESS)
-        {
-            SetLastError( RtlNtStatusToDosError( status ) );
-            return FALSE;
-        }
-        return TRUE;
+        break;
 
     case FileIdBothDirectoryRestartInfo:
     case FileIdBothDirectoryInfo:
         status = NtQueryDirectoryFile( handle, NULL, NULL, NULL, &io, info, size,
                                        FileIdBothDirectoryInformation, FALSE, NULL,
                                        (class == FileIdBothDirectoryRestartInfo) );
-        if (status != STATUS_SUCCESS)
-        {
-            SetLastError( RtlNtStatusToDosError( status ) );
-            return FALSE;
-        }
-        return TRUE;
+        break;
 
     default:
         SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
+
+    if (status != STATUS_SUCCESS)
+    {
+        SetLastError( RtlNtStatusToDosError( status ) );
+        return FALSE;
+    }
+    return TRUE;
 }
 
 
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index 64b0b8b..bd85e01 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -3821,11 +3821,15 @@ else
 static void test_GetFileInformationByHandleEx(void)
 {
     int i;
-    char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024];
+    char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024], *strPtr;
     BOOL ret;
-    DWORD ret2;
-    HANDLE directory;
+    DWORD ret2, written;
+    HANDLE directory, file;
     FILE_ID_BOTH_DIR_INFO *bothDirInfo;
+    FILE_BASIC_INFO *basicInfo;
+    FILE_STANDARD_INFO *standardInfo;
+    FILE_NAME_INFO *nameInfo;
+    LARGE_INTEGER prevWrite;
     struct {
         FILE_INFO_BY_HANDLE_CLASS handleClass;
         void *ptr;
@@ -3888,6 +3892,68 @@ static void test_GetFileInformationByHandleEx(void)
     }
 
     CloseHandle(directory);
+
+    file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+        NULL, OPEN_EXISTING, 0, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
+        "got error %u.\n", GetLastError());
+
+    /* Test FileBasicInfo; make sure the write time changes when a file is updated */
+    memset(buffer, 0xff, sizeof(buffer));
+    ret = pGetFileInformationByHandleEx(file, FileBasicInfo, buffer, sizeof(buffer));
+    ok(ret, "GetFileInformationByHandleEx: failed to get FileBasicInfo, %u\n", GetLastError());
+    basicInfo = (FILE_BASIC_INFO *)buffer;
+    prevWrite = basicInfo->LastWriteTime;
+    CloseHandle(file);
+
+    Sleep(30); /* Make sure a new write time is different from the previous */
+
+    /* Write something to the file, to make sure the write time has changed */
+    file = CreateFileA(tempFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+        NULL, OPEN_EXISTING, 0, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
+        "got error %u.\n", GetLastError());
+    ret = WriteFile(file, tempFileName, strlen(tempFileName), &written, NULL);
+    ok(ret, "GetFileInformationByHandleEx: Write failed\n");
+    CloseHandle(file);
+
+    file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+        NULL, OPEN_EXISTING, 0, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
+        "got error %u.\n", GetLastError());
+
+    memset(buffer, 0xff, sizeof(buffer));
+    ret = pGetFileInformationByHandleEx(file, FileBasicInfo, buffer, sizeof(buffer));
+    ok(ret, "GetFileInformationByHandleEx: failed to get FileBasicInfo, %u\n", GetLastError());
+    basicInfo = (FILE_BASIC_INFO *)buffer;
+    /* Could also check that the creation time didn't change - on windows
+     * it doesn't, but on wine, it does change even if it shouldn't. */
+    ok(basicInfo->LastWriteTime.QuadPart != prevWrite.QuadPart,
+        "GetFileInformationByHandleEx: last write time didn't change\n");
+
+    /* Test FileStandardInfo, check some basic parameters */
+    memset(buffer, 0xff, sizeof(buffer));
+    ret = pGetFileInformationByHandleEx(file, FileStandardInfo, buffer, sizeof(buffer));
+    ok(ret, "GetFileInformationByHandleEx: failed to get FileStandardInfo, %u\n", GetLastError());
+    standardInfo = (FILE_STANDARD_INFO *)buffer;
+    ok(standardInfo->NumberOfLinks == 1, "GetFileInformationByHandleEx: Unexpcted number of links\n");
+    ok(standardInfo->DeletePending == FALSE, "GetFileInformationByHandleEx: Unexpcted pending delete\n");
+    ok(standardInfo->Directory == FALSE, "GetFileInformationByHandleEx: Incorrect directory flag\n");
+
+    /* Test FileNameInfo */
+    memset(buffer, 0xff, sizeof(buffer));
+    ret = pGetFileInformationByHandleEx(file, FileNameInfo, buffer, sizeof(buffer));
+    ok(ret, "GetFileInformationByHandleEx: failed to get FileNameInfo, %u\n", GetLastError());
+    nameInfo = (FILE_NAME_INFO *)buffer;
+    strPtr = strchr(tempFileName, '\\');
+    ok(strPtr != NULL, "GetFileInformationByHandleEx: Temp filename didn't contain backslash\n");
+    ok(nameInfo->FileNameLength == strlen(strPtr) * 2,
+        "GetFileInformationByHandleEx: Incorrect file name length\n");
+    for (i = 0; i < nameInfo->FileNameLength/2; i++)
+        ok(strPtr[i] == nameInfo->FileName[i], "Incorrect filename char %d: %c vs %c\n",
+            i, strPtr[i], nameInfo->FileName[i]);
+    CloseHandle(file);
+
     DeleteFileA(tempFileName);
 }
 
diff --git a/include/winbase.h b/include/winbase.h
index 7540e6d..3601051 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -823,6 +823,27 @@ typedef struct _FILE_ID_BOTH_DIR_INFO {
     WCHAR         FileName[1];
 } FILE_ID_BOTH_DIR_INFO, *PFILE_ID_BOTH_DIR_INFO;
 
+typedef struct _FILE_BASIC_INFO {
+    LARGE_INTEGER CreationTime;
+    LARGE_INTEGER LastAccessTime;
+    LARGE_INTEGER LastWriteTime;
+    LARGE_INTEGER ChangeTime;
+    DWORD         FileAttributes;
+} FILE_BASIC_INFO, *PFILE_BASIC_INFO;
+
+typedef struct _FILE_STANDARD_INFO {
+    LARGE_INTEGER AllocationSize;
+    LARGE_INTEGER EndOfFile;
+    DWORD         NumberOfLinks;
+    BOOLEAN       DeletePending;
+    BOOLEAN       Directory;
+} FILE_STANDARD_INFO, *PFILE_STANDARD_INFO;
+
+typedef struct _FILE_NAME_INFO {
+    DWORD         FileNameLength;
+    WCHAR         FileName[1];
+} FILE_NAME_INFO, *PFILE_NAME_INFO;
+
 #define PIPE_ACCESS_INBOUND  1
 #define PIPE_ACCESS_OUTBOUND 2
 #define PIPE_ACCESS_DUPLEX   3




More information about the wine-cvs mailing list