winpr: add GetFileInformationByHandle

This commit is contained in:
Zhengyi Fu 2022-03-22 16:25:40 +08:00 committed by akallabeth
parent 14568872a9
commit e62aaff319
6 changed files with 154 additions and 43 deletions

View File

@ -216,6 +216,20 @@ typedef struct
WCHAR cAlternateFileName[14];
} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW;
typedef struct
{
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD dwVolumeSerialNumber;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD nNumberOfLinks;
DWORD nFileIndexHigh;
DWORD nFileIndexLow;
} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION;
typedef enum
{
FindExInfoStandard,
@ -312,6 +326,9 @@ extern "C"
WINPR_API DWORD GetFileAttributesW(LPCWSTR lpFileName);
WINPR_API BOOL GetFileInformationByHandle(HANDLE hFile,
LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
WINPR_API BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes);
WINPR_API BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes);

View File

@ -325,6 +325,69 @@ static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh)
return (UINT32)(size & 0xFFFFFFFF);
}
static BOOL FileGetFileInformationByHandle(HANDLE hFile,
LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
{
WINPR_FILE* pFile = (WINPR_FILE*)hFile;
struct stat st;
UINT64 ft;
const char* lastSep;
if (!pFile)
return FALSE;
if (!lpFileInformation)
return FALSE;
if (fstat(fileno(pFile->fp), &st) == -1)
{
WLog_ERR(TAG, "fstat failed with %s [%#08X]", errno, strerror(errno));
return FALSE;
}
lpFileInformation->dwFileAttributes = 0;
if (S_ISDIR(st.st_mode))
lpFileInformation->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
if (lpFileInformation->dwFileAttributes == 0)
lpFileInformation->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
lastSep = strrchr(pFile->lpFileName, '/');
if (lastSep)
{
const char* name = lastSep + 1;
const size_t namelen = strlen(name);
if ((namelen > 1) && (name[0] == '.') && (name[1] != '.'))
lpFileInformation->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
}
if (!(st.st_mode & S_IWUSR))
lpFileInformation->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
#ifdef _DARWIN_FEATURE_64_BIT_INODE
ft = STAT_TIME_TO_FILETIME(st.st_birthtime);
#else
ft = STAT_TIME_TO_FILETIME(st.st_ctime);
#endif
lpFileInformation->ftCreationTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
lpFileInformation->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF;
ft = STAT_TIME_TO_FILETIME(st.st_mtime);
lpFileInformation->ftLastWriteTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
lpFileInformation->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF;
ft = STAT_TIME_TO_FILETIME(st.st_atime);
lpFileInformation->ftLastAccessTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
lpFileInformation->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF;
lpFileInformation->nFileSizeHigh = ((UINT64)st.st_size) >> 32ULL;
lpFileInformation->nFileSizeLow = st.st_size & 0xFFFFFFFF;
lpFileInformation->dwVolumeSerialNumber = st.st_dev;
lpFileInformation->nNumberOfLinks = st.st_nlink;
lpFileInformation->nFileIndexHigh = (st.st_ino >> 4) & 0xFFFFFFFF;
lpFileInformation->nFileIndexLow = st.st_ino & 0xFFFFFFFF;
return TRUE;
}
static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
LPOVERLAPPED lpOverlapped)
@ -484,10 +547,10 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte
static UINT64 FileTimeToUS(const FILETIME* ft)
{
const UINT64 EPOCH_DIFF = 11644473600ULL * 1000000ULL;
const UINT64 EPOCH_DIFF_US = EPOCH_DIFF * 1000000ULL;
UINT64 tmp = ((UINT64)ft->dwHighDateTime) << 32 | ft->dwLowDateTime;
tmp /= 10; /* 100ns steps to 1us step */
tmp -= EPOCH_DIFF;
tmp -= EPOCH_DIFF_US;
return tmp;
}
@ -586,44 +649,52 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
return TRUE;
}
static HANDLE_OPS fileOps = { FileIsHandled,
FileCloseHandle,
FileGetFd,
NULL, /* CleanupHandle */
FileRead,
NULL, /* FileReadEx */
NULL, /* FileReadScatter */
FileWrite,
NULL, /* FileWriteEx */
NULL, /* FileWriteGather */
FileGetFileSize,
NULL, /* FlushFileBuffers */
FileSetEndOfFile,
FileSetFilePointer,
FileSetFilePointerEx,
NULL, /* FileLockFile */
FileLockFileEx,
FileUnlockFile,
FileUnlockFileEx,
FileSetFileTime };
static HANDLE_OPS fileOps = {
FileIsHandled,
FileCloseHandle,
FileGetFd,
NULL, /* CleanupHandle */
FileRead,
NULL, /* FileReadEx */
NULL, /* FileReadScatter */
FileWrite,
NULL, /* FileWriteEx */
NULL, /* FileWriteGather */
FileGetFileSize,
NULL, /* FlushFileBuffers */
FileSetEndOfFile,
FileSetFilePointer,
FileSetFilePointerEx,
NULL, /* FileLockFile */
FileLockFileEx,
FileUnlockFile,
FileUnlockFileEx,
FileSetFileTime,
FileGetFileInformationByHandle,
};
static HANDLE_OPS shmOps = {
FileIsHandled, FileCloseHandle,
FileGetFd, NULL, /* CleanupHandle */
FileRead, NULL, /* FileReadEx */
NULL, /* FileReadScatter */
FileWrite, NULL, /* FileWriteEx */
NULL, /* FileWriteGather */
NULL, /* FileGetFileSize */
NULL, /* FlushFileBuffers */
NULL, /* FileSetEndOfFile */
NULL, /* FileSetFilePointer */
NULL, /* SetFilePointerEx */
NULL, /* FileLockFile */
NULL, /* FileLockFileEx */
NULL, /* FileUnlockFile */
NULL, /* FileUnlockFileEx */
NULL /* FileSetFileTime */
FileIsHandled,
FileCloseHandle,
FileGetFd,
NULL, /* CleanupHandle */
FileRead,
NULL, /* FileReadEx */
NULL, /* FileReadScatter */
FileWrite,
NULL, /* FileWriteEx */
NULL, /* FileWriteGather */
NULL, /* FileGetFileSize */
NULL, /* FlushFileBuffers */
NULL, /* FileSetEndOfFile */
NULL, /* FileSetFilePointer */
NULL, /* SetFilePointerEx */
NULL, /* FileLockFile */
NULL, /* FileLockFileEx */
NULL, /* FileUnlockFile */
NULL, /* FileUnlockFileEx */
NULL, /* FileSetFileTime */
FileGetFileInformationByHandle,
};
static const char* FileGetMode(DWORD dwDesiredAccess, DWORD dwCreationDisposition, BOOL* create)

View File

@ -34,6 +34,9 @@
#include <stdio.h>
#include "../handle/handle.h"
#define EPOCH_DIFF 11644473600LL
#define STAT_TIME_TO_FILETIME(_t) (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL)
struct winpr_file
{
WINPR_HANDLE_DEF();

View File

@ -173,10 +173,6 @@
* Asynchronous I/O User Guide:
* http://code.google.com/p/kernel/wiki/AIOUserGuide
*/
#define EPOCH_DIFF 11644473600LL
#define STAT_TIME_TO_FILETIME(_t) (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL)
static wArrayList* _HandleCreators;
static pthread_once_t _HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
@ -537,6 +533,26 @@ DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
return ret;
}
BOOL GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
{
ULONG Type;
WINPR_HANDLE* handle;
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
return FALSE;
handle = (WINPR_HANDLE*)hFile;
if (handle->ops->GetFileInformationByHandle)
return handle->ops->GetFileInformationByHandle(handle, lpFileInformation);
WLog_ERR(TAG, "GetFileInformationByHandle operation not implemented");
return 0;
}
static char* append(char* buffer, size_t size, const char* append)
{
const size_t len = strnlen(buffer, size);

View File

@ -121,7 +121,8 @@ static HANDLE_OPS ops = {
NULL, /* FileLockFileEx */
NULL, /* FileUnlockFile */
NULL, /* FileUnlockFileEx */
NULL /* SetFileTime */
NULL, /* SetFileTime */
NULL, /* FileGetFileInformationByHandle */
};
static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess,

View File

@ -66,6 +66,8 @@ typedef BOOL (*pcWriteFileGather)(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArr
DWORD nNumberOfBytesToWrite, LPDWORD lpReserved,
LPOVERLAPPED lpOverlapped);
typedef DWORD (*pcGetFileSize)(HANDLE handle, LPDWORD lpFileSizeHigh);
typedef BOOL (*pcGetFileInformationByHandle)(HANDLE handle,
LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
typedef BOOL (*pcFlushFileBuffers)(HANDLE hFile);
typedef BOOL (*pcSetEndOfFile)(HANDLE handle);
typedef DWORD (*pcSetFilePointer)(HANDLE handle, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
@ -106,6 +108,7 @@ typedef struct
pcUnlockFile UnlockFile;
pcUnlockFileEx UnlockFileEx;
pcSetFileTime SetFileTime;
pcGetFileInformationByHandle GetFileInformationByHandle;
} HANDLE_OPS;
struct winpr_handle