Reimplemented GetFileAttributesW, SetFileAttributesW and SetFileTime
using the corresponding ntdll functionality.
This commit is contained in:
parent
ebf0eb3138
commit
174e2a6464
|
@ -367,6 +367,40 @@ BOOL WINAPI GetFileSizeEx( HANDLE hFile, PLARGE_INTEGER lpFileSize )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetFileTime (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetFileTime( HANDLE hFile, const FILETIME *ctime,
|
||||
const FILETIME *atime, const FILETIME *mtime )
|
||||
{
|
||||
FILE_BASIC_INFORMATION info;
|
||||
IO_STATUS_BLOCK io;
|
||||
NTSTATUS status;
|
||||
|
||||
memset( &info, 0, sizeof(info) );
|
||||
if (ctime)
|
||||
{
|
||||
info.CreationTime.u.HighPart = ctime->dwHighDateTime;
|
||||
info.CreationTime.u.LowPart = ctime->dwLowDateTime;
|
||||
}
|
||||
if (atime)
|
||||
{
|
||||
info.LastAccessTime.u.HighPart = atime->dwHighDateTime;
|
||||
info.LastAccessTime.u.LowPart = atime->dwLowDateTime;
|
||||
}
|
||||
if (mtime)
|
||||
{
|
||||
info.LastWriteTime.u.HighPart = mtime->dwHighDateTime;
|
||||
info.LastWriteTime.u.LowPart = mtime->dwLowDateTime;
|
||||
}
|
||||
|
||||
status = NtSetInformationFile( hFile, &io, &info, sizeof(info), FileBasicInformation );
|
||||
if (status == STATUS_SUCCESS) return TRUE;
|
||||
SetLastError( RtlNtStatusToDosError(status) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* LockFile (KERNEL32.@)
|
||||
*/
|
||||
|
@ -918,6 +952,135 @@ BOOL WINAPI FindNextFileA( HANDLE handle, WIN32_FIND_DATAA *data )
|
|||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* GetFileAttributesW (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetFileAttributesW( LPCWSTR name )
|
||||
{
|
||||
FILE_BASIC_INFORMATION info;
|
||||
UNICODE_STRING nt_name;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
|
||||
{
|
||||
SetLastError( ERROR_PATH_NOT_FOUND );
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.ObjectName = &nt_name;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
status = NtQueryAttributesFile( &attr, &info );
|
||||
RtlFreeUnicodeString( &nt_name );
|
||||
|
||||
if (status == STATUS_SUCCESS) return info.FileAttributes;
|
||||
|
||||
/* NtQueryAttributesFile fails on devices, but GetFileAttributesW succeeds */
|
||||
if (RtlIsDosDeviceName_U( name )) return FILE_ATTRIBUTE_ARCHIVE;
|
||||
|
||||
SetLastError( RtlNtStatusToDosError(status) );
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* GetFileAttributesA (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetFileAttributesA( LPCSTR name )
|
||||
{
|
||||
UNICODE_STRING nameW;
|
||||
DWORD ret = INVALID_FILE_ATTRIBUTES;
|
||||
|
||||
if (!name)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
if (RtlCreateUnicodeStringFromAsciiz(&nameW, name))
|
||||
{
|
||||
ret = GetFileAttributesW(nameW.Buffer);
|
||||
RtlFreeUnicodeString(&nameW);
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SetFileAttributesW (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetFileAttributesW( LPCWSTR name, DWORD attributes )
|
||||
{
|
||||
UNICODE_STRING nt_name;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
NTSTATUS status;
|
||||
HANDLE handle;
|
||||
|
||||
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
|
||||
{
|
||||
SetLastError( ERROR_PATH_NOT_FOUND );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.ObjectName = &nt_name;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
status = NtOpenFile( &handle, 0, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT );
|
||||
RtlFreeUnicodeString( &nt_name );
|
||||
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
FILE_BASIC_INFORMATION info;
|
||||
|
||||
memset( &info, 0, sizeof(info) );
|
||||
info.FileAttributes = attributes | FILE_ATTRIBUTE_NORMAL; /* make sure it's not zero */
|
||||
status = NtSetInformationFile( handle, &io, &info, sizeof(info), FileBasicInformation );
|
||||
NtClose( handle );
|
||||
}
|
||||
|
||||
if (status == STATUS_SUCCESS) return TRUE;
|
||||
SetLastError( RtlNtStatusToDosError(status) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SetFileAttributesA (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetFileAttributesA( LPCSTR name, DWORD attributes )
|
||||
{
|
||||
UNICODE_STRING filenameW;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!name)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (RtlCreateUnicodeStringFromAsciiz(&filenameW, name))
|
||||
{
|
||||
ret = SetFileAttributesW(filenameW.Buffer, attributes);
|
||||
RtlFreeUnicodeString(&filenameW);
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* OpenFile (KERNEL32.@)
|
||||
*/
|
||||
|
|
|
@ -110,10 +110,6 @@ static BOOL process_attach(void)
|
|||
{
|
||||
HMODULE16 hModule;
|
||||
|
||||
/* Get the umask */
|
||||
FILE_umask = umask(0777);
|
||||
umask( FILE_umask );
|
||||
|
||||
/* Setup registry locale information */
|
||||
LOCALE_InitRegistry();
|
||||
|
||||
|
|
|
@ -188,6 +188,29 @@ static void init_options(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DIR_is_hidden_file
|
||||
*
|
||||
* Check if the specified file should be hidden based on its name and the show dot files option.
|
||||
*/
|
||||
BOOL DIR_is_hidden_file( const UNICODE_STRING *name )
|
||||
{
|
||||
WCHAR *p, *end;
|
||||
|
||||
if (show_dir_symlinks == -1) init_options();
|
||||
if (show_dot_files) return FALSE;
|
||||
|
||||
end = p = name->Buffer + name->Length/sizeof(WCHAR);
|
||||
while (p > name->Buffer && IS_SEPARATOR(p[-1])) p--;
|
||||
while (p > name->Buffer && !IS_SEPARATOR(p[-1])) p--;
|
||||
if (p == end || *p != '.') return FALSE;
|
||||
/* make sure it isn't '.' or '..' */
|
||||
if (p + 1 == end) return FALSE;
|
||||
if (p[1] == '.' && p + 2 == end) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* hash_short_file_name
|
||||
*
|
||||
|
|
|
@ -39,6 +39,12 @@
|
|||
#ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#endif
|
||||
#ifdef STATFS_DEFINED_BY_SYS_VFS
|
||||
# include <sys/vfs.h>
|
||||
#else
|
||||
|
@ -64,6 +70,11 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||
|
||||
mode_t FILE_umask = 0;
|
||||
|
||||
#define SECSPERDAY 86400
|
||||
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
|
||||
|
||||
/**************************************************************************
|
||||
* NtOpenFile [NTDLL.@]
|
||||
* ZwOpenFile [NTDLL.@]
|
||||
|
@ -868,46 +879,143 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
|||
* Set information about an open file handle.
|
||||
*
|
||||
* PARAMS
|
||||
* FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
|
||||
* IoStatusBlock [O] Receives information about the operation on return
|
||||
* FileInformation [I] Source for file information
|
||||
* Length [I] Size of FileInformation
|
||||
* FileInformationClass [I] Type of file information to set
|
||||
* handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
|
||||
* io [O] Receives information about the operation on return
|
||||
* ptr [I] Source for file information
|
||||
* len [I] Size of FileInformation
|
||||
* class [I] Type of file information to set
|
||||
*
|
||||
* RETURNS
|
||||
* Success: 0. IoStatusBlock is updated.
|
||||
* Success: 0. io is updated.
|
||||
* Failure: An NTSTATUS error code describing the error.
|
||||
*/
|
||||
NTSTATUS WINAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io_status,
|
||||
PVOID ptr, ULONG len,
|
||||
FILE_INFORMATION_CLASS class)
|
||||
NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
||||
PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class)
|
||||
{
|
||||
NTSTATUS status = STATUS_INVALID_PARAMETER_3;
|
||||
int fd;
|
||||
|
||||
TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io_status, ptr, len, class);
|
||||
TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", handle, io, ptr, len, class);
|
||||
|
||||
if ((io->u.Status = wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL )))
|
||||
return io->u.Status;
|
||||
|
||||
io->u.Status = STATUS_SUCCESS;
|
||||
switch (class)
|
||||
{
|
||||
case FileBasicInformation:
|
||||
if (len >= sizeof(FILE_BASIC_INFORMATION))
|
||||
{
|
||||
struct stat st;
|
||||
const FILE_BASIC_INFORMATION *info = ptr;
|
||||
|
||||
#ifdef HAVE_FUTIMES
|
||||
if (info->LastAccessTime.QuadPart || info->LastWriteTime.QuadPart)
|
||||
{
|
||||
ULONGLONG sec, nsec;
|
||||
struct timeval tv[2];
|
||||
|
||||
if (!info->LastAccessTime.QuadPart || !info->LastWriteTime.QuadPart)
|
||||
{
|
||||
|
||||
tv[0].tv_sec = tv[0].tv_usec = 0;
|
||||
tv[1].tv_sec = tv[1].tv_usec = 0;
|
||||
if (!fstat( fd, &st ))
|
||||
{
|
||||
tv[0].tv_sec = st.st_atime;
|
||||
tv[1].tv_sec = st.st_mtime;
|
||||
}
|
||||
}
|
||||
if (info->LastAccessTime.QuadPart)
|
||||
{
|
||||
sec = RtlLargeIntegerDivide( info->LastAccessTime.QuadPart, 10000000, &nsec );
|
||||
tv[0].tv_sec = sec - SECS_1601_TO_1970;
|
||||
tv[0].tv_usec = (UINT)nsec / 10;
|
||||
}
|
||||
if (info->LastWriteTime.QuadPart)
|
||||
{
|
||||
sec = RtlLargeIntegerDivide( info->LastWriteTime.QuadPart, 10000000, &nsec );
|
||||
tv[1].tv_sec = sec - SECS_1601_TO_1970;
|
||||
tv[1].tv_usec = (UINT)nsec / 10;
|
||||
}
|
||||
if (futimes( fd, tv ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
}
|
||||
#endif /* HAVE_FUTIMES */
|
||||
if (io->u.Status == STATUS_SUCCESS && info->FileAttributes)
|
||||
{
|
||||
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
else
|
||||
{
|
||||
if (info->FileAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
{
|
||||
st.st_mode &= ~0222; /* clear write permission bits */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add write permission only where we already have read permission */
|
||||
st.st_mode |= (0600 | ((st.st_mode & 044) >> 1)) & (~FILE_umask);
|
||||
}
|
||||
if (fchmod( fd, st.st_mode ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
break;
|
||||
|
||||
case FilePositionInformation:
|
||||
if (len >= sizeof(FILE_POSITION_INFORMATION))
|
||||
{
|
||||
int fd;
|
||||
FILE_POSITION_INFORMATION* fpi = (FILE_POSITION_INFORMATION*)ptr;
|
||||
const FILE_POSITION_INFORMATION *info = ptr;
|
||||
|
||||
if (!(status = wine_server_handle_to_fd( hFile, 0, &fd, NULL, NULL )))
|
||||
{
|
||||
if (lseek( fd, fpi->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1)
|
||||
status = FILE_GetNtStatus();
|
||||
wine_server_release_fd( hFile, fd );
|
||||
}
|
||||
if (lseek( fd, info->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1)
|
||||
io->u.Status = FILE_GetNtStatus();
|
||||
}
|
||||
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
break;
|
||||
|
||||
default:
|
||||
FIXME("Unsupported class (%d)\n", class);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
io->u.Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
io_status->u.Status = status;
|
||||
io_status->Information = 0;
|
||||
wine_server_release_fd( handle, fd );
|
||||
io->Information = 0;
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtQueryAttributesFile (NTDLL.@)
|
||||
* ZwQueryAttributesFile (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info )
|
||||
{
|
||||
ANSI_STRING unix_name;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!(status = DIR_nt_to_unix( attr->ObjectName, &unix_name,
|
||||
TRUE, !(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat( unix_name.Buffer, &st ) == -1)
|
||||
status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
status = STATUS_INVALID_INFO_CLASS;
|
||||
else
|
||||
{
|
||||
if (S_ISDIR(st.st_mode)) info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
||||
else info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||
if (!(st.st_mode & S_IWUSR)) info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
|
||||
RtlSecondsSince1970ToTime( st.st_mtime, &info->CreationTime );
|
||||
RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime );
|
||||
RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime );
|
||||
RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime );
|
||||
if (DIR_is_hidden_file( attr->ObjectName ))
|
||||
info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
}
|
||||
else WARN("%s not found (%lx)\n", debugstr_us(attr->ObjectName), status );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -2016,10 +2016,15 @@ void __wine_process_init( int argc, char *argv[] )
|
|||
ANSI_STRING func_name;
|
||||
void (* DECLSPEC_NORETURN init_func)();
|
||||
extern void __wine_dbg_ntdll_init(void);
|
||||
extern mode_t FILE_umask;
|
||||
|
||||
thread_init();
|
||||
__wine_dbg_ntdll_init(); /* hack: register debug channels early */
|
||||
|
||||
/* retrieve current umask */
|
||||
FILE_umask = umask(0777);
|
||||
umask( FILE_umask );
|
||||
|
||||
/* setup the load callback and create ntdll modref */
|
||||
wine_dll_set_callback( load_builtin_callback );
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@
|
|||
@ stub NtPrivilegedServiceAuditAlarm
|
||||
@ stdcall NtProtectVirtualMemory(long ptr ptr long ptr)
|
||||
@ stdcall NtPulseEvent(long ptr)
|
||||
@ stub NtQueryAttributesFile
|
||||
@ stdcall NtQueryAttributesFile(ptr ptr)
|
||||
@ stdcall NtQueryDefaultLocale(long ptr)
|
||||
@ stdcall NtQueryDirectoryFile(long long ptr ptr ptr ptr long long long ptr long)
|
||||
@ stdcall NtQueryDirectoryObject(long ptr long long long ptr ptr)
|
||||
|
@ -736,7 +736,7 @@
|
|||
@ stub ZwPrivilegedServiceAuditAlarm
|
||||
@ stdcall ZwProtectVirtualMemory(long ptr ptr long ptr) NtProtectVirtualMemory
|
||||
@ stdcall ZwPulseEvent(long ptr) NtPulseEvent
|
||||
@ stub ZwQueryAttributesFile
|
||||
@ stdcall ZwQueryAttributesFile(ptr ptr) NtQueryAttributesFile
|
||||
@ stdcall ZwQueryDefaultLocale(long ptr) NtQueryDefaultLocale
|
||||
@ stdcall ZwQueryDirectoryFile(long long ptr ptr ptr ptr long long long ptr long)NtQueryDirectoryFile
|
||||
@ stdcall ZwQueryDirectoryObject(long ptr long long long ptr ptr) NtQueryDirectoryObject
|
||||
|
|
|
@ -84,6 +84,7 @@ extern NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
|
|||
|
||||
/* file I/O */
|
||||
extern NTSTATUS FILE_GetNtStatus(void);
|
||||
extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name );
|
||||
extern NTSTATUS DIR_nt_to_unix( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret,
|
||||
int check_last, int check_case );
|
||||
|
||||
|
|
204
files/file.c
204
files/file.c
|
@ -86,8 +86,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
|
|||
#define SECSPERDAY 86400
|
||||
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
|
||||
|
||||
mode_t FILE_umask;
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_ConvertOFMode
|
||||
*
|
||||
|
@ -637,151 +635,6 @@ BOOL WINAPI GetFileInformationByHandle( HANDLE hFile, BY_HANDLE_FILE_INFORMATION
|
|||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* GetFileAttributesW (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetFileAttributesW( LPCWSTR name )
|
||||
{
|
||||
DOS_FULL_NAME full_name;
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
if (!DOSFS_GetFullName( name, TRUE, &full_name) )
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
if (!FILE_Stat( full_name.long_name, &info, NULL ))
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
return info.dwFileAttributes;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* GetFileAttributesA (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetFileAttributesA( LPCSTR name )
|
||||
{
|
||||
UNICODE_STRING nameW;
|
||||
DWORD ret = INVALID_FILE_ATTRIBUTES;
|
||||
|
||||
if (!name)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
if (RtlCreateUnicodeStringFromAsciiz(&nameW, name))
|
||||
{
|
||||
ret = GetFileAttributesW(nameW.Buffer);
|
||||
RtlFreeUnicodeString(&nameW);
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SetFileAttributesW (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD attributes)
|
||||
{
|
||||
struct stat buf;
|
||||
DOS_FULL_NAME full_name;
|
||||
|
||||
if (!lpFileName)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TRACE("(%s,%lx)\n", debugstr_w(lpFileName), attributes);
|
||||
|
||||
if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name ))
|
||||
return FALSE;
|
||||
|
||||
if(stat(full_name.long_name,&buf)==-1)
|
||||
{
|
||||
FILE_SetDosError();
|
||||
return FALSE;
|
||||
}
|
||||
if (attributes & FILE_ATTRIBUTE_READONLY)
|
||||
{
|
||||
if(S_ISDIR(buf.st_mode))
|
||||
/* FIXME */
|
||||
WARN("FILE_ATTRIBUTE_READONLY ignored for directory.\n");
|
||||
else
|
||||
buf.st_mode &= ~0222; /* octal!, clear write permission bits */
|
||||
attributes &= ~FILE_ATTRIBUTE_READONLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add write permission */
|
||||
buf.st_mode |= (0600 | ((buf.st_mode & 044) >> 1)) & (~FILE_umask);
|
||||
}
|
||||
if (attributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (!S_ISDIR(buf.st_mode))
|
||||
FIXME("SetFileAttributes expected the file %s to be a directory\n",
|
||||
debugstr_w(lpFileName));
|
||||
attributes &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
attributes &= ~(FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|
|
||||
FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY);
|
||||
if (attributes)
|
||||
FIXME("(%s):%lx attribute(s) not implemented.\n", debugstr_w(lpFileName), attributes);
|
||||
if (-1==chmod(full_name.long_name,buf.st_mode))
|
||||
{
|
||||
if (GetDriveTypeW(lpFileName) == DRIVE_CDROM)
|
||||
{
|
||||
SetLastError( ERROR_ACCESS_DENIED );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: We don't return FALSE here because of differences between
|
||||
* Linux and Windows privileges. Under Linux only the owner of
|
||||
* the file is allowed to change file attributes. Under Windows,
|
||||
* applications expect that if you can write to a file, you can also
|
||||
* change its attributes (see GENERIC_WRITE). We could try to be
|
||||
* clever here but that would break multi-user installations where
|
||||
* users share read-only DLLs. This is because some installers like
|
||||
* to change attributes of already installed DLLs.
|
||||
*/
|
||||
FIXME("Couldn't set file attributes for existing file \"%s\".\n"
|
||||
"Check permissions or set VFAT \"quiet\" mount flag\n", full_name.long_name);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SetFileAttributesA (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD attributes)
|
||||
{
|
||||
UNICODE_STRING filenameW;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!lpFileName)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (RtlCreateUnicodeStringFromAsciiz(&filenameW, lpFileName))
|
||||
{
|
||||
ret = SetFileAttributesW(filenameW.Buffer, attributes);
|
||||
RtlFreeUnicodeString(&filenameW);
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* GetCompressedFileSizeA [KERNEL32.@]
|
||||
*/
|
||||
|
@ -1725,63 +1578,6 @@ BOOL WINAPI CopyFileExA(LPCSTR sourceFilename, LPCSTR destFilename,
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetFileTime (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetFileTime( HANDLE hFile,
|
||||
const FILETIME *ctime,
|
||||
const FILETIME *atime,
|
||||
const FILETIME *mtime )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
NTSTATUS status;
|
||||
int fd;
|
||||
|
||||
if (!(status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &fd, NULL, NULL )))
|
||||
{
|
||||
#ifdef HAVE_FUTIMES
|
||||
ULONGLONG sec, nsec;
|
||||
struct timeval tv[2];
|
||||
|
||||
if (!atime || !mtime)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
tv[0].tv_sec = tv[0].tv_usec = 0;
|
||||
tv[1].tv_sec = tv[1].tv_usec = 0;
|
||||
if (!fstat( fd, &st ))
|
||||
{
|
||||
tv[0].tv_sec = st.st_atime;
|
||||
tv[1].tv_sec = st.st_mtime;
|
||||
}
|
||||
}
|
||||
if (atime)
|
||||
{
|
||||
sec = ((ULONGLONG)atime->dwHighDateTime << 32) | atime->dwLowDateTime;
|
||||
sec = RtlLargeIntegerDivide( sec, 10000000, &nsec );
|
||||
tv[0].tv_sec = sec - SECS_1601_TO_1970;
|
||||
tv[0].tv_usec = (UINT)nsec / 10;
|
||||
}
|
||||
if (mtime)
|
||||
{
|
||||
sec = ((ULONGLONG)mtime->dwHighDateTime << 32) | mtime->dwLowDateTime;
|
||||
sec = RtlLargeIntegerDivide( sec, 10000000, &nsec );
|
||||
tv[1].tv_sec = sec - SECS_1601_TO_1970;
|
||||
tv[1].tv_usec = (UINT)nsec / 10;
|
||||
}
|
||||
|
||||
if (!futimes( fd, tv )) ret = TRUE;
|
||||
else FILE_SetDosError();
|
||||
#else
|
||||
ret = TRUE; /* pretend it succeeded */
|
||||
#endif
|
||||
wine_server_release_fd( hFile, fd );
|
||||
}
|
||||
else SetLastError( RtlNtStatusToDosError(status) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* GetFileAttributesExW (KERNEL32.@)
|
||||
*/
|
||||
|
|
|
@ -36,7 +36,6 @@ typedef struct
|
|||
} DOS_FULL_NAME;
|
||||
|
||||
/* files/file.c */
|
||||
extern mode_t FILE_umask;
|
||||
extern void FILE_SetDosError(void);
|
||||
extern BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info, BOOL *is_symlink );
|
||||
extern HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
|
||||
|
|
|
@ -1171,6 +1171,7 @@ NTSTATUS WINAPI NtOpenTimer(HANDLE*, ACCESS_MASK, const OBJECT_ATTRIBUTES*);
|
|||
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 NtQueryAttributesFile(const OBJECT_ATTRIBUTES*,FILE_BASIC_INFORMATION*);
|
||||
NTSTATUS WINAPI NtQueryDefaultLocale(BOOLEAN,LCID*);
|
||||
NTSTATUS WINAPI NtQueryDirectoryFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
|
||||
NTSTATUS WINAPI NtQueryInformationFile(HANDLE,PIO_STATUS_BLOCK,PVOID,LONG,FILE_INFORMATION_CLASS);
|
||||
|
|
Loading…
Reference in New Issue