Reimplemented GetFileAttributesW, SetFileAttributesW and SetFileTime
using the corresponding ntdll functionality.
diff --git a/dlls/kernel/file.c b/dlls/kernel/file.c
index 8dfeb98..9c4d0ab 100644
--- a/dlls/kernel/file.c
+++ b/dlls/kernel/file.c
@@ -367,6 +367,40 @@
}
+/***********************************************************************
+ * 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 @@
}
+/**************************************************************************
+ * 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.@)
*/