Added a few more info classes in NtQueryInformationFile.

Use NT file names in CreateNamedPipeW.
Reimplemented GetFileInformationByHandle, GetFileSize and GetFileTime
using ntdll functions.
This commit is contained in:
Alexandre Julliard 2004-04-30 21:03:09 +00:00
parent ff07c20446
commit d4874d6406
5 changed files with 287 additions and 151 deletions

View File

@ -330,15 +330,48 @@ BOOL WINAPI FlushFileBuffers( HANDLE hFile )
}
/***********************************************************************
* GetFileInformationByHandle (KERNEL32.@)
*/
BOOL WINAPI GetFileInformationByHandle( HANDLE hFile, BY_HANDLE_FILE_INFORMATION *info )
{
FILE_ALL_INFORMATION all_info;
IO_STATUS_BLOCK io;
NTSTATUS status;
status = NtQueryInformationFile( hFile, &io, &all_info, sizeof(all_info), FileAllInformation );
if (status == STATUS_SUCCESS)
{
info->dwFileAttributes = all_info.BasicInformation.FileAttributes;
info->ftCreationTime.dwHighDateTime = all_info.BasicInformation.CreationTime.u.HighPart;
info->ftCreationTime.dwLowDateTime = all_info.BasicInformation.CreationTime.u.LowPart;
info->ftLastAccessTime.dwHighDateTime = all_info.BasicInformation.LastAccessTime.u.HighPart;
info->ftLastAccessTime.dwLowDateTime = all_info.BasicInformation.LastAccessTime.u.LowPart;
info->ftLastWriteTime.dwHighDateTime = all_info.BasicInformation.LastWriteTime.u.HighPart;
info->ftLastWriteTime.dwLowDateTime = all_info.BasicInformation.LastWriteTime.u.LowPart;
info->dwVolumeSerialNumber = 0; /* FIXME */
info->nFileSizeHigh = all_info.StandardInformation.EndOfFile.u.HighPart;
info->nFileSizeLow = all_info.StandardInformation.EndOfFile.u.LowPart;
info->nNumberOfLinks = all_info.StandardInformation.NumberOfLinks;
info->nFileIndexHigh = all_info.InternalInformation.IndexNumber.u.HighPart;
info->nFileIndexLow = all_info.InternalInformation.IndexNumber.u.LowPart;
return TRUE;
}
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
/***********************************************************************
* GetFileSize (KERNEL32.@)
*/
DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD filesizehigh )
{
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle( hFile, &info )) return -1;
if (filesizehigh) *filesizehigh = info.nFileSizeHigh;
return info.nFileSizeLow;
LARGE_INTEGER size;
if (!GetFileSizeEx( hFile, &size )) return INVALID_FILE_SIZE;
if (filesizehigh) *filesizehigh = size.u.HighPart;
if (size.u.LowPart == INVALID_FILE_SIZE) SetLastError(0);
return size.u.LowPart;
}
@ -347,24 +380,54 @@ DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD filesizehigh )
*/
BOOL WINAPI GetFileSizeEx( HANDLE hFile, PLARGE_INTEGER lpFileSize )
{
BY_HANDLE_FILE_INFORMATION info;
FILE_END_OF_FILE_INFORMATION info;
IO_STATUS_BLOCK io;
NTSTATUS status;
if (!lpFileSize)
status = NtQueryInformationFile( hFile, &io, &info, sizeof(info), FileEndOfFileInformation );
if (status == STATUS_SUCCESS)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (!GetFileInformationByHandle( hFile, &info ))
{
return FALSE;
}
lpFileSize->u.LowPart = info.nFileSizeLow;
lpFileSize->u.HighPart = info.nFileSizeHigh;
*lpFileSize = info.EndOfFile;
return TRUE;
}
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
/***********************************************************************
* GetFileTime (KERNEL32.@)
*/
BOOL WINAPI GetFileTime( HANDLE hFile, FILETIME *lpCreationTime,
FILETIME *lpLastAccessTime, FILETIME *lpLastWriteTime )
{
FILE_BASIC_INFORMATION info;
IO_STATUS_BLOCK io;
NTSTATUS status;
status = NtQueryInformationFile( hFile, &io, &info, sizeof(info), FileBasicInformation );
if (status == STATUS_SUCCESS)
{
if (lpCreationTime)
{
lpCreationTime->dwHighDateTime = info.CreationTime.u.HighPart;
lpCreationTime->dwLowDateTime = info.CreationTime.u.LowPart;
}
if (lpLastAccessTime)
{
lpLastAccessTime->dwHighDateTime = info.LastAccessTime.u.HighPart;
lpLastAccessTime->dwLowDateTime = info.LastAccessTime.u.LowPart;
}
if (lpLastWriteTime)
{
lpLastWriteTime->dwHighDateTime = info.LastWriteTime.u.HighPart;
lpLastWriteTime->dwLowDateTime = info.LastWriteTime.u.LowPart;
}
return TRUE;
}
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
/***********************************************************************

View File

@ -1037,27 +1037,29 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
{
HANDLE ret;
DWORD len;
static const WCHAR leadin[] = {'\\','\\','.','\\','P','I','P','E','\\'};
UNICODE_STRING nt_name;
static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
if (!name)
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
{
SetLastError( ERROR_PATH_NOT_FOUND );
return INVALID_HANDLE_VALUE;
}
len = strlenW(name);
if (len >= MAX_PATH)
if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
RtlFreeUnicodeString( &nt_name );
return INVALID_HANDLE_VALUE;
}
if (strncmpiW(name, leadin, sizeof(leadin)/sizeof(leadin[0])))
if (nt_name.Length < sizeof(leadin) ||
strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
{
SetLastError( ERROR_INVALID_NAME );
RtlFreeUnicodeString( &nt_name );
return INVALID_HANDLE_VALUE;
}
SERVER_START_REQ( create_named_pipe )
@ -1069,12 +1071,13 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
req->insize = nInBufferSize;
req->timeout = nDefaultTimeOut;
req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
wine_server_add_data( req, name, len * sizeof(WCHAR) );
wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
SetLastError(0);
if (!wine_server_call_err( req )) ret = reply->handle;
else ret = INVALID_HANDLE_VALUE;
}
SERVER_END_REQ;
RtlFreeUnicodeString( &nt_name );
return ret;
}

View File

@ -156,8 +156,8 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
{
req->access = access;
req->inherit = (attr->Attributes & OBJ_INHERIT) != 0;
wine_server_add_data( req, attr->ObjectName->Buffer + sizeof(pipeW)/sizeof(WCHAR),
attr->ObjectName->Length - sizeof(pipeW) );
wine_server_add_data( req, attr->ObjectName->Buffer + 4,
attr->ObjectName->Length - 4*sizeof(WCHAR) );
io->u.Status = wine_server_call( req );
*handle = reply->handle;
}
@ -835,11 +835,64 @@ NTSTATUS WINAPI NtSetVolumeInformationFile(
NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
PVOID ptr, LONG len, FILE_INFORMATION_CLASS class )
{
static const size_t info_sizes[] =
{
0,
sizeof(FILE_DIRECTORY_INFORMATION), /* FileDirectoryInformation */
sizeof(FILE_FULL_DIRECTORY_INFORMATION), /* FileFullDirectoryInformation */
sizeof(FILE_BOTH_DIRECTORY_INFORMATION), /* FileBothDirectoryInformation */
sizeof(FILE_BASIC_INFORMATION), /* FileBasicInformation */
sizeof(FILE_STANDARD_INFORMATION), /* FileStandardInformation */
sizeof(FILE_INTERNAL_INFORMATION), /* FileInternalInformation */
sizeof(FILE_EA_INFORMATION), /* FileEaInformation */
sizeof(FILE_ACCESS_INFORMATION), /* FileAccessInformation */
sizeof(FILE_NAME_INFORMATION)-sizeof(WCHAR), /* FileNameInformation */
sizeof(FILE_RENAME_INFORMATION)-sizeof(WCHAR), /* FileRenameInformation */
0, /* FileLinkInformation */
sizeof(FILE_NAMES_INFORMATION)-sizeof(WCHAR), /* FileNamesInformation */
sizeof(FILE_DISPOSITION_INFORMATION), /* FileDispositionInformation */
sizeof(FILE_POSITION_INFORMATION), /* FilePositionInformation */
sizeof(FILE_FULL_EA_INFORMATION), /* FileFullEaInformation */
sizeof(FILE_MODE_INFORMATION), /* FileModeInformation */
sizeof(FILE_ALIGNMENT_INFORMATION), /* FileAlignmentInformation */
sizeof(FILE_ALL_INFORMATION)-sizeof(WCHAR), /* FileAllInformation */
sizeof(FILE_ALLOCATION_INFORMATION), /* FileAllocationInformation */
sizeof(FILE_END_OF_FILE_INFORMATION), /* FileEndOfFileInformation */
0, /* FileAlternateNameInformation */
sizeof(FILE_STREAM_INFORMATION)-sizeof(WCHAR), /* FileStreamInformation */
0, /* FilePipeInformation */
0, /* FilePipeLocalInformation */
0, /* FilePipeRemoteInformation */
0, /* FileMailslotQueryInformation */
0, /* FileMailslotSetInformation */
0, /* FileCompressionInformation */
0, /* FileObjectIdInformation */
0, /* FileCompletionInformation */
0, /* FileMoveClusterInformation */
0, /* FileQuotaInformation */
0, /* FileReparsePointInformation */
0, /* FileNetworkOpenInformation */
0, /* FileAttributeTagInformation */
0 /* FileTrackingInformation */
};
struct stat st;
int fd;
TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io, ptr, len, class);
io->Information = 0;
if (class <= 0 || class >= FileMaximumInformation)
return io->u.Status = STATUS_INVALID_INFO_CLASS;
if (!info_sizes[class])
{
FIXME("Unsupported class (%d)\n", class);
return io->u.Status = STATUS_NOT_IMPLEMENTED;
}
if (len < info_sizes[class])
return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
if ((io->u.Status = wine_server_handle_to_fd( hFile, 0, &fd, NULL, NULL )))
return io->u.Status;
@ -849,11 +902,6 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
{
FILE_BASIC_INFORMATION *info = ptr;
if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
else
{
struct stat st;
if (fstat( fd, &st ) == -1)
io->u.Status = FILE_GetNtStatus();
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
@ -869,17 +917,11 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime);
}
}
}
break;
case FileStandardInformation:
{
FILE_STANDARD_INFORMATION *info = ptr;
if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
else
{
struct stat st;
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
else
{
@ -897,25 +939,78 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
info->NumberOfLinks = st.st_nlink;
info->DeletePending = FALSE; /* FIXME */
}
io->Information = sizeof(*info);
}
}
}
break;
case FilePositionInformation:
{
FILE_POSITION_INFORMATION *info = ptr;
if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
else
{
off_t res = lseek( fd, 0, SEEK_CUR );
if (res == (off_t)-1) io->u.Status = FILE_GetNtStatus();
else info->CurrentByteOffset.QuadPart = res;
}
break;
case FileInternalInformation:
{
FILE_INTERNAL_INFORMATION *info = ptr;
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
else info->IndexNumber.QuadPart = st.st_ino;
}
break;
case FileEaInformation:
{
FILE_EA_INFORMATION *info = ptr;
info->EaSize = 0;
}
break;
case FileEndOfFileInformation:
{
FILE_END_OF_FILE_INFORMATION *info = ptr;
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
else info->EndOfFile.QuadPart = S_ISDIR(st.st_mode) ? 0 : st.st_size;
}
break;
case FileAllInformation:
{
FILE_ALL_INFORMATION *info = ptr;
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
io->u.Status = STATUS_INVALID_INFO_CLASS;
else
{
info->CurrentByteOffset.QuadPart = res;
io->Information = sizeof(*info);
if ((info->StandardInformation.Directory = S_ISDIR(st.st_mode)))
{
info->BasicInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
info->StandardInformation.AllocationSize.QuadPart = 0;
info->StandardInformation.EndOfFile.QuadPart = 0;
info->StandardInformation.NumberOfLinks = 1;
info->StandardInformation.DeletePending = FALSE;
}
else
{
info->BasicInformation.FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
info->StandardInformation.AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
info->StandardInformation.EndOfFile.QuadPart = st.st_size;
info->StandardInformation.NumberOfLinks = st.st_nlink;
info->StandardInformation.DeletePending = FALSE; /* FIXME */
}
if (!(st.st_mode & S_IWUSR))
info->BasicInformation.FileAttributes |= FILE_ATTRIBUTE_READONLY;
RtlSecondsSince1970ToTime( st.st_mtime, &info->BasicInformation.CreationTime);
RtlSecondsSince1970ToTime( st.st_mtime, &info->BasicInformation.LastWriteTime);
RtlSecondsSince1970ToTime( st.st_ctime, &info->BasicInformation.ChangeTime);
RtlSecondsSince1970ToTime( st.st_atime, &info->BasicInformation.LastAccessTime);
info->InternalInformation.IndexNumber.QuadPart = st.st_ino;
info->EaInformation.EaSize = 0;
info->AccessInformation.AccessFlags = 0; /* FIXME */
info->PositionInformation.CurrentByteOffset.QuadPart = lseek( fd, 0, SEEK_CUR );
info->ModeInformation.Mode = 0; /* FIXME */
info->AlignmentInformation.AlignmentRequirement = 1; /* FIXME */
info->NameInformation.FileNameLength = 0;
io->Information = sizeof(*info) - sizeof(WCHAR);
}
}
break;
@ -925,6 +1020,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
break;
}
wine_server_release_fd( hFile, fd );
if (io->u.Status == STATUS_SUCCESS && !io->Information) io->Information = info_sizes[class];
return io->u.Status;
}

View File

@ -396,92 +396,6 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
}
/***********************************************************************
* FILE_FillInfo
*
* Fill a file information from a struct stat.
*/
static void FILE_FillInfo( struct stat *st, BY_HANDLE_FILE_INFORMATION *info )
{
if (S_ISDIR(st->st_mode))
info->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
else
info->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
if (!(st->st_mode & S_IWUSR))
info->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
RtlSecondsSince1970ToTime( st->st_mtime, (LARGE_INTEGER *)&info->ftCreationTime );
RtlSecondsSince1970ToTime( st->st_mtime, (LARGE_INTEGER *)&info->ftLastWriteTime );
RtlSecondsSince1970ToTime( st->st_atime, (LARGE_INTEGER *)&info->ftLastAccessTime );
info->dwVolumeSerialNumber = 0; /* FIXME */
if (S_ISDIR(st->st_mode))
{
info->nFileSizeHigh = 0;
info->nFileSizeLow = 0;
info->nNumberOfLinks = 1;
}
else
{
info->nFileSizeHigh = st->st_size >> 32;
info->nFileSizeLow = (DWORD)st->st_size;
info->nNumberOfLinks = st->st_nlink;
}
info->nFileIndexHigh = st->st_ino >> 32;
info->nFileIndexLow = (DWORD)st->st_ino;
}
/***********************************************************************
* GetFileInformationByHandle (KERNEL32.@)
*/
BOOL WINAPI GetFileInformationByHandle( HANDLE hFile, BY_HANDLE_FILE_INFORMATION *info )
{
NTSTATUS status;
int fd;
BOOL ret = FALSE;
TRACE("%p,%p\n", hFile, info);
if (!info) return 0;
if (!(status = wine_server_handle_to_fd( hFile, 0, &fd, NULL, NULL )))
{
struct stat st;
if (fstat( fd, &st ) == -1)
FILE_SetDosError();
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
SetLastError( ERROR_INVALID_FUNCTION );
else
{
FILE_FillInfo( &st, info );
ret = TRUE;
}
wine_server_release_fd( hFile, fd );
}
else SetLastError( RtlNtStatusToDosError(status) );
return ret;
}
/***********************************************************************
* GetFileTime (KERNEL32.@)
*/
BOOL WINAPI GetFileTime( HANDLE hFile, FILETIME *lpCreationTime,
FILETIME *lpLastAccessTime,
FILETIME *lpLastWriteTime )
{
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle( hFile, &info )) return FALSE;
if (lpCreationTime) *lpCreationTime = info.ftCreationTime;
if (lpLastAccessTime) *lpLastAccessTime = info.ftLastAccessTime;
if (lpLastWriteTime) *lpLastWriteTime = info.ftLastWriteTime;
return TRUE;
}
/***********************************************************************
* GetTempFileNameA (KERNEL32.@)
*/

View File

@ -306,6 +306,41 @@ typedef struct _FILE_STANDARD_INFORMATION {
BOOLEAN Directory;
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
typedef struct _FILE_INTERNAL_INFORMATION {
LARGE_INTEGER IndexNumber;
} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
typedef struct _FILE_EA_INFORMATION {
ULONG EaSize;
} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
typedef struct _FILE_ACCESS_INFORMATION {
ACCESS_MASK AccessFlags;
} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
typedef struct _FILE_RENAME_INFORMATION {
BOOLEAN Replace;
HANDLE RootDir;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
typedef struct _FILE_DISPOSITION_INFORMATION {
BOOLEAN DoDeleteFile;
} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
typedef struct _FILE_POSITION_INFORMATION {
LARGE_INTEGER CurrentByteOffset;
} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
@ -314,6 +349,14 @@ typedef struct _FILE_ALIGNMENT_INFORMATION {
ULONG AlignmentRequirement;
} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;
typedef struct _FILE_ALLOCATION_INFORMATION {
LARGE_INTEGER AllocationSize;
} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION;
typedef struct _FILE_END_OF_FILE_INFORMATION {
LARGE_INTEGER EndOfFile;
} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION;
typedef struct _FILE_NETWORK_OPEN_INFORMATION {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
@ -332,6 +375,10 @@ typedef struct _FILE_FULL_EA_INFORMATION {
CHAR EaName[1];
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
typedef struct _FILE_MODE_INFORMATION {
ULONG Mode;
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
typedef struct _FILE_STREAM_INFORMATION
{
ULONG NextEntryOffset;
@ -347,6 +394,19 @@ struct _FILE_ATTRIBUTE_TAG_INFORMATION
ULONG ReparseTag;
} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION;
typedef struct _FILE_ALL_INFORMATION
{
FILE_BASIC_INFORMATION BasicInformation;
FILE_STANDARD_INFORMATION StandardInformation;
FILE_INTERNAL_INFORMATION InternalInformation;
FILE_EA_INFORMATION EaInformation;
FILE_ACCESS_INFORMATION AccessInformation;
FILE_POSITION_INFORMATION PositionInformation;
FILE_MODE_INFORMATION ModeInformation;
FILE_ALIGNMENT_INFORMATION AlignmentInformation;
FILE_NAME_INFORMATION NameInformation;
} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
typedef enum _FSINFOCLASS {
FileFsVolumeInformation = 1,
FileFsLabelInformation,