2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/file.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
);
202 SetFilePointer(HANDLE hFile
,
203 LONG lDistanceToMove
,
204 PLONG lpDistanceToMoveHigh
,
207 FILE_POSITION_INFORMATION FilePosition
;
208 FILE_STANDARD_INFORMATION FileStandard
;
210 IO_STATUS_BLOCK IoStatusBlock
;
211 LARGE_INTEGER Distance
;
213 TRACE("SetFilePointer(hFile %p, lDistanceToMove %d, dwMoveMethod %lu)\n",
214 hFile
,lDistanceToMove
,dwMoveMethod
);
216 if(IsConsoleHandle(hFile
))
218 SetLastError(ERROR_INVALID_HANDLE
);
219 return INVALID_SET_FILE_POINTER
;
222 if (lpDistanceToMoveHigh
)
224 Distance
.u
.HighPart
= *lpDistanceToMoveHigh
;
225 Distance
.u
.LowPart
= lDistanceToMove
;
229 Distance
.QuadPart
= lDistanceToMove
;
235 errCode
= NtQueryInformationFile(hFile
,
238 sizeof(FILE_POSITION_INFORMATION
),
239 FilePositionInformation
);
240 FilePosition
.CurrentByteOffset
.QuadPart
+= Distance
.QuadPart
;
241 if (!NT_SUCCESS(errCode
))
243 if (lpDistanceToMoveHigh
!= NULL
)
244 *lpDistanceToMoveHigh
= -1;
245 BaseSetLastNTError(errCode
);
246 return INVALID_SET_FILE_POINTER
;
250 errCode
= NtQueryInformationFile(hFile
,
253 sizeof(FILE_STANDARD_INFORMATION
),
254 FileStandardInformation
);
255 FilePosition
.CurrentByteOffset
.QuadPart
=
256 FileStandard
.EndOfFile
.QuadPart
+ Distance
.QuadPart
;
257 if (!NT_SUCCESS(errCode
))
259 if (lpDistanceToMoveHigh
!= NULL
)
260 *lpDistanceToMoveHigh
= -1;
261 BaseSetLastNTError(errCode
);
262 return INVALID_SET_FILE_POINTER
;
266 FilePosition
.CurrentByteOffset
.QuadPart
= Distance
.QuadPart
;
269 SetLastError(ERROR_INVALID_PARAMETER
);
270 return INVALID_SET_FILE_POINTER
;
273 if(FilePosition
.CurrentByteOffset
.QuadPart
< 0)
275 SetLastError(ERROR_NEGATIVE_SEEK
);
276 return INVALID_SET_FILE_POINTER
;
279 if (lpDistanceToMoveHigh
== NULL
&& FilePosition
.CurrentByteOffset
.HighPart
!= 0)
281 /* If we're moving the pointer outside of the 32 bit boundaries but
282 the application only passed a 32 bit value we need to bail out! */
283 SetLastError(ERROR_INVALID_PARAMETER
);
284 return INVALID_SET_FILE_POINTER
;
287 errCode
= NtSetInformationFile(hFile
,
290 sizeof(FILE_POSITION_INFORMATION
),
291 FilePositionInformation
);
292 if (!NT_SUCCESS(errCode
))
294 if (lpDistanceToMoveHigh
!= NULL
)
295 *lpDistanceToMoveHigh
= -1;
297 BaseSetLastNTError(errCode
);
298 return INVALID_SET_FILE_POINTER
;
301 if (lpDistanceToMoveHigh
!= NULL
)
303 *lpDistanceToMoveHigh
= FilePosition
.CurrentByteOffset
.u
.HighPart
;
306 if (FilePosition
.CurrentByteOffset
.u
.LowPart
== MAXDWORD
)
308 /* The value of -1 is valid here, especially when the new
309 file position is greater than 4 GB. Since NtSetInformationFile
310 succeeded we never set an error code and we explicitly need
311 to clear a previously set error code in this case, which
312 an application will check if INVALID_SET_FILE_POINTER is returned! */
313 SetLastError(ERROR_SUCCESS
);
316 return FilePosition
.CurrentByteOffset
.u
.LowPart
;
325 SetFilePointerEx(HANDLE hFile
,
326 LARGE_INTEGER liDistanceToMove
,
327 PLARGE_INTEGER lpNewFilePointer
,
330 FILE_POSITION_INFORMATION FilePosition
;
331 FILE_STANDARD_INFORMATION FileStandard
;
333 IO_STATUS_BLOCK IoStatusBlock
;
335 if(IsConsoleHandle(hFile
))
337 SetLastError(ERROR_INVALID_HANDLE
);
344 NtQueryInformationFile(hFile
,
347 sizeof(FILE_POSITION_INFORMATION
),
348 FilePositionInformation
);
349 FilePosition
.CurrentByteOffset
.QuadPart
+= liDistanceToMove
.QuadPart
;
352 NtQueryInformationFile(hFile
,
355 sizeof(FILE_STANDARD_INFORMATION
),
356 FileStandardInformation
);
357 FilePosition
.CurrentByteOffset
.QuadPart
=
358 FileStandard
.EndOfFile
.QuadPart
+ liDistanceToMove
.QuadPart
;
361 FilePosition
.CurrentByteOffset
.QuadPart
= liDistanceToMove
.QuadPart
;
364 SetLastError(ERROR_INVALID_PARAMETER
);
368 if(FilePosition
.CurrentByteOffset
.QuadPart
< 0)
370 SetLastError(ERROR_NEGATIVE_SEEK
);
374 errCode
= NtSetInformationFile(hFile
,
377 sizeof(FILE_POSITION_INFORMATION
),
378 FilePositionInformation
);
379 if (!NT_SUCCESS(errCode
))
381 BaseSetLastNTError(errCode
);
385 if (lpNewFilePointer
)
387 *lpNewFilePointer
= FilePosition
.CurrentByteOffset
;
397 GetFileType(HANDLE hFile
)
399 FILE_FS_DEVICE_INFORMATION DeviceInfo
;
400 IO_STATUS_BLOCK StatusBlock
;
403 /* Get real handle */
404 hFile
= TranslateStdHandle(hFile
);
406 /* Check for console handle */
407 if (IsConsoleHandle(hFile
))
409 if (VerifyConsoleIoHandle(hFile
))
410 return FILE_TYPE_CHAR
;
413 Status
= NtQueryVolumeInformationFile(hFile
,
416 sizeof(FILE_FS_DEVICE_INFORMATION
),
417 FileFsDeviceInformation
);
418 if (!NT_SUCCESS(Status
))
420 BaseSetLastNTError(Status
);
421 return FILE_TYPE_UNKNOWN
;
424 switch (DeviceInfo
.DeviceType
)
426 case FILE_DEVICE_CD_ROM
:
427 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
428 case FILE_DEVICE_CONTROLLER
:
429 case FILE_DEVICE_DATALINK
:
430 case FILE_DEVICE_DFS
:
431 case FILE_DEVICE_DISK
:
432 case FILE_DEVICE_DISK_FILE_SYSTEM
:
433 case FILE_DEVICE_VIRTUAL_DISK
:
434 return FILE_TYPE_DISK
;
436 case FILE_DEVICE_KEYBOARD
:
437 case FILE_DEVICE_MOUSE
:
438 case FILE_DEVICE_NULL
:
439 case FILE_DEVICE_PARALLEL_PORT
:
440 case FILE_DEVICE_PRINTER
:
441 case FILE_DEVICE_SERIAL_PORT
:
442 case FILE_DEVICE_SCREEN
:
443 case FILE_DEVICE_SOUND
:
444 case FILE_DEVICE_MODEM
:
445 return FILE_TYPE_CHAR
;
447 case FILE_DEVICE_NAMED_PIPE
:
448 return FILE_TYPE_PIPE
;
451 return FILE_TYPE_UNKNOWN
;
459 GetFileSize(HANDLE hFile
,
460 LPDWORD lpFileSizeHigh
)
463 FILE_STANDARD_INFORMATION FileStandard
;
464 IO_STATUS_BLOCK IoStatusBlock
;
466 errCode
= NtQueryInformationFile(hFile
,
469 sizeof(FILE_STANDARD_INFORMATION
),
470 FileStandardInformation
);
471 if (!NT_SUCCESS(errCode
))
473 BaseSetLastNTError(errCode
);
474 if ( lpFileSizeHigh
== NULL
)
483 if ( lpFileSizeHigh
!= NULL
)
484 *lpFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
486 return FileStandard
.EndOfFile
.u
.LowPart
;
497 PLARGE_INTEGER lpFileSize
501 FILE_STANDARD_INFORMATION FileStandard
;
502 IO_STATUS_BLOCK IoStatusBlock
;
504 errCode
= NtQueryInformationFile(hFile
,
507 sizeof(FILE_STANDARD_INFORMATION
),
508 FileStandardInformation
);
509 if (!NT_SUCCESS(errCode
))
511 BaseSetLastNTError(errCode
);
515 *lpFileSize
= FileStandard
.EndOfFile
;
525 GetCompressedFileSizeA(LPCSTR lpFileName
,
526 LPDWORD lpFileSizeHigh
)
530 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
531 return INVALID_FILE_SIZE
;
533 return GetCompressedFileSizeW(FileNameW
, lpFileSizeHigh
);
541 GetCompressedFileSizeW(LPCWSTR lpFileName
,
542 LPDWORD lpFileSizeHigh
)
544 FILE_COMPRESSION_INFORMATION FileCompression
;
546 IO_STATUS_BLOCK IoStatusBlock
;
549 hFile
= CreateFileW(lpFileName
,
554 FILE_ATTRIBUTE_NORMAL
,
557 if (hFile
== INVALID_HANDLE_VALUE
)
558 return INVALID_FILE_SIZE
;
560 errCode
= NtQueryInformationFile(hFile
,
563 sizeof(FILE_COMPRESSION_INFORMATION
),
564 FileCompressionInformation
);
568 if (!NT_SUCCESS(errCode
))
570 BaseSetLastNTError(errCode
);
571 return INVALID_FILE_SIZE
;
575 *lpFileSizeHigh
= FileCompression
.CompressedFileSize
.u
.HighPart
;
577 SetLastError(NO_ERROR
);
578 return FileCompression
.CompressedFileSize
.u
.LowPart
;
586 GetFileInformationByHandle(HANDLE hFile
,
587 LPBY_HANDLE_FILE_INFORMATION lpFileInformation
)
591 FILE_FS_VOLUME_INFORMATION FileFsVolume
;
596 FILE_BASIC_INFORMATION FileBasic
;
597 FILE_INTERNAL_INFORMATION FileInternal
;
598 FILE_STANDARD_INFORMATION FileStandard
;
600 IO_STATUS_BLOCK IoStatusBlock
;
602 if(IsConsoleHandle(hFile
))
604 SetLastError(ERROR_INVALID_HANDLE
);
608 errCode
= NtQueryInformationFile(hFile
,
611 sizeof(FILE_BASIC_INFORMATION
),
612 FileBasicInformation
);
613 if (!NT_SUCCESS(errCode
))
615 BaseSetLastNTError(errCode
);
619 lpFileInformation
->dwFileAttributes
= (DWORD
)FileBasic
.FileAttributes
;
621 lpFileInformation
->ftCreationTime
.dwHighDateTime
= FileBasic
.CreationTime
.u
.HighPart
;
622 lpFileInformation
->ftCreationTime
.dwLowDateTime
= FileBasic
.CreationTime
.u
.LowPart
;
624 lpFileInformation
->ftLastAccessTime
.dwHighDateTime
= FileBasic
.LastAccessTime
.u
.HighPart
;
625 lpFileInformation
->ftLastAccessTime
.dwLowDateTime
= FileBasic
.LastAccessTime
.u
.LowPart
;
627 lpFileInformation
->ftLastWriteTime
.dwHighDateTime
= FileBasic
.LastWriteTime
.u
.HighPart
;
628 lpFileInformation
->ftLastWriteTime
.dwLowDateTime
= FileBasic
.LastWriteTime
.u
.LowPart
;
630 errCode
= NtQueryInformationFile(hFile
,
633 sizeof(FILE_INTERNAL_INFORMATION
),
634 FileInternalInformation
);
635 if (!NT_SUCCESS(errCode
))
637 BaseSetLastNTError(errCode
);
641 lpFileInformation
->nFileIndexHigh
= FileInternal
.IndexNumber
.u
.HighPart
;
642 lpFileInformation
->nFileIndexLow
= FileInternal
.IndexNumber
.u
.LowPart
;
644 errCode
= NtQueryVolumeInformationFile(hFile
,
647 sizeof(FileFsVolume
),
648 FileFsVolumeInformation
);
649 if (!NT_SUCCESS(errCode
))
651 BaseSetLastNTError(errCode
);
655 lpFileInformation
->dwVolumeSerialNumber
= FileFsVolume
.FileFsVolume
.VolumeSerialNumber
;
657 errCode
= NtQueryInformationFile(hFile
,
660 sizeof(FILE_STANDARD_INFORMATION
),
661 FileStandardInformation
);
662 if (!NT_SUCCESS(errCode
))
664 BaseSetLastNTError(errCode
);
668 lpFileInformation
->nNumberOfLinks
= FileStandard
.NumberOfLinks
;
669 lpFileInformation
->nFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
670 lpFileInformation
->nFileSizeLow
= FileStandard
.EndOfFile
.u
.LowPart
;
680 GetFileAttributesExW(LPCWSTR lpFileName
,
681 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
682 LPVOID lpFileInformation
)
684 FILE_NETWORK_OPEN_INFORMATION FileInformation
;
685 OBJECT_ATTRIBUTES ObjectAttributes
;
686 UNICODE_STRING FileName
;
688 WIN32_FILE_ATTRIBUTE_DATA
* FileAttributeData
;
690 TRACE("GetFileAttributesExW(%S) called\n", lpFileName
);
693 if (fInfoLevelId
!= GetFileExInfoStandard
|| lpFileInformation
== NULL
)
695 SetLastError(ERROR_INVALID_PARAMETER
);
699 /* Validate and translate the filename */
700 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
705 WARN ("Invalid path '%S'\n", lpFileName
);
706 SetLastError (ERROR_BAD_PATHNAME
);
710 /* build the object attributes */
711 InitializeObjectAttributes (&ObjectAttributes
,
713 OBJ_CASE_INSENSITIVE
,
717 /* Get file attributes */
718 Status
= NtQueryFullAttributesFile(&ObjectAttributes
,
721 RtlFreeUnicodeString (&FileName
);
722 if (!NT_SUCCESS (Status
))
724 WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status
);
725 BaseSetLastNTError (Status
);
729 FileAttributeData
= (WIN32_FILE_ATTRIBUTE_DATA
*)lpFileInformation
;
730 FileAttributeData
->dwFileAttributes
= FileInformation
.FileAttributes
;
731 FileAttributeData
->ftCreationTime
.dwLowDateTime
= FileInformation
.CreationTime
.u
.LowPart
;
732 FileAttributeData
->ftCreationTime
.dwHighDateTime
= FileInformation
.CreationTime
.u
.HighPart
;
733 FileAttributeData
->ftLastAccessTime
.dwLowDateTime
= FileInformation
.LastAccessTime
.u
.LowPart
;
734 FileAttributeData
->ftLastAccessTime
.dwHighDateTime
= FileInformation
.LastAccessTime
.u
.HighPart
;
735 FileAttributeData
->ftLastWriteTime
.dwLowDateTime
= FileInformation
.LastWriteTime
.u
.LowPart
;
736 FileAttributeData
->ftLastWriteTime
.dwHighDateTime
= FileInformation
.LastWriteTime
.u
.HighPart
;
737 FileAttributeData
->nFileSizeLow
= FileInformation
.EndOfFile
.u
.LowPart
;
738 FileAttributeData
->nFileSizeHigh
= FileInformation
.EndOfFile
.u
.HighPart
;
747 GetFileAttributesExA(LPCSTR lpFileName
,
748 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
749 LPVOID lpFileInformation
)
753 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
756 return GetFileAttributesExW(FileNameW
, fInfoLevelId
, lpFileInformation
);
764 GetFileAttributesA(LPCSTR lpFileName
)
766 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData
;
770 if (!lpFileName
|| !(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
771 return INVALID_FILE_ATTRIBUTES
;
773 ret
= GetFileAttributesExW(FileNameW
, GetFileExInfoStandard
, &FileAttributeData
);
775 return ret
? FileAttributeData
.dwFileAttributes
: INVALID_FILE_ATTRIBUTES
;
783 GetFileAttributesW(LPCWSTR lpFileName
)
785 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData
;
788 TRACE ("GetFileAttributeW(%S) called\n", lpFileName
);
790 Result
= GetFileAttributesExW(lpFileName
, GetFileExInfoStandard
, &FileAttributeData
);
792 return Result
? FileAttributeData
.dwFileAttributes
: INVALID_FILE_ATTRIBUTES
;
800 GetFileAttributesByHandle(IN HANDLE hFile
,
801 OUT LPDWORD dwFileAttributes
,
804 FILE_BASIC_INFORMATION FileBasic
;
805 IO_STATUS_BLOCK IoStatusBlock
;
808 UNREFERENCED_PARAMETER(dwFlags
);
810 if (IsConsoleHandle(hFile
))
812 SetLastError(ERROR_INVALID_HANDLE
);
816 Status
= NtQueryInformationFile(hFile
,
820 FileBasicInformation
);
821 if (NT_SUCCESS(Status
))
823 *dwFileAttributes
= FileBasic
.FileAttributes
;
827 BaseSetLastNTError(Status
);
836 SetFileAttributesByHandle(IN HANDLE hFile
,
837 IN DWORD dwFileAttributes
,
840 FILE_BASIC_INFORMATION FileBasic
;
841 IO_STATUS_BLOCK IoStatusBlock
;
844 UNREFERENCED_PARAMETER(dwFlags
);
846 if (IsConsoleHandle(hFile
))
848 SetLastError(ERROR_INVALID_HANDLE
);
852 Status
= NtQueryInformationFile(hFile
,
856 FileBasicInformation
);
857 if (NT_SUCCESS(Status
))
859 FileBasic
.FileAttributes
= dwFileAttributes
;
861 Status
= NtSetInformationFile(hFile
,
865 FileBasicInformation
);
868 if (!NT_SUCCESS(Status
))
870 BaseSetLastNTError(Status
);
884 DWORD dwFileAttributes
)
888 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
891 return SetFileAttributesW(FileNameW
, dwFileAttributes
);
899 SetFileAttributesW(LPCWSTR lpFileName
,
900 DWORD dwFileAttributes
)
902 FILE_BASIC_INFORMATION FileInformation
;
903 OBJECT_ATTRIBUTES ObjectAttributes
;
904 IO_STATUS_BLOCK IoStatusBlock
;
905 UNICODE_STRING FileName
;
909 TRACE ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName
, dwFileAttributes
);
911 /* Validate and translate the filename */
912 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
917 WARN ("Invalid path\n");
918 SetLastError (ERROR_BAD_PATHNAME
);
921 TRACE ("FileName: \'%wZ\'\n", &FileName
);
923 /* build the object attributes */
924 InitializeObjectAttributes (&ObjectAttributes
,
926 OBJ_CASE_INSENSITIVE
,
931 Status
= NtOpenFile (&FileHandle
,
932 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
,
935 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
936 FILE_SYNCHRONOUS_IO_NONALERT
);
937 RtlFreeUnicodeString (&FileName
);
938 if (!NT_SUCCESS (Status
))
940 WARN ("NtOpenFile() failed (Status %lx)\n", Status
);
941 BaseSetLastNTError (Status
);
945 Status
= NtQueryInformationFile(FileHandle
,
948 sizeof(FILE_BASIC_INFORMATION
),
949 FileBasicInformation
);
950 if (!NT_SUCCESS(Status
))
952 WARN ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status
);
953 NtClose (FileHandle
);
954 BaseSetLastNTError (Status
);
958 FileInformation
.FileAttributes
= dwFileAttributes
;
959 Status
= NtSetInformationFile(FileHandle
,
962 sizeof(FILE_BASIC_INFORMATION
),
963 FileBasicInformation
);
964 NtClose (FileHandle
);
965 if (!NT_SUCCESS(Status
))
967 WARN ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status
);
968 BaseSetLastNTError (Status
);
979 GetFileTime(IN HANDLE hFile
,
980 OUT LPFILETIME lpCreationTime OPTIONAL
,
981 OUT LPFILETIME lpLastAccessTime OPTIONAL
,
982 OUT LPFILETIME lpLastWriteTime OPTIONAL
)
985 IO_STATUS_BLOCK IoStatusBlock
;
986 FILE_BASIC_INFORMATION FileBasic
;
988 if(IsConsoleHandle(hFile
))
990 BaseSetLastNTError(STATUS_INVALID_HANDLE
);
994 Status
= NtQueryInformationFile(hFile
,
997 sizeof(FILE_BASIC_INFORMATION
),
998 FileBasicInformation
);
999 if (!NT_SUCCESS(Status
))
1001 BaseSetLastNTError(Status
);
1007 lpCreationTime
->dwLowDateTime
= FileBasic
.CreationTime
.LowPart
;
1008 lpCreationTime
->dwHighDateTime
= FileBasic
.CreationTime
.HighPart
;
1011 if (lpLastAccessTime
)
1013 lpLastAccessTime
->dwLowDateTime
= FileBasic
.LastAccessTime
.LowPart
;
1014 lpLastAccessTime
->dwHighDateTime
= FileBasic
.LastAccessTime
.HighPart
;
1017 if (lpLastWriteTime
)
1019 lpLastWriteTime
->dwLowDateTime
= FileBasic
.LastWriteTime
.LowPart
;
1020 lpLastWriteTime
->dwHighDateTime
= FileBasic
.LastWriteTime
.HighPart
;
1031 SetFileTime(IN HANDLE hFile
,
1032 CONST FILETIME
*lpCreationTime OPTIONAL
,
1033 CONST FILETIME
*lpLastAccessTime OPTIONAL
,
1034 CONST FILETIME
*lpLastWriteTime OPTIONAL
)
1037 IO_STATUS_BLOCK IoStatusBlock
;
1038 FILE_BASIC_INFORMATION FileBasic
;
1040 if(IsConsoleHandle(hFile
))
1042 BaseSetLastNTError(STATUS_INVALID_HANDLE
);
1046 memset(&FileBasic
, 0, sizeof(FILE_BASIC_INFORMATION
));
1050 FileBasic
.CreationTime
.LowPart
= lpCreationTime
->dwLowDateTime
;
1051 FileBasic
.CreationTime
.HighPart
= lpCreationTime
->dwHighDateTime
;
1054 if (lpLastAccessTime
)
1056 FileBasic
.LastAccessTime
.LowPart
= lpLastAccessTime
->dwLowDateTime
;
1057 FileBasic
.LastAccessTime
.HighPart
= lpLastAccessTime
->dwHighDateTime
;
1060 if (lpLastWriteTime
)
1062 FileBasic
.LastWriteTime
.LowPart
= lpLastWriteTime
->dwLowDateTime
;
1063 FileBasic
.LastWriteTime
.HighPart
= lpLastWriteTime
->dwHighDateTime
;
1066 Status
= NtSetInformationFile(hFile
,
1069 sizeof(FILE_BASIC_INFORMATION
),
1070 FileBasicInformation
);
1071 if (!NT_SUCCESS(Status
))
1073 BaseSetLastNTError(Status
);
1082 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1087 SetEndOfFile(HANDLE hFile
)
1089 IO_STATUS_BLOCK IoStatusBlock
;
1090 FILE_END_OF_FILE_INFORMATION EndOfFileInfo
;
1091 FILE_ALLOCATION_INFORMATION FileAllocationInfo
;
1092 FILE_POSITION_INFORMATION FilePosInfo
;
1095 if(IsConsoleHandle(hFile
))
1097 SetLastError(ERROR_INVALID_HANDLE
);
1101 //get current position
1102 Status
= NtQueryInformationFile(
1106 sizeof(FILE_POSITION_INFORMATION
),
1107 FilePositionInformation
1110 if (!NT_SUCCESS(Status
)){
1111 BaseSetLastNTError(Status
);
1115 EndOfFileInfo
.EndOfFile
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1119 This call is not supposed to free up any space after the eof marker
1120 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1121 But...most file systems dispatch both FileEndOfFileInformation
1122 and FileAllocationInformation as they were the same command.
1125 Status
= NtSetInformationFile(
1127 &IoStatusBlock
, //out
1129 sizeof(FILE_END_OF_FILE_INFORMATION
),
1130 FileEndOfFileInformation
1133 if (!NT_SUCCESS(Status
)){
1134 BaseSetLastNTError(Status
);
1138 FileAllocationInfo
.AllocationSize
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1141 Status
= NtSetInformationFile(
1143 &IoStatusBlock
, //out
1144 &FileAllocationInfo
,
1145 sizeof(FILE_ALLOCATION_INFORMATION
),
1146 FileAllocationInformation
1149 if (!NT_SUCCESS(Status
)){
1150 BaseSetLastNTError(Status
);
1166 LONGLONG ValidDataLength
1169 IO_STATUS_BLOCK IoStatusBlock
;
1170 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation
;
1173 ValidDataLengthInformation
.ValidDataLength
.QuadPart
= ValidDataLength
;
1175 Status
= NtSetInformationFile(
1177 &IoStatusBlock
, //out
1178 &ValidDataLengthInformation
,
1179 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION
),
1180 FileValidDataLengthInformation
1183 if (!NT_SUCCESS(Status
)){
1184 BaseSetLastNTError(Status
);