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