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
,
332 FILE_POSITION_INFORMATION FilePosition
;
333 FILE_STANDARD_INFORMATION FileStandard
;
335 IO_STATUS_BLOCK IoStatusBlock
;
337 if(IsConsoleHandle(hFile
))
339 SetLastError(ERROR_INVALID_HANDLE
);
346 NtQueryInformationFile(hFile
,
349 sizeof(FILE_POSITION_INFORMATION
),
350 FilePositionInformation
);
351 FilePosition
.CurrentByteOffset
.QuadPart
+= liDistanceToMove
.QuadPart
;
354 NtQueryInformationFile(hFile
,
357 sizeof(FILE_STANDARD_INFORMATION
),
358 FileStandardInformation
);
359 FilePosition
.CurrentByteOffset
.QuadPart
=
360 FileStandard
.EndOfFile
.QuadPart
+ liDistanceToMove
.QuadPart
;
363 FilePosition
.CurrentByteOffset
.QuadPart
= liDistanceToMove
.QuadPart
;
366 SetLastError(ERROR_INVALID_PARAMETER
);
370 if(FilePosition
.CurrentByteOffset
.QuadPart
< 0)
372 SetLastError(ERROR_NEGATIVE_SEEK
);
376 errCode
= NtSetInformationFile(hFile
,
379 sizeof(FILE_POSITION_INFORMATION
),
380 FilePositionInformation
);
381 if (!NT_SUCCESS(errCode
))
383 BaseSetLastNTError(errCode
);
387 if (lpNewFilePointer
)
389 *lpNewFilePointer
= FilePosition
.CurrentByteOffset
;
399 GetFileType(HANDLE hFile
)
401 FILE_FS_DEVICE_INFORMATION DeviceInfo
;
402 IO_STATUS_BLOCK StatusBlock
;
405 /* Get real handle */
406 hFile
= TranslateStdHandle(hFile
);
408 /* Check for console handle */
409 if (IsConsoleHandle(hFile
))
411 if (VerifyConsoleIoHandle(hFile
))
412 return FILE_TYPE_CHAR
;
415 Status
= NtQueryVolumeInformationFile(hFile
,
418 sizeof(FILE_FS_DEVICE_INFORMATION
),
419 FileFsDeviceInformation
);
420 if (!NT_SUCCESS(Status
))
422 BaseSetLastNTError(Status
);
423 return FILE_TYPE_UNKNOWN
;
426 switch (DeviceInfo
.DeviceType
)
428 case FILE_DEVICE_CD_ROM
:
429 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
430 case FILE_DEVICE_CONTROLLER
:
431 case FILE_DEVICE_DATALINK
:
432 case FILE_DEVICE_DFS
:
433 case FILE_DEVICE_DISK
:
434 case FILE_DEVICE_DISK_FILE_SYSTEM
:
435 case FILE_DEVICE_VIRTUAL_DISK
:
436 return FILE_TYPE_DISK
;
438 case FILE_DEVICE_KEYBOARD
:
439 case FILE_DEVICE_MOUSE
:
440 case FILE_DEVICE_NULL
:
441 case FILE_DEVICE_PARALLEL_PORT
:
442 case FILE_DEVICE_PRINTER
:
443 case FILE_DEVICE_SERIAL_PORT
:
444 case FILE_DEVICE_SCREEN
:
445 case FILE_DEVICE_SOUND
:
446 case FILE_DEVICE_MODEM
:
447 return FILE_TYPE_CHAR
;
449 case FILE_DEVICE_NAMED_PIPE
:
450 return FILE_TYPE_PIPE
;
453 return FILE_TYPE_UNKNOWN
;
461 GetFileSize(HANDLE hFile
,
462 LPDWORD lpFileSizeHigh
)
465 FILE_STANDARD_INFORMATION FileStandard
;
466 IO_STATUS_BLOCK IoStatusBlock
;
468 errCode
= NtQueryInformationFile(hFile
,
471 sizeof(FILE_STANDARD_INFORMATION
),
472 FileStandardInformation
);
473 if (!NT_SUCCESS(errCode
))
475 BaseSetLastNTError(errCode
);
476 if ( lpFileSizeHigh
== NULL
)
485 if ( lpFileSizeHigh
!= NULL
)
486 *lpFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
488 return FileStandard
.EndOfFile
.u
.LowPart
;
499 PLARGE_INTEGER lpFileSize
503 FILE_STANDARD_INFORMATION FileStandard
;
504 IO_STATUS_BLOCK IoStatusBlock
;
506 errCode
= NtQueryInformationFile(hFile
,
509 sizeof(FILE_STANDARD_INFORMATION
),
510 FileStandardInformation
);
511 if (!NT_SUCCESS(errCode
))
513 BaseSetLastNTError(errCode
);
517 *lpFileSize
= FileStandard
.EndOfFile
;
527 GetCompressedFileSizeA(LPCSTR lpFileName
,
528 LPDWORD lpFileSizeHigh
)
532 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
533 return INVALID_FILE_SIZE
;
535 return GetCompressedFileSizeW(FileNameW
, lpFileSizeHigh
);
543 GetCompressedFileSizeW(LPCWSTR lpFileName
,
544 LPDWORD lpFileSizeHigh
)
546 FILE_COMPRESSION_INFORMATION FileCompression
;
548 IO_STATUS_BLOCK IoStatusBlock
;
551 hFile
= CreateFileW(lpFileName
,
556 FILE_ATTRIBUTE_NORMAL
,
559 if (hFile
== INVALID_HANDLE_VALUE
)
560 return INVALID_FILE_SIZE
;
562 errCode
= NtQueryInformationFile(hFile
,
565 sizeof(FILE_COMPRESSION_INFORMATION
),
566 FileCompressionInformation
);
570 if (!NT_SUCCESS(errCode
))
572 BaseSetLastNTError(errCode
);
573 return INVALID_FILE_SIZE
;
577 *lpFileSizeHigh
= FileCompression
.CompressedFileSize
.u
.HighPart
;
579 SetLastError(NO_ERROR
);
580 return FileCompression
.CompressedFileSize
.u
.LowPart
;
588 GetFileInformationByHandle(HANDLE hFile
,
589 LPBY_HANDLE_FILE_INFORMATION lpFileInformation
)
593 FILE_FS_VOLUME_INFORMATION FileFsVolume
;
598 FILE_BASIC_INFORMATION FileBasic
;
599 FILE_INTERNAL_INFORMATION FileInternal
;
600 FILE_STANDARD_INFORMATION FileStandard
;
602 IO_STATUS_BLOCK IoStatusBlock
;
604 if(IsConsoleHandle(hFile
))
606 SetLastError(ERROR_INVALID_HANDLE
);
610 errCode
= NtQueryInformationFile(hFile
,
613 sizeof(FILE_BASIC_INFORMATION
),
614 FileBasicInformation
);
615 if (!NT_SUCCESS(errCode
))
617 BaseSetLastNTError(errCode
);
621 lpFileInformation
->dwFileAttributes
= (DWORD
)FileBasic
.FileAttributes
;
623 lpFileInformation
->ftCreationTime
.dwHighDateTime
= FileBasic
.CreationTime
.u
.HighPart
;
624 lpFileInformation
->ftCreationTime
.dwLowDateTime
= FileBasic
.CreationTime
.u
.LowPart
;
626 lpFileInformation
->ftLastAccessTime
.dwHighDateTime
= FileBasic
.LastAccessTime
.u
.HighPart
;
627 lpFileInformation
->ftLastAccessTime
.dwLowDateTime
= FileBasic
.LastAccessTime
.u
.LowPart
;
629 lpFileInformation
->ftLastWriteTime
.dwHighDateTime
= FileBasic
.LastWriteTime
.u
.HighPart
;
630 lpFileInformation
->ftLastWriteTime
.dwLowDateTime
= FileBasic
.LastWriteTime
.u
.LowPart
;
632 errCode
= NtQueryInformationFile(hFile
,
635 sizeof(FILE_INTERNAL_INFORMATION
),
636 FileInternalInformation
);
637 if (!NT_SUCCESS(errCode
))
639 BaseSetLastNTError(errCode
);
643 lpFileInformation
->nFileIndexHigh
= FileInternal
.IndexNumber
.u
.HighPart
;
644 lpFileInformation
->nFileIndexLow
= FileInternal
.IndexNumber
.u
.LowPart
;
646 errCode
= NtQueryVolumeInformationFile(hFile
,
649 sizeof(FileFsVolume
),
650 FileFsVolumeInformation
);
651 if (!NT_SUCCESS(errCode
))
653 BaseSetLastNTError(errCode
);
657 lpFileInformation
->dwVolumeSerialNumber
= FileFsVolume
.FileFsVolume
.VolumeSerialNumber
;
659 errCode
= NtQueryInformationFile(hFile
,
662 sizeof(FILE_STANDARD_INFORMATION
),
663 FileStandardInformation
);
664 if (!NT_SUCCESS(errCode
))
666 BaseSetLastNTError(errCode
);
670 lpFileInformation
->nNumberOfLinks
= FileStandard
.NumberOfLinks
;
671 lpFileInformation
->nFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
672 lpFileInformation
->nFileSizeLow
= FileStandard
.EndOfFile
.u
.LowPart
;
682 GetFileAttributesExW(LPCWSTR lpFileName
,
683 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
684 LPVOID lpFileInformation
)
686 FILE_NETWORK_OPEN_INFORMATION FileInformation
;
687 OBJECT_ATTRIBUTES ObjectAttributes
;
688 UNICODE_STRING FileName
;
690 WIN32_FILE_ATTRIBUTE_DATA
* FileAttributeData
;
692 TRACE("GetFileAttributesExW(%S) called\n", lpFileName
);
695 if (fInfoLevelId
!= GetFileExInfoStandard
|| lpFileInformation
== NULL
)
697 SetLastError(ERROR_INVALID_PARAMETER
);
701 /* Validate and translate the filename */
702 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
707 WARN ("Invalid path '%S'\n", lpFileName
);
708 SetLastError (ERROR_BAD_PATHNAME
);
712 /* build the object attributes */
713 InitializeObjectAttributes (&ObjectAttributes
,
715 OBJ_CASE_INSENSITIVE
,
719 /* Get file attributes */
720 Status
= NtQueryFullAttributesFile(&ObjectAttributes
,
723 RtlFreeUnicodeString (&FileName
);
724 if (!NT_SUCCESS (Status
))
726 WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status
);
727 BaseSetLastNTError (Status
);
731 FileAttributeData
= (WIN32_FILE_ATTRIBUTE_DATA
*)lpFileInformation
;
732 FileAttributeData
->dwFileAttributes
= FileInformation
.FileAttributes
;
733 FileAttributeData
->ftCreationTime
.dwLowDateTime
= FileInformation
.CreationTime
.u
.LowPart
;
734 FileAttributeData
->ftCreationTime
.dwHighDateTime
= FileInformation
.CreationTime
.u
.HighPart
;
735 FileAttributeData
->ftLastAccessTime
.dwLowDateTime
= FileInformation
.LastAccessTime
.u
.LowPart
;
736 FileAttributeData
->ftLastAccessTime
.dwHighDateTime
= FileInformation
.LastAccessTime
.u
.HighPart
;
737 FileAttributeData
->ftLastWriteTime
.dwLowDateTime
= FileInformation
.LastWriteTime
.u
.LowPart
;
738 FileAttributeData
->ftLastWriteTime
.dwHighDateTime
= FileInformation
.LastWriteTime
.u
.HighPart
;
739 FileAttributeData
->nFileSizeLow
= FileInformation
.EndOfFile
.u
.LowPart
;
740 FileAttributeData
->nFileSizeHigh
= FileInformation
.EndOfFile
.u
.HighPart
;
749 GetFileAttributesExA(LPCSTR lpFileName
,
750 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
751 LPVOID lpFileInformation
)
755 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
758 return GetFileAttributesExW(FileNameW
, fInfoLevelId
, lpFileInformation
);
766 GetFileAttributesA(LPCSTR lpFileName
)
768 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData
;
772 if (!lpFileName
|| !(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
773 return INVALID_FILE_ATTRIBUTES
;
775 ret
= GetFileAttributesExW(FileNameW
, GetFileExInfoStandard
, &FileAttributeData
);
777 return ret
? FileAttributeData
.dwFileAttributes
: INVALID_FILE_ATTRIBUTES
;
785 GetFileAttributesW(LPCWSTR lpFileName
)
787 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData
;
790 TRACE ("GetFileAttributeW(%S) called\n", lpFileName
);
792 Result
= GetFileAttributesExW(lpFileName
, GetFileExInfoStandard
, &FileAttributeData
);
794 return Result
? FileAttributeData
.dwFileAttributes
: INVALID_FILE_ATTRIBUTES
;
802 GetFileAttributesByHandle(IN HANDLE hFile
,
803 OUT LPDWORD dwFileAttributes
,
806 FILE_BASIC_INFORMATION FileBasic
;
807 IO_STATUS_BLOCK IoStatusBlock
;
810 UNREFERENCED_PARAMETER(dwFlags
);
812 if (IsConsoleHandle(hFile
))
814 SetLastError(ERROR_INVALID_HANDLE
);
818 Status
= NtQueryInformationFile(hFile
,
822 FileBasicInformation
);
823 if (NT_SUCCESS(Status
))
825 *dwFileAttributes
= FileBasic
.FileAttributes
;
829 BaseSetLastNTError(Status
);
838 SetFileAttributesByHandle(IN HANDLE hFile
,
839 IN DWORD dwFileAttributes
,
842 FILE_BASIC_INFORMATION FileBasic
;
843 IO_STATUS_BLOCK IoStatusBlock
;
846 UNREFERENCED_PARAMETER(dwFlags
);
848 if (IsConsoleHandle(hFile
))
850 SetLastError(ERROR_INVALID_HANDLE
);
854 Status
= NtQueryInformationFile(hFile
,
858 FileBasicInformation
);
859 if (NT_SUCCESS(Status
))
861 FileBasic
.FileAttributes
= dwFileAttributes
;
863 Status
= NtSetInformationFile(hFile
,
867 FileBasicInformation
);
870 if (!NT_SUCCESS(Status
))
872 BaseSetLastNTError(Status
);
886 DWORD dwFileAttributes
)
890 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
893 return SetFileAttributesW(FileNameW
, dwFileAttributes
);
902 SetFileAttributesW(LPCWSTR lpFileName
,
903 DWORD dwFileAttributes
)
908 UNICODE_STRING NtPathU
;
909 IO_STATUS_BLOCK IoStatusBlock
;
910 RTL_RELATIVE_NAME_U RelativeName
;
911 OBJECT_ATTRIBUTES ObjectAttributes
;
912 FILE_BASIC_INFORMATION FileInformation
;
914 /* Get relative name */
915 if (!RtlDosPathNameToRelativeNtPathName_U(lpFileName
, &NtPathU
, NULL
, &RelativeName
))
917 SetLastError(ERROR_PATH_NOT_FOUND
);
921 /* Save buffer to allow later freeing */
922 PathUBuffer
= NtPathU
.Buffer
;
924 /* If we have relative name (and root dir), use them instead */
925 if (RelativeName
.RelativeName
.Length
!= 0)
927 NtPathU
.Length
= RelativeName
.RelativeName
.Length
;
928 NtPathU
.MaximumLength
= RelativeName
.RelativeName
.MaximumLength
;
929 NtPathU
.Buffer
= RelativeName
.RelativeName
.Buffer
;
933 RelativeName
.ContainingDirectory
= NULL
;
936 /* Prepare the object attribute for opening the file */
937 InitializeObjectAttributes(&ObjectAttributes
, &NtPathU
,
938 OBJ_CASE_INSENSITIVE
,
939 RelativeName
.ContainingDirectory
, NULL
);
941 /* Attempt to open the file, while supporting reparse point */
942 Status
= NtOpenFile(&FileHandle
, FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
943 &ObjectAttributes
, &IoStatusBlock
,
944 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
945 FILE_OPEN_REPARSE_POINT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
);
946 /* If opening failed, check whether it was because of reparse point support */
947 if (!NT_SUCCESS(Status
))
949 /* Nope, just quit */
950 if (Status
!= STATUS_INVALID_PARAMETER
)
952 RtlReleaseRelativeName(&RelativeName
);
953 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer
);
954 BaseSetLastNTError(Status
);
959 /* Yes, retry without */
960 Status
= NtOpenFile(&FileHandle
, FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
961 &ObjectAttributes
, &IoStatusBlock
,
962 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
963 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
);
964 if (!NT_SUCCESS(Status
))
966 RtlReleaseRelativeName(&RelativeName
);
967 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer
);
968 BaseSetLastNTError(Status
);
974 /* We don't need strings anylonger */
975 RtlReleaseRelativeName(&RelativeName
);
976 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer
);
978 /* Zero our structure, we'll only set file attributes */
979 ZeroMemory(&FileInformation
, sizeof(FileInformation
));
980 /* Set the attributes, filtering only allowed attributes, and forcing normal attribute */
981 FileInformation
.FileAttributes
= (dwFileAttributes
& FILE_ATTRIBUTE_VALID_SET_FLAGS
) | FILE_ATTRIBUTE_NORMAL
;
983 /* Finally, set the attributes */
984 Status
= NtSetInformationFile(FileHandle
, &IoStatusBlock
, &FileInformation
,
985 sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
);
989 /* If it failed, set the error and fail */
990 if (!NT_SUCCESS(Status
))
992 BaseSetLastNTError(Status
);
1004 GetFileTime(IN HANDLE hFile
,
1005 OUT LPFILETIME lpCreationTime OPTIONAL
,
1006 OUT LPFILETIME lpLastAccessTime OPTIONAL
,
1007 OUT LPFILETIME lpLastWriteTime OPTIONAL
)
1010 IO_STATUS_BLOCK IoStatusBlock
;
1011 FILE_BASIC_INFORMATION FileBasic
;
1013 if(IsConsoleHandle(hFile
))
1015 BaseSetLastNTError(STATUS_INVALID_HANDLE
);
1019 Status
= NtQueryInformationFile(hFile
,
1022 sizeof(FILE_BASIC_INFORMATION
),
1023 FileBasicInformation
);
1024 if (!NT_SUCCESS(Status
))
1026 BaseSetLastNTError(Status
);
1032 lpCreationTime
->dwLowDateTime
= FileBasic
.CreationTime
.LowPart
;
1033 lpCreationTime
->dwHighDateTime
= FileBasic
.CreationTime
.HighPart
;
1036 if (lpLastAccessTime
)
1038 lpLastAccessTime
->dwLowDateTime
= FileBasic
.LastAccessTime
.LowPart
;
1039 lpLastAccessTime
->dwHighDateTime
= FileBasic
.LastAccessTime
.HighPart
;
1042 if (lpLastWriteTime
)
1044 lpLastWriteTime
->dwLowDateTime
= FileBasic
.LastWriteTime
.LowPart
;
1045 lpLastWriteTime
->dwHighDateTime
= FileBasic
.LastWriteTime
.HighPart
;
1056 SetFileTime(IN HANDLE hFile
,
1057 CONST FILETIME
*lpCreationTime OPTIONAL
,
1058 CONST FILETIME
*lpLastAccessTime OPTIONAL
,
1059 CONST FILETIME
*lpLastWriteTime OPTIONAL
)
1062 IO_STATUS_BLOCK IoStatusBlock
;
1063 FILE_BASIC_INFORMATION FileBasic
;
1065 if(IsConsoleHandle(hFile
))
1067 BaseSetLastNTError(STATUS_INVALID_HANDLE
);
1071 memset(&FileBasic
, 0, sizeof(FILE_BASIC_INFORMATION
));
1075 FileBasic
.CreationTime
.LowPart
= lpCreationTime
->dwLowDateTime
;
1076 FileBasic
.CreationTime
.HighPart
= lpCreationTime
->dwHighDateTime
;
1079 if (lpLastAccessTime
)
1081 FileBasic
.LastAccessTime
.LowPart
= lpLastAccessTime
->dwLowDateTime
;
1082 FileBasic
.LastAccessTime
.HighPart
= lpLastAccessTime
->dwHighDateTime
;
1085 if (lpLastWriteTime
)
1087 FileBasic
.LastWriteTime
.LowPart
= lpLastWriteTime
->dwLowDateTime
;
1088 FileBasic
.LastWriteTime
.HighPart
= lpLastWriteTime
->dwHighDateTime
;
1091 Status
= NtSetInformationFile(hFile
,
1094 sizeof(FILE_BASIC_INFORMATION
),
1095 FileBasicInformation
);
1096 if (!NT_SUCCESS(Status
))
1098 BaseSetLastNTError(Status
);
1107 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1112 SetEndOfFile(HANDLE hFile
)
1114 IO_STATUS_BLOCK IoStatusBlock
;
1115 FILE_END_OF_FILE_INFORMATION EndOfFileInfo
;
1116 FILE_ALLOCATION_INFORMATION FileAllocationInfo
;
1117 FILE_POSITION_INFORMATION FilePosInfo
;
1120 if(IsConsoleHandle(hFile
))
1122 SetLastError(ERROR_INVALID_HANDLE
);
1126 //get current position
1127 Status
= NtQueryInformationFile(
1131 sizeof(FILE_POSITION_INFORMATION
),
1132 FilePositionInformation
1135 if (!NT_SUCCESS(Status
)){
1136 BaseSetLastNTError(Status
);
1140 EndOfFileInfo
.EndOfFile
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1144 This call is not supposed to free up any space after the eof marker
1145 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1146 But...most file systems dispatch both FileEndOfFileInformation
1147 and FileAllocationInformation as they were the same command.
1150 Status
= NtSetInformationFile(
1152 &IoStatusBlock
, //out
1154 sizeof(FILE_END_OF_FILE_INFORMATION
),
1155 FileEndOfFileInformation
1158 if (!NT_SUCCESS(Status
)){
1159 BaseSetLastNTError(Status
);
1163 FileAllocationInfo
.AllocationSize
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1166 Status
= NtSetInformationFile(
1168 &IoStatusBlock
, //out
1169 &FileAllocationInfo
,
1170 sizeof(FILE_ALLOCATION_INFORMATION
),
1171 FileAllocationInformation
1174 if (!NT_SUCCESS(Status
)){
1175 BaseSetLastNTError(Status
);
1191 LONGLONG ValidDataLength
1194 IO_STATUS_BLOCK IoStatusBlock
;
1195 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation
;
1198 ValidDataLengthInformation
.ValidDataLength
.QuadPart
= ValidDataLength
;
1200 Status
= NtSetInformationFile(
1202 &IoStatusBlock
, //out
1203 &ValidDataLengthInformation
,
1204 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION
),
1205 FileValidDataLengthInformation
1208 if (!NT_SUCCESS(Status
)){
1209 BaseSetLastNTError(Status
);