From f6a70969e1d1cce3bfa5a02770812c11de932b0b Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Tue, 24 Jun 2003 02:32:01 +0000 Subject: [PATCH] - start moving a few file related functions from files/file.c to dlls/kernel subdir (also splitting 16bit APIs in a separate file) - implemented ntdll.Nt{Lock|Unlock}File, and made use of those for the kernel32 equivalent - implemented a few information classes in NtQueryInformationFile and NtSetInformationFile (still lots of missing classes) - enhanced the get_file_info server request in order to implement correctly NtQueryInformationFile (change time & file alloc size) - rewrote registry loading to comply with latest changes --- dlls/kernel/Makefile.in | 2 + dlls/kernel/file.c | 347 +++++++++++++++++++++++ dlls/kernel/file16.c | 220 +++++++++++++++ dlls/kernel/kernel_private.h | 5 + dlls/ntdll/file.c | 267 ++++++++++++++++-- dlls/ntdll/ntdll.spec | 8 +- files/file.c | 502 +-------------------------------- include/wine/server_protocol.h | 5 +- include/winternl.h | 4 + misc/registry.c | 35 +-- server/file.c | 15 +- server/protocol.def | 3 + server/trace.c | 3 + 13 files changed, 874 insertions(+), 542 deletions(-) create mode 100644 dlls/kernel/file.c create mode 100644 dlls/kernel/file16.c diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in index e0410cff550..8a26c2846c5 100644 --- a/dlls/kernel/Makefile.in +++ b/dlls/kernel/Makefile.in @@ -28,6 +28,8 @@ C_SRCS = \ console.c \ debugger.c \ editline.c \ + file.c \ + file16.c \ format_msg.c \ kernel_main.c \ lcformat.c \ diff --git a/dlls/kernel/file.c b/dlls/kernel/file.c new file mode 100644 index 00000000000..dca832c604f --- /dev/null +++ b/dlls/kernel/file.c @@ -0,0 +1,347 @@ +/* + * File handling functions + * + * Copyright 1993 John Burton + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * TODO: + * Fix the CopyFileEx methods to implement the "extended" functionality. + * Right now, they simply call the CopyFile method. + */ + +#include "config.h" +#include "wine/port.h" + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winternl.h" + +#include "kernel_private.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(file); + +/************************************************************************** + * Operations on file handles * + **************************************************************************/ + +/*********************************************************************** + * _hread (KERNEL32.@) + */ +LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count) +{ + return _lread( hFile, buffer, count ); +} + + +/*********************************************************************** + * _hwrite (KERNEL32.@) + * + * experimentation yields that _lwrite: + * o truncates the file at the current position with + * a 0 len write + * o returns 0 on a 0 length write + * o works with console handles + * + */ +LONG WINAPI _hwrite( HFILE handle, LPCSTR buffer, LONG count ) +{ + DWORD result; + + TRACE("%d %p %ld\n", handle, buffer, count ); + + if (!count) + { + /* Expand or truncate at current position */ + if (!SetEndOfFile( (HANDLE)handle )) return HFILE_ERROR; + return 0; + } + if (!WriteFile( (HANDLE)handle, buffer, count, &result, NULL )) + return HFILE_ERROR; + return result; +} + + +/*********************************************************************** + * _lclose (KERNEL32.@) + */ +HFILE WINAPI _lclose( HFILE hFile ) +{ + TRACE("handle %d\n", hFile ); + return CloseHandle( (HANDLE)hFile ) ? 0 : HFILE_ERROR; +} + + +/*********************************************************************** + * _lcreat (KERNEL32.@) + */ +HFILE WINAPI _lcreat( LPCSTR path, INT attr ) +{ + /* Mask off all flags not explicitly allowed by the doc */ + attr &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; + TRACE("%s %02x\n", path, attr ); + return (HFILE)CreateFileA( path, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + CREATE_ALWAYS, attr, 0 ); +} + + +/*********************************************************************** + * _lopen (KERNEL32.@) + */ +HFILE WINAPI _lopen( LPCSTR path, INT mode ) +{ + DWORD access, sharing; + + TRACE("('%s',%04x)\n", path, mode ); + FILE_ConvertOFMode( mode, &access, &sharing ); + return (HFILE)CreateFileA( path, access, sharing, NULL, OPEN_EXISTING, 0, 0 ); +} + + +/*********************************************************************** + * _lread (KERNEL32.@) + */ +UINT WINAPI _lread( HFILE handle, LPVOID buffer, UINT count ) +{ + DWORD result; + if (!ReadFile( (HANDLE)handle, buffer, count, &result, NULL )) return -1; + return result; +} + + +/*********************************************************************** + * _llseek (KERNEL32.@) + */ +LONG WINAPI _llseek( HFILE hFile, LONG lOffset, INT nOrigin ) +{ + return SetFilePointer( (HANDLE)hFile, lOffset, NULL, nOrigin ); +} + + +/*********************************************************************** + * _lwrite (KERNEL32.@) + */ +UINT WINAPI _lwrite( HFILE hFile, LPCSTR buffer, UINT count ) +{ + return (UINT)_hwrite( hFile, buffer, (LONG)count ); +} + + +/*********************************************************************** + * FlushFileBuffers (KERNEL32.@) + */ +BOOL WINAPI FlushFileBuffers( HANDLE hFile ) +{ + NTSTATUS nts; + IO_STATUS_BLOCK ioblk; + + if (is_console_handle( hFile )) + { + /* this will fail (as expected) for an output handle */ + /* FIXME: wait until FlushFileBuffers is moved to dll/kernel */ + /* return FlushConsoleInputBuffer( hFile ); */ + return TRUE; + } + nts = NtFlushBuffersFile( hFile, &ioblk ); + if (nts != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError( nts ) ); + return FALSE; + } + + return TRUE; +} + + +/*********************************************************************** + * 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; +} + + +/*********************************************************************** + * GetFileSizeEx (KERNEL32.@) + */ +BOOL WINAPI GetFileSizeEx( HANDLE hFile, PLARGE_INTEGER lpFileSize ) +{ + BY_HANDLE_FILE_INFORMATION info; + + if (!lpFileSize) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (!GetFileInformationByHandle( hFile, &info )) + { + return FALSE; + } + + lpFileSize->s.LowPart = info.nFileSizeLow; + lpFileSize->s.HighPart = info.nFileSizeHigh; + + return TRUE; +} + + +/************************************************************************** + * LockFile (KERNEL32.@) + */ +BOOL WINAPI LockFile( HANDLE hFile, DWORD offset_low, DWORD offset_high, + DWORD count_low, DWORD count_high ) +{ + NTSTATUS status; + LARGE_INTEGER count, offset; + + TRACE( "%p %lx%08lx %lx%08lx\n", + hFile, offset_high, offset_low, count_high, count_low ); + + count.s.LowPart = count_low; + count.s.HighPart = count_high; + offset.s.LowPart = offset_low; + offset.s.HighPart = offset_high; + + status = NtLockFile( hFile, 0, NULL, NULL, + NULL, &offset, &count, NULL, TRUE, TRUE ); + + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + return !status; +} + + +/************************************************************************** + * LockFileEx [KERNEL32.@] + * + * Locks a byte range within an open file for shared or exclusive access. + * + * RETURNS + * success: TRUE + * failure: FALSE + * + * NOTES + * Per Microsoft docs, the third parameter (reserved) must be set to 0. + */ +BOOL WINAPI LockFileEx( HANDLE hFile, DWORD flags, DWORD reserved, + DWORD count_low, DWORD count_high, LPOVERLAPPED overlapped ) +{ + NTSTATUS status; + LARGE_INTEGER count, offset; + + if (reserved) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + TRACE( "%p %lx%08lx %lx%08lx flags %lx\n", + hFile, overlapped->OffsetHigh, overlapped->Offset, + count_high, count_low, flags ); + + count.s.LowPart = count_low; + count.s.HighPart = count_high; + offset.s.LowPart = overlapped->Offset; + offset.s.HighPart = overlapped->OffsetHigh; + + status = NtLockFile( hFile, overlapped->hEvent, NULL, NULL, + NULL, &offset, &count, NULL, + flags & LOCKFILE_FAIL_IMMEDIATELY, + flags & LOCKFILE_EXCLUSIVE_LOCK ); + + if (status) SetLastError( RtlNtStatusToDosError(status) ); + return !status; +} + + +/************************************************************************** + * UnlockFile (KERNEL32.@) + */ +BOOL WINAPI UnlockFile( HANDLE hFile, DWORD offset_low, DWORD offset_high, + DWORD count_low, DWORD count_high ) +{ + NTSTATUS status; + LARGE_INTEGER count, offset; + + count.s.LowPart = count_low; + count.s.HighPart = count_high; + offset.s.LowPart = offset_low; + offset.s.HighPart = offset_high; + + status = NtUnlockFile( hFile, NULL, &offset, &count, NULL); + if (status) SetLastError( RtlNtStatusToDosError(status) ); + return !status; +} + + +/************************************************************************** + * UnlockFileEx (KERNEL32.@) + */ +BOOL WINAPI UnlockFileEx( HANDLE hFile, DWORD reserved, DWORD count_low, DWORD count_high, + LPOVERLAPPED overlapped ) +{ + if (reserved) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + if (overlapped->hEvent) FIXME("Unimplemented overlapped operation\n"); + + return UnlockFile( hFile, overlapped->Offset, overlapped->OffsetHigh, count_low, count_high ); +} + +/************************************************************************** + * Operations on file names * + **************************************************************************/ + +/************************************************************************** + * ReplaceFileW (KERNEL32.@) + * ReplaceFile (KERNEL32.@) + */ +BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName,LPCWSTR lpReplacementFileName, + LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, + LPVOID lpExclude, LPVOID lpReserved) +{ + FIXME("(%s,%s,%s,%08lx,%p,%p) stub\n",debugstr_w(lpReplacedFileName),debugstr_w(lpReplacementFileName), + debugstr_w(lpBackupFileName),dwReplaceFlags,lpExclude,lpReserved); + SetLastError(ERROR_UNABLE_TO_MOVE_REPLACEMENT); + return FALSE; +} + + +/************************************************************************** + * ReplaceFileA (KERNEL32.@) + */ +BOOL WINAPI ReplaceFileA(LPCSTR lpReplacedFileName,LPCSTR lpReplacementFileName, + LPCSTR lpBackupFileName, DWORD dwReplaceFlags, + LPVOID lpExclude, LPVOID lpReserved) +{ + FIXME("(%s,%s,%s,%08lx,%p,%p) stub\n",lpReplacedFileName,lpReplacementFileName, + lpBackupFileName,dwReplaceFlags,lpExclude,lpReserved); + SetLastError(ERROR_UNABLE_TO_MOVE_REPLACEMENT); + return FALSE; +} diff --git a/dlls/kernel/file16.c b/dlls/kernel/file16.c new file mode 100644 index 00000000000..d74a1271570 --- /dev/null +++ b/dlls/kernel/file16.c @@ -0,0 +1,220 @@ +/* + * File handling functions + * + * Copyright 1993 John Burton + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * TODO: + * Fix the CopyFileEx methods to implement the "extended" functionality. + * Right now, they simply call the CopyFile method. + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "wine/winbase16.h" +#include "wine/server.h" + +#include "msdos.h" +#include "kernel_private.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(file); + +/*********************************************************************** + * _hread16 (KERNEL.349) + */ +LONG WINAPI _hread16( HFILE16 hFile, LPVOID buffer, LONG count) +{ + return _lread( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count ); +} + + +/*********************************************************************** + * _hwrite (KERNEL.350) + */ +LONG WINAPI _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count ) +{ + return _hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count ); +} + + +/*********************************************************************** + * _lcreat (KERNEL.83) + */ +HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr ) +{ + return Win32HandleToDosFileHandle( (HANDLE)_lcreat( path, attr ) ); +} + +/*********************************************************************** + * _llseek (KERNEL.84) + * + * FIXME: + * Seeking before the start of the file should be allowed for _llseek16, + * but cause subsequent I/O operations to fail (cf. interrupt list) + * + */ +LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin ) +{ + return SetFilePointer( DosFileHandleToWin32Handle(hFile), lOffset, NULL, nOrigin ); +} + + +/*********************************************************************** + * _lopen (KERNEL.85) + */ +HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode ) +{ + return Win32HandleToDosFileHandle( (HANDLE)_lopen( path, mode ) ); +} + + +/*********************************************************************** + * _lread16 (KERNEL.82) + */ +UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count ) +{ + return (UINT16)_lread((HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count ); +} + + +/*********************************************************************** + * _lwrite (KERNEL.86) + */ +UINT16 WINAPI _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count ) +{ + return (UINT16)_hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count ); +} + +/*********************************************************************** + * _hread (KERNEL.349) + */ +LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count ) +{ + LONG maxlen; + + TRACE("%d %08lx %ld\n", hFile, (DWORD)buffer, count ); + + /* Some programs pass a count larger than the allocated buffer */ + maxlen = GetSelectorLimit16( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1; + if (count > maxlen) count = maxlen; + return _lread((HFILE)DosFileHandleToWin32Handle(hFile), MapSL(buffer), count ); +} + + +/*********************************************************************** + * _lread (KERNEL.82) + */ +UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count ) +{ + return (UINT16)WIN16_hread( hFile, buffer, (LONG)count ); +} + + +/*********************************************************************** + * DeleteFile (KERNEL.146) + */ +BOOL16 WINAPI DeleteFile16( LPCSTR path ) +{ + return DeleteFileA( path ); +} + +/************************************************************************** + * GetFileAttributes (KERNEL.420) + */ +DWORD WINAPI GetFileAttributes16( LPCSTR name ) +{ + return GetFileAttributesA( name ); +} + + +/*********************************************************************** + * GetTempFileName (KERNEL.97) + */ +UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique, + LPSTR buffer ) +{ + char temppath[MAX_PATH]; + char *prefix16 = NULL; + UINT16 ret; + + if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */ + { + GetCurrentDirectoryA(sizeof(temppath), temppath); + drive |= temppath[0]; + } + + if (drive & TF_FORCEDRIVE) + { + char d[3]; + + d[0] = drive & ~TF_FORCEDRIVE; + d[1] = ':'; + d[2] = '\0'; + if (GetDriveTypeA(d) == DRIVE_NO_ROOT_DIR) + { + drive &= ~TF_FORCEDRIVE; + WARN("invalid drive %d specified\n", drive ); + } + } + + if (drive & TF_FORCEDRIVE) + sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE ); + else + GetTempPathA( MAX_PATH, temppath ); + + if (prefix) + { + prefix16 = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + 2); + *prefix16 = '~'; + strcpy(prefix16 + 1, prefix); + } + + ret = GetTempFileNameA( temppath, prefix16, unique, buffer ); + + if (prefix16) HeapFree(GetProcessHeap(), 0, prefix16); + return ret; +} + +/************************************************************************** + * SetFileAttributes (KERNEL.421) + */ +BOOL16 WINAPI SetFileAttributes16( LPCSTR lpFileName, DWORD attributes ) +{ + return SetFileAttributesA( lpFileName, attributes ); +} + + +/*********************************************************************** + * SetHandleCount (KERNEL.199) + */ +UINT16 WINAPI SetHandleCount16( UINT16 count ) +{ + return SetHandleCount( count ); +} diff --git a/dlls/kernel/kernel_private.h b/dlls/kernel/kernel_private.h index fa3b99c287e..2662e2eccf0 100644 --- a/dlls/kernel/kernel_private.h +++ b/dlls/kernel/kernel_private.h @@ -44,4 +44,9 @@ static inline HANDLE console_handle_unmap(HANDLE h) return h != INVALID_HANDLE_VALUE ? (HANDLE)((DWORD)h ^ 3) : INVALID_HANDLE_VALUE; } +/* Size of per-process table of DOS handles */ +#define DOS_TABLE_SIZE 256 +extern HANDLE dos_handles[DOS_TABLE_SIZE]; +void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing ); + #endif diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index c985413f96e..2c02a339d90 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -345,32 +345,161 @@ NTSTATUS WINAPI NtSetVolumeInformationFile( * NtQueryInformationFile [NTDLL.@] * ZwQueryInformationFile [NTDLL.@] */ -NTSTATUS WINAPI NtQueryInformationFile( - HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass) +NTSTATUS WINAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io_status, + PVOID ptr, LONG len, + FILE_INFORMATION_CLASS class) { - FIXME("(%p,%p,%p,0x%08lx,0x%08x),stub!\n", - FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass); - return 0; + NTSTATUS status; + LONG used = 0; + BYTE answer[256]; + time_t ct = 0, wt = 0, at = 0; + + TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io_status, ptr, len, class); + + switch (class) + { + case FileBasicInformation: + { + FILE_BASIC_INFORMATION* fbi = (FILE_BASIC_INFORMATION*)answer; + if (sizeof(answer) < sizeof(*fbi)) goto too_small; + + SERVER_START_REQ( get_file_info ) + { + req->handle = hFile; + if (!(status = wine_server_call( req ))) + { + /* FIXME: which file types are supported ? + * Serial ports (FILE_TYPE_CHAR) are not, + * and MSDN also says that pipes are not supported. + * FILE_TYPE_REMOTE seems to be supported according to + * MSDN q234741.txt */ + if ((reply->type == FILE_TYPE_DISK) || + (reply->type == FILE_TYPE_REMOTE)) + { + at = reply->access_time; + wt = reply->write_time; + ct = reply->change_time; + fbi->FileAttributes = reply->attr; + used = sizeof(*fbi); + } + else status = STATUS_INVALID_HANDLE; /* FIXME ??? */ + } + } + SERVER_END_REQ; + if (used) + { + RtlSecondsSince1970ToTime(wt, &fbi->CreationTime); + RtlSecondsSince1970ToTime(wt, &fbi->LastWriteTime); + RtlSecondsSince1970ToTime(ct, &fbi->ChangeTime); + RtlSecondsSince1970ToTime(at, &fbi->LastAccessTime); + } + } + break; + case FileStandardInformation: + { + FILE_STANDARD_INFORMATION* fsi = (FILE_STANDARD_INFORMATION*)answer; + if (sizeof(answer) < sizeof(*fsi)) goto too_small; + + SERVER_START_REQ( get_file_info ) + { + req->handle = hFile; + if (!(status = wine_server_call( req ))) + { + /* FIXME: which file types are supported ? + * Serial ports (FILE_TYPE_CHAR) are not, + * and MSDN also says that pipes are not supported. + * FILE_TYPE_REMOTE seems to be supported according to + * MSDN q234741.txt */ + if ((reply->type == FILE_TYPE_DISK) || + (reply->type == FILE_TYPE_REMOTE)) + { + fsi->AllocationSize.s.HighPart = reply->alloc_high; + fsi->AllocationSize.s.LowPart = reply->alloc_low; + fsi->EndOfFile.s.HighPart = reply->size_high; + fsi->EndOfFile.s.LowPart = reply->size_low; + fsi->NumberOfLinks = reply->links; + fsi->DeletePending = FALSE; /* FIXME */ + fsi->Directory = (reply->attr & FILE_ATTRIBUTE_DIRECTORY); + used = sizeof(*fsi); + } + else status = STATUS_INVALID_HANDLE; /* FIXME ??? */ + } + } + SERVER_END_REQ; + } + break; + case FilePositionInformation: + { + FILE_POSITION_INFORMATION* fpi = (FILE_POSITION_INFORMATION*)answer; + if (sizeof(answer) < sizeof(*fpi)) goto too_small; + + SERVER_START_REQ( set_file_pointer ) + { + req->handle = hFile; + req->low = 0; + req->high = 0; + req->whence = SEEK_CUR; + if (!(status = wine_server_call( req ))) + { + fpi->CurrentByteOffset.s.HighPart = reply->new_high; + fpi->CurrentByteOffset.s.LowPart = reply->new_low; + used = sizeof(*fpi); + } + } + SERVER_END_REQ; + } + break; + default: + FIXME("Unsupported class (%d)\n", class); + return io_status->u.Status = STATUS_NOT_IMPLEMENTED; + } + if (used) memcpy(ptr, answer, min(used, len)); + io_status->u.Status = status; + io_status->Information = len; + return status; + too_small: + io_status->Information = 0; + return io_status->u.Status = STATUS_BUFFER_TOO_SMALL; } /****************************************************************************** * NtSetInformationFile [NTDLL.@] * ZwSetInformationFile [NTDLL.@] */ -NTSTATUS WINAPI NtSetInformationFile( - HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass) +NTSTATUS WINAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io_status, + PVOID ptr, ULONG len, + FILE_INFORMATION_CLASS class) { - FIXME("(%p,%p,%p,0x%08lx,0x%08x)\n", - FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass); - return 0; + NTSTATUS status = STATUS_INVALID_PARAMETER_3; + + TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io_status, ptr, len, class); + + switch (class) + { + case FilePositionInformation: + if (len >= sizeof(FILE_POSITION_INFORMATION)) + { + FILE_POSITION_INFORMATION* fpi = (FILE_POSITION_INFORMATION*)ptr; + + SERVER_START_REQ( set_file_pointer ) + { + req->handle = hFile; + req->low = fpi->CurrentByteOffset.s.LowPart; + req->high = fpi->CurrentByteOffset.s.HighPart; + req->whence = SEEK_SET; + status = wine_server_call( req ); + } + SERVER_END_REQ; + status = STATUS_SUCCESS; + } + break; + default: + FIXME("Unsupported class (%d)\n", class); + return STATUS_NOT_IMPLEMENTED; + } + io_status->u.Status = status; + io_status->Information = 0; + return status; } /****************************************************************************** @@ -487,7 +616,7 @@ NTSTATUS WINAPI NtQueryVolumeInformationFile ( case FileFsMaximumInformation: break; } - IoStatusBlock->DUMMYUNIONNAME.Status = STATUS_SUCCESS; + IoStatusBlock->u.Status = STATUS_SUCCESS; IoStatusBlock->Information = len; return STATUS_SUCCESS; } @@ -514,3 +643,103 @@ NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK* IoStatusBlock } return ret; } + +/****************************************************************** + * NtLockFile (NTDLL.@) + * + * + */ +NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event, + PIO_APC_ROUTINE apc, void* apc_user, + PIO_STATUS_BLOCK io_status, PLARGE_INTEGER offset, + PLARGE_INTEGER count, ULONG* key, BOOLEAN dont_wait, + BOOLEAN exclusive ) +{ + NTSTATUS ret; + HANDLE handle; + BOOLEAN async; + + if (apc || io_status || key) + { + FIXME("Unimplemented yet parameter\n"); + return STATUS_NOT_IMPLEMENTED; + } + + for (;;) + { + SERVER_START_REQ( lock_file ) + { + req->handle = hFile; + req->offset_low = offset->s.LowPart; + req->offset_high = offset->s.HighPart; + req->count_low = count->s.LowPart; + req->count_high = count->s.HighPart; + req->shared = !exclusive; + req->wait = !dont_wait; + ret = wine_server_call( req ); + handle = reply->handle; + async = reply->overlapped; + } + SERVER_END_REQ; + if (ret != STATUS_PENDING) + { + if (!ret && lock_granted_event) NtSetEvent(lock_granted_event, NULL); + return ret; + } + + if (async) + { + FIXME( "Async I/O lock wait not implemented, might deadlock\n" ); + if (handle) NtClose( handle ); + return STATUS_PENDING; + } + if (handle) + { + NtWaitForSingleObject( handle, FALSE, NULL ); + NtClose( handle ); + } + else + { + LARGE_INTEGER time; + + /* Unix lock conflict, sleep a bit and retry */ + time.QuadPart = 100 * (ULONGLONG)10000; + time.QuadPart = -time.QuadPart; + NtWaitForMultipleObjects( 0, NULL, FALSE, FALSE, &time ); + } + } +} + + +/****************************************************************** + * NtUnlockFile (NTDLL.@) + * + * + */ +NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status, + PLARGE_INTEGER offset, PLARGE_INTEGER count, + PULONG key ) +{ + NTSTATUS status; + + TRACE( "%p %lx%08lx %lx%08lx\n", + hFile, offset->s.HighPart, offset->s.LowPart, count->s.HighPart, count->s.LowPart ); + + if (io_status || key) + { + FIXME("Unimplemented yet parameter\n"); + return STATUS_NOT_IMPLEMENTED; + } + + SERVER_START_REQ( unlock_file ) + { + req->handle = hFile; + req->offset_low = offset->s.LowPart; + req->offset_high = offset->s.HighPart; + req->count_low = count->s.LowPart; + req->count_high = count->s.HighPart; + status = wine_server_call( req ); + } + SERVER_END_REQ; + return status; +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 1264292641a..b045d56c893 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -123,7 +123,7 @@ @ stdcall NtListenPort(ptr ptr) @ stub NtLoadDriver @ stdcall NtLoadKey(ptr ptr) -@ stub NtLockFile +@ stdcall NtLockFile(long long ptr ptr ptr ptr ptr ptr long long) @ stdcall NtLockVirtualMemory(long ptr ptr long) @ stub NtMakeTemporaryObject @ stdcall NtMapViewOfSection(long long ptr long long ptr ptr long long long) @@ -245,7 +245,7 @@ @ stub NtUnloadDriver @ stdcall NtUnloadKey(long) @ stub NtUnloadKeyEx -@ stub NtUnlockFile +@ stdcall NtUnlockFile(long ptr ptr ptr ptr) @ stdcall NtUnlockVirtualMemory(long ptr ptr long) @ stdcall NtUnmapViewOfSection(long ptr) @ stub NtVdmControl @@ -655,7 +655,7 @@ @ stdcall ZwListenPort(ptr ptr) NtListenPort @ stub ZwLoadDriver @ stdcall ZwLoadKey(ptr ptr) NtLoadKey -@ stub ZwLockFile +@ stdcall ZwLockFile(long long ptr ptr ptr ptr ptr ptr long long) NtLockFile @ stdcall ZwLockVirtualMemory(long ptr ptr long) NtLockVirtualMemory @ stub ZwMakeTemporaryObject @ stdcall ZwMapViewOfSection(long long ptr long long ptr ptr long long long) NtMapViewOfSection @@ -774,7 +774,7 @@ @ stub ZwUnloadDriver @ stdcall ZwUnloadKey(long) NtUnloadKey @ stub ZwUnloadKeyEx -@ stub ZwUnlockFile +@ stdcall ZwUnlockFile(long ptr ptr ptr ptr) NtUnlockFile @ stdcall ZwUnlockVirtualMemory(long ptr ptr long) NtUnlockVirtualMemory @ stdcall ZwUnmapViewOfSection(long ptr) NtUnmapViewOfSection @ stub ZwVdmControl diff --git a/files/file.c b/files/file.c index 0982999e2b0..e14332bf020 100644 --- a/files/file.c +++ b/files/file.c @@ -82,14 +82,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(file); #define MAP_ANON MAP_ANONYMOUS #endif -/* Size of per-process table of DOS handles */ -#define DOS_TABLE_SIZE 256 - /* Macro to derive file offset from OVERLAPPED struct */ #define OVERLAPPED_OFFSET(overlapped) ((off_t) (overlapped)->Offset + ((off_t) (overlapped)->OffsetHigh << 32)) -static HANDLE dos_handles[DOS_TABLE_SIZE]; - +HANDLE dos_handles[DOS_TABLE_SIZE]; mode_t FILE_umask; extern HANDLE WINAPI FILE_SmbOpen(LPCSTR name); @@ -172,7 +168,7 @@ static void fileio_async_cleanup ( struct async_private *ovp ) * * Convert OF_* mode into flags for CreateFile. */ -static void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing ) +void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing ) { switch(mode & 0x03) { @@ -920,15 +916,6 @@ DWORD WINAPI GetFileInformationByHandle( HANDLE hFile, } -/************************************************************************** - * GetFileAttributes (KERNEL.420) - */ -DWORD WINAPI GetFileAttributes16( LPCSTR name ) -{ - return GetFileAttributesA( name ); -} - - /************************************************************************** * GetFileAttributesW (KERNEL32.@) */ @@ -974,15 +961,6 @@ DWORD WINAPI GetFileAttributesA( LPCSTR name ) } -/************************************************************************** - * SetFileAttributes (KERNEL.421) - */ -BOOL16 WINAPI SetFileAttributes16( LPCSTR lpFileName, DWORD attributes ) -{ - return SetFileAttributesA( lpFileName, attributes ); -} - - /************************************************************************** * SetFileAttributesW (KERNEL32.@) */ @@ -1081,43 +1059,6 @@ BOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD attributes) } -/*********************************************************************** - * 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; -} - - -/*********************************************************************** - * GetFileSizeEx (KERNEL32.@) - */ -BOOL WINAPI GetFileSizeEx( HANDLE hFile, PLARGE_INTEGER lpFileSize ) -{ - BY_HANDLE_FILE_INFORMATION info; - - if (!lpFileSize) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - if (!GetFileInformationByHandle( hFile, &info )) - { - return FALSE; - } - - lpFileSize->s.LowPart = info.nFileSizeLow; - lpFileSize->s.HighPart = info.nFileSizeHigh; - - return TRUE; -} - - /*********************************************************************** * GetFileTime (KERNEL32.@) */ @@ -1133,6 +1074,7 @@ BOOL WINAPI GetFileTime( HANDLE hFile, FILETIME *lpCreationTime, return TRUE; } + /*********************************************************************** * FILE_GetTempFileName : utility for GetTempFileName */ @@ -1244,51 +1186,12 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, } -/*********************************************************************** - * GetTempFileName (KERNEL.97) - */ -UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique, - LPSTR buffer ) -{ - char temppath[MAX_PATH]; - char *prefix16 = NULL; - UINT16 ret; - - if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */ - drive |= DRIVE_GetCurrentDrive() + 'A'; - - if ((drive & TF_FORCEDRIVE) && - !DRIVE_IsValid( toupper(drive & ~TF_FORCEDRIVE) - 'A' )) - { - drive &= ~TF_FORCEDRIVE; - WARN("invalid drive %d specified\n", drive ); - } - - if (drive & TF_FORCEDRIVE) - sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE ); - else - GetTempPathA( MAX_PATH, temppath ); - - if (prefix) - { - prefix16 = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + 2); - *prefix16 = '~'; - strcpy(prefix16 + 1, prefix); - } - - ret = GetTempFileNameA( temppath, prefix16, unique, buffer ); - - if (prefix16) HeapFree(GetProcessHeap(), 0, prefix16); - return ret; -} - /*********************************************************************** * FILE_DoOpenFile * * Implementation of OpenFile16() and OpenFile32(). */ -static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode, - BOOL win32 ) +static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode, BOOL win32 ) { HFILE hFileRet; HANDLE handle; @@ -1630,15 +1533,6 @@ HFILE16 WINAPI _lclose16( HFILE16 hFile ) } -/*********************************************************************** - * _lclose (KERNEL32.@) - */ -HFILE WINAPI _lclose( HFILE hFile ) -{ - TRACE("handle %d\n", hFile ); - return CloseHandle( (HANDLE)hFile ) ? 0 : HFILE_ERROR; -} - /*********************************************************************** * GetOverlappedResult (KERNEL32.@) * @@ -2212,75 +2106,6 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, } -/*********************************************************************** - * _hread (KERNEL.349) - */ -LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count ) -{ - LONG maxlen; - - TRACE("%d %08lx %ld\n", - hFile, (DWORD)buffer, count ); - - /* Some programs pass a count larger than the allocated buffer */ - maxlen = GetSelectorLimit16( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1; - if (count > maxlen) count = maxlen; - return _lread((HFILE)DosFileHandleToWin32Handle(hFile), MapSL(buffer), count ); -} - - -/*********************************************************************** - * _lread (KERNEL.82) - */ -UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count ) -{ - return (UINT16)WIN16_hread( hFile, buffer, (LONG)count ); -} - - -/*********************************************************************** - * _lread (KERNEL32.@) - */ -UINT WINAPI _lread( HFILE handle, LPVOID buffer, UINT count ) -{ - DWORD result; - if (!ReadFile( (HANDLE)handle, buffer, count, &result, NULL )) return -1; - return result; -} - - -/*********************************************************************** - * _lread16 (KERNEL.82) - */ -UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count ) -{ - return (UINT16)_lread((HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count ); -} - - -/*********************************************************************** - * _lcreat (KERNEL.83) - */ -HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr ) -{ - return Win32HandleToDosFileHandle( (HANDLE)_lcreat( path, attr ) ); -} - - -/*********************************************************************** - * _lcreat (KERNEL32.@) - */ -HFILE WINAPI _lcreat( LPCSTR path, INT attr ) -{ - /* Mask off all flags not explicitly allowed by the doc */ - attr &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; - TRACE("%s %02x\n", path, attr ); - return (HFILE)CreateFileA( path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - CREATE_ALWAYS, attr, 0 ); -} - - /*********************************************************************** * SetFilePointer (KERNEL32.@) */ @@ -2311,132 +2136,6 @@ DWORD WINAPI SetFilePointer( HANDLE hFile, LONG distance, LONG *highword, } -/*********************************************************************** - * _llseek (KERNEL.84) - * - * FIXME: - * Seeking before the start of the file should be allowed for _llseek16, - * but cause subsequent I/O operations to fail (cf. interrupt list) - * - */ -LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin ) -{ - return SetFilePointer( DosFileHandleToWin32Handle(hFile), lOffset, NULL, nOrigin ); -} - - -/*********************************************************************** - * _llseek (KERNEL32.@) - */ -LONG WINAPI _llseek( HFILE hFile, LONG lOffset, INT nOrigin ) -{ - return SetFilePointer( (HANDLE)hFile, lOffset, NULL, nOrigin ); -} - - -/*********************************************************************** - * _lopen (KERNEL.85) - */ -HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode ) -{ - return Win32HandleToDosFileHandle( (HANDLE)_lopen( path, mode ) ); -} - - -/*********************************************************************** - * _lopen (KERNEL32.@) - */ -HFILE WINAPI _lopen( LPCSTR path, INT mode ) -{ - DWORD access, sharing; - - TRACE("('%s',%04x)\n", path, mode ); - FILE_ConvertOFMode( mode, &access, &sharing ); - return (HFILE)CreateFileA( path, access, sharing, NULL, OPEN_EXISTING, 0, 0 ); -} - - -/*********************************************************************** - * _lwrite (KERNEL.86) - */ -UINT16 WINAPI _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count ) -{ - return (UINT16)_hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count ); -} - -/*********************************************************************** - * _lwrite (KERNEL32.@) - */ -UINT WINAPI _lwrite( HFILE hFile, LPCSTR buffer, UINT count ) -{ - return (UINT)_hwrite( hFile, buffer, (LONG)count ); -} - - -/*********************************************************************** - * _hread16 (KERNEL.349) - */ -LONG WINAPI _hread16( HFILE16 hFile, LPVOID buffer, LONG count) -{ - return _lread( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count ); -} - - -/*********************************************************************** - * _hread (KERNEL32.@) - */ -LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count) -{ - return _lread( hFile, buffer, count ); -} - - -/*********************************************************************** - * _hwrite (KERNEL.350) - */ -LONG WINAPI _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count ) -{ - return _hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count ); -} - - -/*********************************************************************** - * _hwrite (KERNEL32.@) - * - * experimentation yields that _lwrite: - * o truncates the file at the current position with - * a 0 len write - * o returns 0 on a 0 length write - * o works with console handles - * - */ -LONG WINAPI _hwrite( HFILE handle, LPCSTR buffer, LONG count ) -{ - DWORD result; - - TRACE("%d %p %ld\n", handle, buffer, count ); - - if (!count) - { - /* Expand or truncate at current position */ - if (!SetEndOfFile( (HANDLE)handle )) return HFILE_ERROR; - return 0; - } - if (!WriteFile( (HANDLE)handle, buffer, count, &result, NULL )) - return HFILE_ERROR; - return result; -} - - -/*********************************************************************** - * SetHandleCount (KERNEL.199) - */ -UINT16 WINAPI SetHandleCount16( UINT16 count ) -{ - return SetHandleCount( count ); -} - - /************************************************************************* * SetHandleCount (KERNEL32.@) */ @@ -2446,32 +2145,6 @@ UINT WINAPI SetHandleCount( UINT count ) } -/*********************************************************************** - * FlushFileBuffers (KERNEL32.@) - */ -BOOL WINAPI FlushFileBuffers( HANDLE hFile ) -{ - NTSTATUS nts; - IO_STATUS_BLOCK ioblk; - - if (is_console_handle( hFile )) - { - /* this will fail (as expected) for an output handle */ - /* FIXME: wait until FlushFileBuffers is moved to dll/kernel */ - /* return FlushConsoleInputBuffer( hFile ); */ - return TRUE; - } - nts = NtFlushBuffersFile( hFile, &ioblk ); - if (nts != STATUS_SUCCESS) - { - SetLastError( RtlNtStatusToDosError( nts ) ); - return FALSE; - } - - return TRUE; -} - - /************************************************************************** * SetEndOfFile (KERNEL32.@) */ @@ -2488,15 +2161,6 @@ BOOL WINAPI SetEndOfFile( HANDLE hFile ) } -/*********************************************************************** - * DeleteFile (KERNEL.146) - */ -BOOL16 WINAPI DeleteFile16( LPCSTR path ) -{ - return DeleteFileA( path ); -} - - /*********************************************************************** * DeleteFileW (KERNEL32.@) */ @@ -3041,6 +2705,7 @@ BOOL WINAPI CopyFileExW(LPCWSTR sourceFilename, LPCWSTR destFilename, return CopyFileW(sourceFilename, destFilename, (copyFlags & COPY_FILE_FAIL_IF_EXISTS) != 0); } + /************************************************************************** * CopyFileExA (KERNEL32.@) */ @@ -3096,136 +2761,6 @@ BOOL WINAPI SetFileTime( HANDLE hFile, } -/************************************************************************** - * LockFile (KERNEL32.@) - */ -BOOL WINAPI LockFile( HANDLE hFile, DWORD offset_low, DWORD offset_high, - DWORD count_low, DWORD count_high ) -{ - BOOL ret; - - TRACE( "%p %lx%08lx %lx%08lx\n", hFile, offset_high, offset_low, count_high, count_low ); - - SERVER_START_REQ( lock_file ) - { - req->handle = hFile; - req->offset_low = offset_low; - req->offset_high = offset_high; - req->count_low = count_low; - req->count_high = count_high; - req->shared = FALSE; - req->wait = FALSE; - ret = !wine_server_call_err( req ); - } - SERVER_END_REQ; - return ret; -} - -/************************************************************************** - * LockFileEx [KERNEL32.@] - * - * Locks a byte range within an open file for shared or exclusive access. - * - * RETURNS - * success: TRUE - * failure: FALSE - * - * NOTES - * Per Microsoft docs, the third parameter (reserved) must be set to 0. - */ -BOOL WINAPI LockFileEx( HANDLE hFile, DWORD flags, DWORD reserved, - DWORD count_low, DWORD count_high, LPOVERLAPPED overlapped ) -{ - NTSTATUS err; - BOOL async; - HANDLE handle; - - if (reserved) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - TRACE( "%p %lx%08lx %lx%08lx flags %lx\n", - hFile, overlapped->OffsetHigh, overlapped->Offset, count_high, count_low, flags ); - - for (;;) - { - SERVER_START_REQ( lock_file ) - { - req->handle = hFile; - req->offset_low = overlapped->Offset; - req->offset_high = overlapped->OffsetHigh; - req->count_low = count_low; - req->count_high = count_high; - req->shared = !(flags & LOCKFILE_EXCLUSIVE_LOCK); - req->wait = !(flags & LOCKFILE_FAIL_IMMEDIATELY); - err = wine_server_call( req ); - handle = reply->handle; - async = reply->overlapped; - } - SERVER_END_REQ; - if (err != STATUS_PENDING) - { - if (err) SetLastError( RtlNtStatusToDosError(err) ); - return !err; - } - if (async) - { - FIXME( "Async I/O lock wait not implemented, might deadlock\n" ); - if (handle) CloseHandle( handle ); - SetLastError( ERROR_IO_PENDING ); - return FALSE; - } - if (handle) - { - WaitForSingleObject( handle, INFINITE ); - CloseHandle( handle ); - } - else Sleep(100); /* Unix lock conflict, sleep a bit and retry */ - } -} - - -/************************************************************************** - * UnlockFile (KERNEL32.@) - */ -BOOL WINAPI UnlockFile( HANDLE hFile, DWORD offset_low, DWORD offset_high, - DWORD count_low, DWORD count_high ) -{ - BOOL ret; - - TRACE( "%p %lx%08lx %lx%08lx\n", hFile, offset_high, offset_low, count_high, count_low ); - - SERVER_START_REQ( unlock_file ) - { - req->handle = hFile; - req->offset_low = offset_low; - req->offset_high = offset_high; - req->count_low = count_low; - req->count_high = count_high; - ret = !wine_server_call_err( req ); - } - SERVER_END_REQ; - return ret; -} - - -/************************************************************************** - * UnlockFileEx (KERNEL32.@) - */ -BOOL WINAPI UnlockFileEx( HANDLE hFile, DWORD reserved, DWORD count_low, DWORD count_high, - LPOVERLAPPED overlapped ) -{ - if (reserved) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - return UnlockFile( hFile, overlapped->Offset, overlapped->OffsetHigh, count_low, count_high ); -} - - /************************************************************************** * GetFileAttributesExW (KERNEL32.@) */ @@ -3289,30 +2824,3 @@ BOOL WINAPI GetFileAttributesExA( SetLastError(ERROR_NOT_ENOUGH_MEMORY); return ret; } - -/************************************************************************** - * ReplaceFileW (KERNEL32.@) - * ReplaceFile (KERNEL32.@) - */ -BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName,LPCWSTR lpReplacementFileName, - LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, - LPVOID lpExclude, LPVOID lpReserved) -{ - FIXME("(%s,%s,%s,%08lx,%p,%p) stub\n",debugstr_w(lpReplacedFileName),debugstr_w(lpReplacementFileName), - debugstr_w(lpBackupFileName),dwReplaceFlags,lpExclude,lpReserved); - SetLastError(ERROR_UNABLE_TO_MOVE_REPLACEMENT); - return FALSE; -} - -/************************************************************************** - * ReplaceFileA (KERNEL32.@) - */ -BOOL WINAPI ReplaceFileA(LPCSTR lpReplacedFileName,LPCSTR lpReplacementFileName, - LPCSTR lpBackupFileName, DWORD dwReplaceFlags, - LPVOID lpExclude, LPVOID lpReserved) -{ - FIXME("(%s,%s,%s,%08lx,%p,%p) stub\n",lpReplacedFileName,lpReplacementFileName, - lpBackupFileName,dwReplaceFlags,lpExclude,lpReserved); - SetLastError(ERROR_UNABLE_TO_MOVE_REPLACEMENT); - return FALSE; -} diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index b0f664aec71..b2ccd2bfb2a 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -892,8 +892,11 @@ struct get_file_info_reply int attr; time_t access_time; time_t write_time; + time_t change_time; int size_high; int size_low; + int alloc_high; + int alloc_low; int links; int index_high; int index_low; @@ -3615,6 +3618,6 @@ union generic_reply struct set_clipboard_info_reply set_clipboard_info_reply; }; -#define SERVER_PROTOCOL_VERSION 112 +#define SERVER_PROTOCOL_VERSION 113 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/winternl.h b/include/winternl.h index 126e505966d..446b4203cb8 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -936,6 +936,7 @@ NTSTATUS WINAPI NtFlushVirtualMemory(HANDLE,LPCVOID*,ULONG*,ULONG); NTSTATUS WINAPI NtFreeVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG); NTSTATUS WINAPI NtGetContextThread(HANDLE,CONTEXT*); NTSTATUS WINAPI NtLoadKey(const OBJECT_ATTRIBUTES *,const OBJECT_ATTRIBUTES *); +NTSTATUS WINAPI NtLockFile(HANDLE,HANDLE,PIO_APC_ROUTINE,void*,PIO_STATUS_BLOCK,PLARGE_INTEGER,PLARGE_INTEGER,ULONG*,BOOLEAN,BOOLEAN); NTSTATUS WINAPI NtLockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG); NTSTATUS WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,ULONG,const LARGE_INTEGER*,ULONG*,SECTION_INHERIT,ULONG,ULONG); NTSTATUS WINAPI NtNotifyChangeKey(HKEY,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN); @@ -951,6 +952,7 @@ NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG,ULONG*); NTSTATUS WINAPI NtPulseEvent(HANDLE,PULONG); NTSTATUS WINAPI NtQueueApcThread(HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR); NTSTATUS WINAPI NtQueryDefaultLocale(BOOLEAN,LCID*); +NTSTATUS WINAPI NtQueryInformationFile(HANDLE,PIO_STATUS_BLOCK,PVOID,LONG,FILE_INFORMATION_CLASS); NTSTATUS WINAPI NtQueryInformationProcess(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG); NTSTATUS WINAPI NtQueryInformationThread(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG); NTSTATUS WINAPI NtQueryInformationToken(HANDLE,DWORD,LPVOID,DWORD,LPDWORD); @@ -973,6 +975,7 @@ NTSTATUS WINAPI NtSaveKey(HKEY,HANDLE); NTSTATUS WINAPI NtSetContextThread(HANDLE,const CONTEXT*); NTSTATUS WINAPI NtSetDefaultLocale(BOOLEAN,LCID); NTSTATUS WINAPI NtSetEvent(HANDLE,PULONG); +NTSTATUS WINAPI NtSetInformationFile(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FILE_INFORMATION_CLASS); NTSTATUS WINAPI NtSetInformationKey(HKEY,const int,PVOID,ULONG); NTSTATUS WINAPI NtSetInformationObject(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG); NTSTATUS WINAPI NtSetSecurityObject(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR); @@ -983,6 +986,7 @@ NTSTATUS WINAPI NtSuspendThread(HANDLE,PULONG); NTSTATUS WINAPI NtTerminateProcess(HANDLE,LONG); NTSTATUS WINAPI NtTerminateThread(HANDLE,LONG); NTSTATUS WINAPI NtUnloadKey(HKEY); +NTSTATUS WINAPI NtUnlockFile(HANDLE,PIO_STATUS_BLOCK,PLARGE_INTEGER,PLARGE_INTEGER,PULONG); NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG); NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID); NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,PLARGE_INTEGER); diff --git a/misc/registry.c b/misc/registry.c index 85b57572a08..21ed173cd24 100644 --- a/misc/registry.c +++ b/misc/registry.c @@ -313,7 +313,7 @@ struct _w31_valent { }; /* recursive helper function to display a directory tree [Internal] */ -void _w31_dumptree(unsigned short idx,unsigned char *txt,struct _w31_tabent *tab,struct _w31_header *head,HKEY hkey,time_t lastmodified, int level) +static void _w31_dumptree(unsigned short idx,unsigned char *txt,struct _w31_tabent *tab,struct _w31_header *head,HKEY hkey,time_t lastmodified, int level) { static const WCHAR classesW[] = {'.','c','l','a','s','s','e','s',0}; struct _w31_dirent *dir; @@ -379,9 +379,9 @@ void _w31_dumptree(unsigned short idx,unsigned char *txt,struct _w31_tabent *tab /****************************************************************************** * _w31_loadreg [Internal] */ -void _w31_loadreg(void) +static void _w31_loadreg(void) { - HFILE hf; + HANDLE hf; HKEY root; OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW; @@ -392,56 +392,57 @@ void _w31_loadreg(void) OFSTRUCT ofs; BY_HANDLE_FILE_INFORMATION hfinfo; time_t lastmodified; + DWORD r; TRACE("(void)\n"); - hf = OpenFile("reg.dat",&ofs,OF_READ); - if (hf==HFILE_ERROR) return; + hf = (HANDLE)OpenFile("reg.dat",&ofs,OF_READ); + if (hf==(HANDLE)HFILE_ERROR) return; /* read & dump header */ - if (sizeof(head)!=_lread(hf,&head,sizeof(head))) { + if (!ReadFile(hf,&head,sizeof(head),&r,NULL) || r!=sizeof(head)) { ERR("reg.dat is too short.\n"); - _lclose(hf); + CloseHandle(hf); return; } if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) { ERR("reg.dat has bad signature.\n"); - _lclose(hf); + CloseHandle(hf); return; } len = head.tabcnt * sizeof(struct _w31_tabent); /* read and dump index table */ tab = _xmalloc(len); - if (len!=_lread(hf,tab,len)) { + if (!ReadFile(hf,tab,len,&r,NULL) || r!=len) { ERR("couldn't read %d bytes.\n",len); free(tab); - _lclose(hf); + CloseHandle(hf); return; } /* read text */ txt = _xmalloc(head.textsize); - if (-1==_llseek(hf,head.textoff,SEEK_SET)) { + if (-1==SetFilePointer(hf,head.textoff,NULL,SEEK_SET)) { ERR("couldn't seek to textblock.\n"); free(tab); free(txt); - _lclose(hf); + CloseHandle(hf); return; } - if (head.textsize!=_lread(hf,txt,head.textsize)) { + if (!ReadFile(hf,txt,head.textsize,&r,NULL) || r!=head.textsize) { ERR("textblock too short (%d instead of %ld).\n",len,head.textsize); free(tab); free(txt); - _lclose(hf); + CloseHandle(hf); return; } - if (!GetFileInformationByHandle((HANDLE)hf,&hfinfo)) { + if (!GetFileInformationByHandle(hf,&hfinfo)) { ERR("GetFileInformationByHandle failed?.\n"); free(tab); free(txt); - _lclose(hf); + CloseHandle(hf); return; } lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL); @@ -461,7 +462,7 @@ void _w31_loadreg(void) } free(tab); free(txt); - _lclose(hf); + CloseHandle(hf); return; } diff --git a/server/file.c b/server/file.c index 0ed7ae50698..96d525040c4 100644 --- a/server/file.c +++ b/server/file.c @@ -329,15 +329,22 @@ static int file_get_info( struct fd *fd, struct get_file_info_reply *reply, int if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY; reply->access_time = st.st_atime; reply->write_time = st.st_mtime; + reply->change_time = st.st_ctime; if (S_ISDIR(st.st_mode)) { - reply->size_high = 0; - reply->size_low = 0; + reply->size_high = 0; + reply->size_low = 0; + reply->alloc_high = 0; + reply->alloc_low = 0; } else { - reply->size_high = st.st_size >> 32; - reply->size_low = st.st_size & 0xffffffff; + file_pos_t alloc; + reply->size_high = st.st_size >> 32; + reply->size_low = st.st_size & 0xffffffff; + alloc = (file_pos_t)st.st_blksize * st.st_blocks; + reply->alloc_high = alloc >> 32; + reply->alloc_low = alloc & 0xffffffff; } reply->links = st.st_nlink; reply->index_high = st.st_dev; diff --git a/server/protocol.def b/server/protocol.def index bb3e37a89ee..60c6399bc88 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -677,8 +677,11 @@ enum fd_type int attr; /* file attributes */ time_t access_time; /* last access time */ time_t write_time; /* last write time */ + time_t change_time; /* last change time */ int size_high; /* file size */ int size_low; /* file size */ + int alloc_high; /* size used on disk */ + int alloc_low; /* size used on disk */ int links; /* number of links */ int index_high; /* unique index */ int index_low; /* unique index */ diff --git a/server/trace.c b/server/trace.c index 2067695ca20..e68dafe409d 100644 --- a/server/trace.c +++ b/server/trace.c @@ -893,8 +893,11 @@ static void dump_get_file_info_reply( const struct get_file_info_reply *req ) fprintf( stderr, " attr=%d,", req->attr ); fprintf( stderr, " access_time=%ld,", req->access_time ); fprintf( stderr, " write_time=%ld,", req->write_time ); + fprintf( stderr, " change_time=%ld,", req->change_time ); fprintf( stderr, " size_high=%d,", req->size_high ); fprintf( stderr, " size_low=%d,", req->size_low ); + fprintf( stderr, " alloc_high=%d,", req->alloc_high ); + fprintf( stderr, " alloc_low=%d,", req->alloc_low ); fprintf( stderr, " links=%d,", req->links ); fprintf( stderr, " index_high=%d,", req->index_high ); fprintf( stderr, " index_low=%d,", req->index_low );