2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/file/fileinfo.c
5 * PURPOSE: Directory functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
12 /* INCLUDES *****************************************************************/
17 DEBUG_CHANNEL(kernel32file
);
19 /* FUNCTIONS ****************************************************************/
22 FilenameA2W(LPCSTR NameA
, BOOL alloc
)
26 PUNICODE_STRING pstrW
;
29 //ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
30 ASSERT(NtCurrentTeb()->StaticUnicodeString
.MaximumLength
== sizeof(NtCurrentTeb()->StaticUnicodeBuffer
));
32 RtlInitAnsiString(&str
, NameA
);
33 pstrW
= alloc
? &strW
: &NtCurrentTeb()->StaticUnicodeString
;
36 Status
= RtlAnsiStringToUnicodeString( pstrW
, &str
, (BOOLEAN
)alloc
);
38 Status
= RtlOemStringToUnicodeString( pstrW
, &str
, (BOOLEAN
)alloc
);
40 if (NT_SUCCESS(Status
))
43 if (Status
== STATUS_BUFFER_OVERFLOW
)
44 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
46 BaseSetLastNTError(Status
);
53 No copy/conversion is done if the dest. buffer is too small.
56 Success: number of TCHARS copied into dest. buffer NOT including nullterm
57 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
60 FilenameU2A_FitOrFail(
62 INT destLen
, /* buffer size in TCHARS incl. nullchar */
63 PUNICODE_STRING SourceU
68 /* destLen should never exceed MAX_PATH */
69 if (destLen
> MAX_PATH
) destLen
= MAX_PATH
;
71 ret
= bIsFileApiAnsi
? RtlUnicodeStringToAnsiSize(SourceU
) : RtlUnicodeStringToOemSize(SourceU
);
72 /* ret incl. nullchar */
74 if (DestA
&& (INT
)ret
<= destLen
)
79 str
.MaximumLength
= (USHORT
)destLen
;
83 RtlUnicodeStringToAnsiString(&str
, SourceU
, FALSE
);
85 RtlUnicodeStringToOemString(&str
, SourceU
, FALSE
);
87 ret
= str
.Length
; /* SUCCESS: length without terminating 0 */
95 No copy/conversion is done if the dest. buffer is too small.
98 Success: number of TCHARS copied into dest. buffer NOT including nullterm
99 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
102 FilenameW2A_FitOrFail(
104 INT destLen
, /* buffer size in TCHARS incl. nullchar */
106 INT sourceLen
/* buffer size in TCHARS incl. nullchar */
111 if (sourceLen
< 0) sourceLen
= wcslen(SourceW
) + 1;
113 strW
.Buffer
= (PWCHAR
)SourceW
;
114 strW
.MaximumLength
= sourceLen
* sizeof(WCHAR
);
115 strW
.Length
= strW
.MaximumLength
- sizeof(WCHAR
);
117 return FilenameU2A_FitOrFail(DestA
, destLen
, &strW
);
122 Return: num. TCHARS copied into dest including nullterm
127 INT destlen
, /* buffer size in TCHARS incl. nullchar */
129 INT srclen
/* buffer size in TCHARS incl. nullchar */
134 if (srclen
< 0) srclen
= strlen( src
) + 1;
137 RtlMultiByteToUnicodeN( dest
, destlen
* sizeof(WCHAR
), &ret
, (LPSTR
)src
, srclen
);
139 RtlOemToUnicodeN( dest
, destlen
* sizeof(WCHAR
), &ret
, (LPSTR
)src
, srclen
);
141 if (ret
) dest
[(ret
/sizeof(WCHAR
))-1]=0;
143 return ret
/sizeof(WCHAR
);
147 Return: num. TCHARS copied into dest including nullterm
152 INT destlen
, /* buffer size in TCHARS incl. nullchar */
154 INT srclen
/* buffer size in TCHARS incl. nullchar */
159 if (srclen
< 0) srclen
= wcslen( src
) + 1;
162 RtlUnicodeToMultiByteN( dest
, destlen
, &ret
, (LPWSTR
) src
, srclen
* sizeof(WCHAR
));
164 RtlUnicodeToOemN( dest
, destlen
, &ret
, (LPWSTR
) src
, srclen
* sizeof(WCHAR
) );
166 if (ret
) dest
[ret
-1]=0;
175 FlushFileBuffers(IN HANDLE hFile
)
178 IO_STATUS_BLOCK IoStatusBlock
;
180 hFile
= TranslateStdHandle(hFile
);
182 if (IsConsoleHandle(hFile
))
184 return FlushConsoleInputBuffer(hFile
);
187 Status
= NtFlushBuffersFile(hFile
,
189 if (!NT_SUCCESS(Status
))
191 BaseSetLastNTError(Status
);
204 SetFilePointer(HANDLE hFile
,
205 LONG lDistanceToMove
,
206 PLONG lpDistanceToMoveHigh
,
209 FILE_POSITION_INFORMATION FilePosition
;
210 FILE_STANDARD_INFORMATION FileStandard
;
212 IO_STATUS_BLOCK IoStatusBlock
;
213 LARGE_INTEGER Distance
;
215 TRACE("SetFilePointer(hFile %p, lDistanceToMove %d, dwMoveMethod %lu)\n",
216 hFile
,lDistanceToMove
,dwMoveMethod
);
218 if(IsConsoleHandle(hFile
))
220 SetLastError(ERROR_INVALID_HANDLE
);
221 return INVALID_SET_FILE_POINTER
;
224 if (lpDistanceToMoveHigh
)
226 Distance
.u
.HighPart
= *lpDistanceToMoveHigh
;
227 Distance
.u
.LowPart
= lDistanceToMove
;
231 Distance
.QuadPart
= lDistanceToMove
;
237 errCode
= NtQueryInformationFile(hFile
,
240 sizeof(FILE_POSITION_INFORMATION
),
241 FilePositionInformation
);
242 FilePosition
.CurrentByteOffset
.QuadPart
+= Distance
.QuadPart
;
243 if (!NT_SUCCESS(errCode
))
245 if (lpDistanceToMoveHigh
!= NULL
)
246 *lpDistanceToMoveHigh
= -1;
247 BaseSetLastNTError(errCode
);
248 return INVALID_SET_FILE_POINTER
;
252 errCode
= NtQueryInformationFile(hFile
,
255 sizeof(FILE_STANDARD_INFORMATION
),
256 FileStandardInformation
);
257 FilePosition
.CurrentByteOffset
.QuadPart
=
258 FileStandard
.EndOfFile
.QuadPart
+ Distance
.QuadPart
;
259 if (!NT_SUCCESS(errCode
))
261 if (lpDistanceToMoveHigh
!= NULL
)
262 *lpDistanceToMoveHigh
= -1;
263 BaseSetLastNTError(errCode
);
264 return INVALID_SET_FILE_POINTER
;
268 FilePosition
.CurrentByteOffset
.QuadPart
= Distance
.QuadPart
;
271 SetLastError(ERROR_INVALID_PARAMETER
);
272 return INVALID_SET_FILE_POINTER
;
275 if(FilePosition
.CurrentByteOffset
.QuadPart
< 0)
277 SetLastError(ERROR_NEGATIVE_SEEK
);
278 return INVALID_SET_FILE_POINTER
;
281 if (lpDistanceToMoveHigh
== NULL
&& FilePosition
.CurrentByteOffset
.HighPart
!= 0)
283 /* If we're moving the pointer outside of the 32 bit boundaries but
284 the application only passed a 32 bit value we need to bail out! */
285 SetLastError(ERROR_INVALID_PARAMETER
);
286 return INVALID_SET_FILE_POINTER
;
289 errCode
= NtSetInformationFile(hFile
,
292 sizeof(FILE_POSITION_INFORMATION
),
293 FilePositionInformation
);
294 if (!NT_SUCCESS(errCode
))
296 if (lpDistanceToMoveHigh
!= NULL
)
297 *lpDistanceToMoveHigh
= -1;
299 BaseSetLastNTError(errCode
);
300 return INVALID_SET_FILE_POINTER
;
303 if (lpDistanceToMoveHigh
!= NULL
)
305 *lpDistanceToMoveHigh
= FilePosition
.CurrentByteOffset
.u
.HighPart
;
308 if (FilePosition
.CurrentByteOffset
.u
.LowPart
== MAXDWORD
)
310 /* The value of -1 is valid here, especially when the new
311 file position is greater than 4 GB. Since NtSetInformationFile
312 succeeded we never set an error code and we explicitly need
313 to clear a previously set error code in this case, which
314 an application will check if INVALID_SET_FILE_POINTER is returned! */
315 SetLastError(ERROR_SUCCESS
);
318 return FilePosition
.CurrentByteOffset
.u
.LowPart
;
327 SetFilePointerEx(HANDLE hFile
,
328 LARGE_INTEGER liDistanceToMove
,
329 PLARGE_INTEGER lpNewFilePointer
,
333 IO_STATUS_BLOCK IoStatusBlock
;
334 FILE_POSITION_INFORMATION FilePosition
;
335 FILE_STANDARD_INFORMATION FileStandard
;
337 if (IsConsoleHandle(hFile
))
339 BaseSetLastNTError(STATUS_INVALID_HANDLE
);
343 switch (dwMoveMethod
)
347 Status
= NtQueryInformationFile(hFile
, &IoStatusBlock
,
349 sizeof(FILE_POSITION_INFORMATION
),
350 FilePositionInformation
);
351 if (!NT_SUCCESS(Status
))
353 BaseSetLastNTError(Status
);
357 FilePosition
.CurrentByteOffset
.QuadPart
+= liDistanceToMove
.QuadPart
;
363 Status
= NtQueryInformationFile(hFile
, &IoStatusBlock
,
365 sizeof(FILE_STANDARD_INFORMATION
),
366 FileStandardInformation
);
367 if (!NT_SUCCESS(Status
))
369 BaseSetLastNTError(Status
);
373 FilePosition
.CurrentByteOffset
.QuadPart
= FileStandard
.EndOfFile
.QuadPart
+
374 liDistanceToMove
.QuadPart
;
380 FilePosition
.CurrentByteOffset
.QuadPart
= liDistanceToMove
.QuadPart
;
386 SetLastError(ERROR_INVALID_PARAMETER
);
391 if (FilePosition
.CurrentByteOffset
.QuadPart
< 0)
393 SetLastError(ERROR_NEGATIVE_SEEK
);
397 Status
= NtSetInformationFile(hFile
, &IoStatusBlock
, &FilePosition
,
398 sizeof(FILE_POSITION_INFORMATION
),
399 FilePositionInformation
);
400 if (!NT_SUCCESS(Status
))
402 BaseSetLastNTError(Status
);
406 if (lpNewFilePointer
!= NULL
)
408 *lpNewFilePointer
= FilePosition
.CurrentByteOffset
;
419 GetFileType(HANDLE hFile
)
421 FILE_FS_DEVICE_INFORMATION DeviceInfo
;
422 IO_STATUS_BLOCK StatusBlock
;
425 /* Get real handle */
426 hFile
= TranslateStdHandle(hFile
);
428 /* Check for console handle */
429 if (IsConsoleHandle(hFile
))
431 if (VerifyConsoleIoHandle(hFile
))
432 return FILE_TYPE_CHAR
;
435 Status
= NtQueryVolumeInformationFile(hFile
,
438 sizeof(FILE_FS_DEVICE_INFORMATION
),
439 FileFsDeviceInformation
);
440 if (!NT_SUCCESS(Status
))
442 BaseSetLastNTError(Status
);
443 return FILE_TYPE_UNKNOWN
;
446 switch (DeviceInfo
.DeviceType
)
448 case FILE_DEVICE_CD_ROM
:
449 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
450 case FILE_DEVICE_CONTROLLER
:
451 case FILE_DEVICE_DATALINK
:
452 case FILE_DEVICE_DFS
:
453 case FILE_DEVICE_DISK
:
454 case FILE_DEVICE_DISK_FILE_SYSTEM
:
455 case FILE_DEVICE_VIRTUAL_DISK
:
456 return FILE_TYPE_DISK
;
458 case FILE_DEVICE_KEYBOARD
:
459 case FILE_DEVICE_MOUSE
:
460 case FILE_DEVICE_NULL
:
461 case FILE_DEVICE_PARALLEL_PORT
:
462 case FILE_DEVICE_PRINTER
:
463 case FILE_DEVICE_SERIAL_PORT
:
464 case FILE_DEVICE_SCREEN
:
465 case FILE_DEVICE_SOUND
:
466 case FILE_DEVICE_MODEM
:
467 return FILE_TYPE_CHAR
;
469 case FILE_DEVICE_NAMED_PIPE
:
470 return FILE_TYPE_PIPE
;
473 return FILE_TYPE_UNKNOWN
;
481 GetFileSize(HANDLE hFile
,
482 LPDWORD lpFileSizeHigh
)
485 FILE_STANDARD_INFORMATION FileStandard
;
486 IO_STATUS_BLOCK IoStatusBlock
;
488 errCode
= NtQueryInformationFile(hFile
,
491 sizeof(FILE_STANDARD_INFORMATION
),
492 FileStandardInformation
);
493 if (!NT_SUCCESS(errCode
))
495 BaseSetLastNTError(errCode
);
496 if ( lpFileSizeHigh
== NULL
)
505 if ( lpFileSizeHigh
!= NULL
)
506 *lpFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
508 return FileStandard
.EndOfFile
.u
.LowPart
;
519 PLARGE_INTEGER lpFileSize
523 FILE_STANDARD_INFORMATION FileStandard
;
524 IO_STATUS_BLOCK IoStatusBlock
;
526 errCode
= NtQueryInformationFile(hFile
,
529 sizeof(FILE_STANDARD_INFORMATION
),
530 FileStandardInformation
);
531 if (!NT_SUCCESS(errCode
))
533 BaseSetLastNTError(errCode
);
537 *lpFileSize
= FileStandard
.EndOfFile
;
547 GetCompressedFileSizeA(LPCSTR lpFileName
,
548 LPDWORD lpFileSizeHigh
)
552 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
553 return INVALID_FILE_SIZE
;
555 return GetCompressedFileSizeW(FileNameW
, lpFileSizeHigh
);
563 GetCompressedFileSizeW(LPCWSTR lpFileName
,
564 LPDWORD lpFileSizeHigh
)
566 FILE_COMPRESSION_INFORMATION FileCompression
;
568 IO_STATUS_BLOCK IoStatusBlock
;
571 hFile
= CreateFileW(lpFileName
,
576 FILE_ATTRIBUTE_NORMAL
,
579 if (hFile
== INVALID_HANDLE_VALUE
)
580 return INVALID_FILE_SIZE
;
582 errCode
= NtQueryInformationFile(hFile
,
585 sizeof(FILE_COMPRESSION_INFORMATION
),
586 FileCompressionInformation
);
590 if (!NT_SUCCESS(errCode
))
592 BaseSetLastNTError(errCode
);
593 return INVALID_FILE_SIZE
;
597 *lpFileSizeHigh
= FileCompression
.CompressedFileSize
.u
.HighPart
;
599 SetLastError(NO_ERROR
);
600 return FileCompression
.CompressedFileSize
.u
.LowPart
;
608 GetFileInformationByHandle(HANDLE hFile
,
609 LPBY_HANDLE_FILE_INFORMATION lpFileInformation
)
613 FILE_FS_VOLUME_INFORMATION FileFsVolume
;
618 FILE_BASIC_INFORMATION FileBasic
;
619 FILE_INTERNAL_INFORMATION FileInternal
;
620 FILE_STANDARD_INFORMATION FileStandard
;
622 IO_STATUS_BLOCK IoStatusBlock
;
624 if(IsConsoleHandle(hFile
))
626 SetLastError(ERROR_INVALID_HANDLE
);
630 errCode
= NtQueryInformationFile(hFile
,
633 sizeof(FILE_BASIC_INFORMATION
),
634 FileBasicInformation
);
635 if (!NT_SUCCESS(errCode
))
637 BaseSetLastNTError(errCode
);
641 lpFileInformation
->dwFileAttributes
= (DWORD
)FileBasic
.FileAttributes
;
643 lpFileInformation
->ftCreationTime
.dwHighDateTime
= FileBasic
.CreationTime
.u
.HighPart
;
644 lpFileInformation
->ftCreationTime
.dwLowDateTime
= FileBasic
.CreationTime
.u
.LowPart
;
646 lpFileInformation
->ftLastAccessTime
.dwHighDateTime
= FileBasic
.LastAccessTime
.u
.HighPart
;
647 lpFileInformation
->ftLastAccessTime
.dwLowDateTime
= FileBasic
.LastAccessTime
.u
.LowPart
;
649 lpFileInformation
->ftLastWriteTime
.dwHighDateTime
= FileBasic
.LastWriteTime
.u
.HighPart
;
650 lpFileInformation
->ftLastWriteTime
.dwLowDateTime
= FileBasic
.LastWriteTime
.u
.LowPart
;
652 errCode
= NtQueryInformationFile(hFile
,
655 sizeof(FILE_INTERNAL_INFORMATION
),
656 FileInternalInformation
);
657 if (!NT_SUCCESS(errCode
))
659 BaseSetLastNTError(errCode
);
663 lpFileInformation
->nFileIndexHigh
= FileInternal
.IndexNumber
.u
.HighPart
;
664 lpFileInformation
->nFileIndexLow
= FileInternal
.IndexNumber
.u
.LowPart
;
666 errCode
= NtQueryVolumeInformationFile(hFile
,
669 sizeof(FileFsVolume
),
670 FileFsVolumeInformation
);
671 if (!NT_SUCCESS(errCode
))
673 BaseSetLastNTError(errCode
);
677 lpFileInformation
->dwVolumeSerialNumber
= FileFsVolume
.FileFsVolume
.VolumeSerialNumber
;
679 errCode
= NtQueryInformationFile(hFile
,
682 sizeof(FILE_STANDARD_INFORMATION
),
683 FileStandardInformation
);
684 if (!NT_SUCCESS(errCode
))
686 BaseSetLastNTError(errCode
);
690 lpFileInformation
->nNumberOfLinks
= FileStandard
.NumberOfLinks
;
691 lpFileInformation
->nFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
692 lpFileInformation
->nFileSizeLow
= FileStandard
.EndOfFile
.u
.LowPart
;
702 GetFileAttributesExW(LPCWSTR lpFileName
,
703 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
704 LPVOID lpFileInformation
)
706 FILE_NETWORK_OPEN_INFORMATION FileInformation
;
707 OBJECT_ATTRIBUTES ObjectAttributes
;
708 UNICODE_STRING FileName
;
710 WIN32_FILE_ATTRIBUTE_DATA
* FileAttributeData
;
712 TRACE("GetFileAttributesExW(%S) called\n", lpFileName
);
715 if (fInfoLevelId
!= GetFileExInfoStandard
|| lpFileInformation
== NULL
)
717 SetLastError(ERROR_INVALID_PARAMETER
);
721 /* Validate and translate the filename */
722 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
727 WARN ("Invalid path '%S'\n", lpFileName
);
728 SetLastError (ERROR_BAD_PATHNAME
);
732 /* build the object attributes */
733 InitializeObjectAttributes (&ObjectAttributes
,
735 OBJ_CASE_INSENSITIVE
,
739 /* Get file attributes */
740 Status
= NtQueryFullAttributesFile(&ObjectAttributes
,
743 RtlFreeUnicodeString (&FileName
);
744 if (!NT_SUCCESS (Status
))
746 WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status
);
747 BaseSetLastNTError (Status
);
751 FileAttributeData
= (WIN32_FILE_ATTRIBUTE_DATA
*)lpFileInformation
;
752 FileAttributeData
->dwFileAttributes
= FileInformation
.FileAttributes
;
753 FileAttributeData
->ftCreationTime
.dwLowDateTime
= FileInformation
.CreationTime
.u
.LowPart
;
754 FileAttributeData
->ftCreationTime
.dwHighDateTime
= FileInformation
.CreationTime
.u
.HighPart
;
755 FileAttributeData
->ftLastAccessTime
.dwLowDateTime
= FileInformation
.LastAccessTime
.u
.LowPart
;
756 FileAttributeData
->ftLastAccessTime
.dwHighDateTime
= FileInformation
.LastAccessTime
.u
.HighPart
;
757 FileAttributeData
->ftLastWriteTime
.dwLowDateTime
= FileInformation
.LastWriteTime
.u
.LowPart
;
758 FileAttributeData
->ftLastWriteTime
.dwHighDateTime
= FileInformation
.LastWriteTime
.u
.HighPart
;
759 FileAttributeData
->nFileSizeLow
= FileInformation
.EndOfFile
.u
.LowPart
;
760 FileAttributeData
->nFileSizeHigh
= FileInformation
.EndOfFile
.u
.HighPart
;
769 GetFileAttributesExA(LPCSTR lpFileName
,
770 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
771 LPVOID lpFileInformation
)
775 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
778 return GetFileAttributesExW(FileNameW
, fInfoLevelId
, lpFileInformation
);
786 GetFileAttributesA(LPCSTR lpFileName
)
790 if (!lpFileName
|| !(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
791 return INVALID_FILE_ATTRIBUTES
;
793 return GetFileAttributesW(FileNameW
);
802 GetFileAttributesW(LPCWSTR lpFileName
)
805 UNICODE_STRING FileName
;
806 OBJECT_ATTRIBUTES ObjectAttributes
;
807 FILE_BASIC_INFORMATION FileInformation
;
809 /* Get the NT path name */
810 if (!RtlDosPathNameToNtPathName_U(lpFileName
, &FileName
, NULL
, NULL
))
812 SetLastError(ERROR_PATH_NOT_FOUND
);
813 return INVALID_FILE_ATTRIBUTES
;
816 /* Prepare for querying attributes */
817 InitializeObjectAttributes(&ObjectAttributes
, &FileName
,
818 OBJ_CASE_INSENSITIVE
,
820 /* Simply query attributes */
821 Status
= NtQueryAttributesFile(&ObjectAttributes
, &FileInformation
);
822 if (!NT_SUCCESS(Status
))
824 /* It failed? Is it a DOS device? */
825 if (RtlIsDosDeviceName_U(lpFileName
))
827 return FILE_ATTRIBUTE_ARCHIVE
;
830 /* Set the error otherwise */
831 BaseSetLastNTError(Status
);
832 return INVALID_FILE_ATTRIBUTES
;
835 /* Return the file attributes */
836 return FileInformation
.FileAttributes
;
844 GetFileAttributesByHandle(IN HANDLE hFile
,
845 OUT LPDWORD dwFileAttributes
,
848 FILE_BASIC_INFORMATION FileBasic
;
849 IO_STATUS_BLOCK IoStatusBlock
;
852 UNREFERENCED_PARAMETER(dwFlags
);
854 if (IsConsoleHandle(hFile
))
856 SetLastError(ERROR_INVALID_HANDLE
);
860 Status
= NtQueryInformationFile(hFile
,
864 FileBasicInformation
);
865 if (NT_SUCCESS(Status
))
867 *dwFileAttributes
= FileBasic
.FileAttributes
;
871 BaseSetLastNTError(Status
);
880 SetFileAttributesByHandle(IN HANDLE hFile
,
881 IN DWORD dwFileAttributes
,
884 FILE_BASIC_INFORMATION FileBasic
;
885 IO_STATUS_BLOCK IoStatusBlock
;
888 UNREFERENCED_PARAMETER(dwFlags
);
890 if (IsConsoleHandle(hFile
))
892 SetLastError(ERROR_INVALID_HANDLE
);
896 Status
= NtQueryInformationFile(hFile
,
900 FileBasicInformation
);
901 if (NT_SUCCESS(Status
))
903 FileBasic
.FileAttributes
= dwFileAttributes
;
905 Status
= NtSetInformationFile(hFile
,
909 FileBasicInformation
);
912 if (!NT_SUCCESS(Status
))
914 BaseSetLastNTError(Status
);
928 DWORD dwFileAttributes
)
932 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
935 return SetFileAttributesW(FileNameW
, dwFileAttributes
);
944 SetFileAttributesW(LPCWSTR lpFileName
,
945 DWORD dwFileAttributes
)
950 UNICODE_STRING NtPathU
;
951 IO_STATUS_BLOCK IoStatusBlock
;
952 RTL_RELATIVE_NAME_U RelativeName
;
953 OBJECT_ATTRIBUTES ObjectAttributes
;
954 FILE_BASIC_INFORMATION FileInformation
;
956 /* Get relative name */
957 if (!RtlDosPathNameToRelativeNtPathName_U(lpFileName
, &NtPathU
, NULL
, &RelativeName
))
959 SetLastError(ERROR_PATH_NOT_FOUND
);
963 /* Save buffer to allow later freeing */
964 PathUBuffer
= NtPathU
.Buffer
;
966 /* If we have relative name (and root dir), use them instead */
967 if (RelativeName
.RelativeName
.Length
!= 0)
969 NtPathU
.Length
= RelativeName
.RelativeName
.Length
;
970 NtPathU
.MaximumLength
= RelativeName
.RelativeName
.MaximumLength
;
971 NtPathU
.Buffer
= RelativeName
.RelativeName
.Buffer
;
975 RelativeName
.ContainingDirectory
= NULL
;
978 /* Prepare the object attribute for opening the file */
979 InitializeObjectAttributes(&ObjectAttributes
, &NtPathU
,
980 OBJ_CASE_INSENSITIVE
,
981 RelativeName
.ContainingDirectory
, NULL
);
983 /* Attempt to open the file, while supporting reparse point */
984 Status
= NtOpenFile(&FileHandle
, FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
985 &ObjectAttributes
, &IoStatusBlock
,
986 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
987 FILE_OPEN_REPARSE_POINT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
);
988 /* If opening failed, check whether it was because of reparse point support */
989 if (!NT_SUCCESS(Status
))
991 /* Nope, just quit */
992 if (Status
!= STATUS_INVALID_PARAMETER
)
994 RtlReleaseRelativeName(&RelativeName
);
995 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer
);
996 BaseSetLastNTError(Status
);
1001 /* Yes, retry without */
1002 Status
= NtOpenFile(&FileHandle
, FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
1003 &ObjectAttributes
, &IoStatusBlock
,
1004 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1005 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
);
1006 if (!NT_SUCCESS(Status
))
1008 RtlReleaseRelativeName(&RelativeName
);
1009 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer
);
1010 BaseSetLastNTError(Status
);
1016 /* We don't need strings anylonger */
1017 RtlReleaseRelativeName(&RelativeName
);
1018 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer
);
1020 /* Zero our structure, we'll only set file attributes */
1021 ZeroMemory(&FileInformation
, sizeof(FileInformation
));
1022 /* Set the attributes, filtering only allowed attributes, and forcing normal attribute */
1023 FileInformation
.FileAttributes
= (dwFileAttributes
& FILE_ATTRIBUTE_VALID_SET_FLAGS
) | FILE_ATTRIBUTE_NORMAL
;
1025 /* Finally, set the attributes */
1026 Status
= NtSetInformationFile(FileHandle
, &IoStatusBlock
, &FileInformation
,
1027 sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
);
1028 /* Close the file */
1029 NtClose(FileHandle
);
1031 /* If it failed, set the error and fail */
1032 if (!NT_SUCCESS(Status
))
1034 BaseSetLastNTError(Status
);
1046 GetFileTime(IN HANDLE hFile
,
1047 OUT LPFILETIME lpCreationTime OPTIONAL
,
1048 OUT LPFILETIME lpLastAccessTime OPTIONAL
,
1049 OUT LPFILETIME lpLastWriteTime OPTIONAL
)
1052 IO_STATUS_BLOCK IoStatusBlock
;
1053 FILE_BASIC_INFORMATION FileBasic
;
1055 if(IsConsoleHandle(hFile
))
1057 BaseSetLastNTError(STATUS_INVALID_HANDLE
);
1061 Status
= NtQueryInformationFile(hFile
,
1064 sizeof(FILE_BASIC_INFORMATION
),
1065 FileBasicInformation
);
1066 if (!NT_SUCCESS(Status
))
1068 BaseSetLastNTError(Status
);
1074 lpCreationTime
->dwLowDateTime
= FileBasic
.CreationTime
.LowPart
;
1075 lpCreationTime
->dwHighDateTime
= FileBasic
.CreationTime
.HighPart
;
1078 if (lpLastAccessTime
)
1080 lpLastAccessTime
->dwLowDateTime
= FileBasic
.LastAccessTime
.LowPart
;
1081 lpLastAccessTime
->dwHighDateTime
= FileBasic
.LastAccessTime
.HighPart
;
1084 if (lpLastWriteTime
)
1086 lpLastWriteTime
->dwLowDateTime
= FileBasic
.LastWriteTime
.LowPart
;
1087 lpLastWriteTime
->dwHighDateTime
= FileBasic
.LastWriteTime
.HighPart
;
1098 SetFileTime(IN HANDLE hFile
,
1099 CONST FILETIME
*lpCreationTime OPTIONAL
,
1100 CONST FILETIME
*lpLastAccessTime OPTIONAL
,
1101 CONST FILETIME
*lpLastWriteTime OPTIONAL
)
1104 IO_STATUS_BLOCK IoStatusBlock
;
1105 FILE_BASIC_INFORMATION FileBasic
;
1107 if(IsConsoleHandle(hFile
))
1109 BaseSetLastNTError(STATUS_INVALID_HANDLE
);
1113 memset(&FileBasic
, 0, sizeof(FILE_BASIC_INFORMATION
));
1117 FileBasic
.CreationTime
.LowPart
= lpCreationTime
->dwLowDateTime
;
1118 FileBasic
.CreationTime
.HighPart
= lpCreationTime
->dwHighDateTime
;
1121 if (lpLastAccessTime
)
1123 FileBasic
.LastAccessTime
.LowPart
= lpLastAccessTime
->dwLowDateTime
;
1124 FileBasic
.LastAccessTime
.HighPart
= lpLastAccessTime
->dwHighDateTime
;
1127 if (lpLastWriteTime
)
1129 FileBasic
.LastWriteTime
.LowPart
= lpLastWriteTime
->dwLowDateTime
;
1130 FileBasic
.LastWriteTime
.HighPart
= lpLastWriteTime
->dwHighDateTime
;
1133 Status
= NtSetInformationFile(hFile
,
1136 sizeof(FILE_BASIC_INFORMATION
),
1137 FileBasicInformation
);
1138 if (!NT_SUCCESS(Status
))
1140 BaseSetLastNTError(Status
);
1149 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1154 SetEndOfFile(HANDLE hFile
)
1156 IO_STATUS_BLOCK IoStatusBlock
;
1157 FILE_END_OF_FILE_INFORMATION EndOfFileInfo
;
1158 FILE_ALLOCATION_INFORMATION FileAllocationInfo
;
1159 FILE_POSITION_INFORMATION FilePosInfo
;
1162 if(IsConsoleHandle(hFile
))
1164 SetLastError(ERROR_INVALID_HANDLE
);
1168 //get current position
1169 Status
= NtQueryInformationFile(
1173 sizeof(FILE_POSITION_INFORMATION
),
1174 FilePositionInformation
1177 if (!NT_SUCCESS(Status
)){
1178 BaseSetLastNTError(Status
);
1182 EndOfFileInfo
.EndOfFile
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1186 This call is not supposed to free up any space after the eof marker
1187 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1188 But...most file systems dispatch both FileEndOfFileInformation
1189 and FileAllocationInformation as they were the same command.
1192 Status
= NtSetInformationFile(
1194 &IoStatusBlock
, //out
1196 sizeof(FILE_END_OF_FILE_INFORMATION
),
1197 FileEndOfFileInformation
1200 if (!NT_SUCCESS(Status
)){
1201 BaseSetLastNTError(Status
);
1205 FileAllocationInfo
.AllocationSize
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1208 Status
= NtSetInformationFile(
1210 &IoStatusBlock
, //out
1211 &FileAllocationInfo
,
1212 sizeof(FILE_ALLOCATION_INFORMATION
),
1213 FileAllocationInformation
1216 if (!NT_SUCCESS(Status
)){
1217 BaseSetLastNTError(Status
);
1233 LONGLONG ValidDataLength
1236 IO_STATUS_BLOCK IoStatusBlock
;
1237 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation
;
1240 ValidDataLengthInformation
.ValidDataLength
.QuadPart
= ValidDataLength
;
1242 Status
= NtSetInformationFile(
1244 &IoStatusBlock
, //out
1245 &ValidDataLengthInformation
,
1246 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION
),
1247 FileValidDataLengthInformation
1250 if (!NT_SUCCESS(Status
)){
1251 BaseSetLastNTError(Status
);