3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/file.c
6 * PURPOSE: Directory functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
13 /* INCLUDES *****************************************************************/
18 DEBUG_CHANNEL(kernel32file
);
20 /* GLOBALS ******************************************************************/
22 BOOL bIsFileApiAnsi
= TRUE
; // set the file api to ansi or oem
24 /* FUNCTIONS ****************************************************************/
29 FilenameA2W(LPCSTR NameA
, BOOL alloc
)
33 PUNICODE_STRING pstrW
;
36 //ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
37 ASSERT(NtCurrentTeb()->StaticUnicodeString
.MaximumLength
== sizeof(NtCurrentTeb()->StaticUnicodeBuffer
));
39 RtlInitAnsiString(&str
, NameA
);
40 pstrW
= alloc
? &strW
: &NtCurrentTeb()->StaticUnicodeString
;
43 Status
= RtlAnsiStringToUnicodeString( pstrW
, &str
, (BOOLEAN
)alloc
);
45 Status
= RtlOemStringToUnicodeString( pstrW
, &str
, (BOOLEAN
)alloc
);
47 if (NT_SUCCESS(Status
))
50 if (Status
== STATUS_BUFFER_OVERFLOW
)
51 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
53 SetLastErrorByStatus(Status
);
60 No copy/conversion is done if the dest. buffer is too small.
63 Success: number of TCHARS copied into dest. buffer NOT including nullterm
64 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
67 FilenameU2A_FitOrFail(
69 INT destLen
, /* buffer size in TCHARS incl. nullchar */
70 PUNICODE_STRING SourceU
75 /* destLen should never exceed MAX_PATH */
76 if (destLen
> MAX_PATH
) destLen
= MAX_PATH
;
78 ret
= bIsFileApiAnsi
? RtlUnicodeStringToAnsiSize(SourceU
) : RtlUnicodeStringToOemSize(SourceU
);
79 /* ret incl. nullchar */
81 if (DestA
&& (INT
)ret
<= destLen
)
86 str
.MaximumLength
= (USHORT
)destLen
;
90 RtlUnicodeStringToAnsiString(&str
, SourceU
, FALSE
);
92 RtlUnicodeStringToOemString(&str
, SourceU
, FALSE
);
94 ret
= str
.Length
; /* SUCCESS: length without terminating 0 */
102 No copy/conversion is done if the dest. buffer is too small.
105 Success: number of TCHARS copied into dest. buffer NOT including nullterm
106 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
109 FilenameW2A_FitOrFail(
111 INT destLen
, /* buffer size in TCHARS incl. nullchar */
113 INT sourceLen
/* buffer size in TCHARS incl. nullchar */
118 if (sourceLen
< 0) sourceLen
= wcslen(SourceW
) + 1;
120 strW
.Buffer
= (PWCHAR
)SourceW
;
121 strW
.MaximumLength
= sourceLen
* sizeof(WCHAR
);
122 strW
.Length
= strW
.MaximumLength
- sizeof(WCHAR
);
124 return FilenameU2A_FitOrFail(DestA
, destLen
, &strW
);
129 Return: num. TCHARS copied into dest including nullterm
134 INT destlen
, /* buffer size in TCHARS incl. nullchar */
136 INT srclen
/* buffer size in TCHARS incl. nullchar */
141 if (srclen
< 0) srclen
= strlen( src
) + 1;
144 RtlMultiByteToUnicodeN( dest
, destlen
* sizeof(WCHAR
), &ret
, (LPSTR
)src
, srclen
);
146 RtlOemToUnicodeN( dest
, destlen
* sizeof(WCHAR
), &ret
, (LPSTR
)src
, srclen
);
148 if (ret
) dest
[(ret
/sizeof(WCHAR
))-1]=0;
150 return ret
/sizeof(WCHAR
);
154 Return: num. TCHARS copied into dest including nullterm
159 INT destlen
, /* buffer size in TCHARS incl. nullchar */
161 INT srclen
/* buffer size in TCHARS incl. nullchar */
166 if (srclen
< 0) srclen
= wcslen( src
) + 1;
169 RtlUnicodeToMultiByteN( dest
, destlen
, &ret
, (LPWSTR
) src
, srclen
* sizeof(WCHAR
));
171 RtlUnicodeToOemN( dest
, destlen
, &ret
, (LPWSTR
) src
, srclen
* sizeof(WCHAR
) );
173 if (ret
) dest
[ret
-1]=0;
184 SetFileApisToOEM(VOID
)
186 /* Set the correct Base Api */
187 Basep8BitStringToUnicodeString
= (PRTL_CONVERT_STRING
)RtlOemStringToUnicodeString
;
189 /* FIXME: Old, deprecated way */
190 bIsFileApiAnsi
= FALSE
;
199 SetFileApisToANSI(VOID
)
201 /* Set the correct Base Api */
202 Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
204 /* FIXME: Old, deprecated way */
205 bIsFileApiAnsi
= TRUE
;
213 AreFileApisANSI(VOID
)
215 return bIsFileApiAnsi
;
223 OpenFile(LPCSTR lpFileName
,
224 LPOFSTRUCT lpReOpenBuff
,
227 OBJECT_ATTRIBUTES ObjectAttributes
;
228 IO_STATUS_BLOCK IoStatusBlock
;
229 UNICODE_STRING FileNameString
;
230 UNICODE_STRING FileNameU
;
231 ANSI_STRING FileName
;
232 WCHAR PathNameW
[MAX_PATH
];
233 HANDLE FileHandle
= NULL
;
238 TRACE("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName
, lpReOpenBuff
, uStyle
);
240 if (lpReOpenBuff
== NULL
)
245 lpReOpenBuff
->nErrCode
= 0;
247 if (uStyle
& OF_REOPEN
) lpFileName
= lpReOpenBuff
->szPathName
;
254 if (!GetFullPathNameA(lpFileName
,
255 sizeof(lpReOpenBuff
->szPathName
),
256 lpReOpenBuff
->szPathName
,
259 lpReOpenBuff
->nErrCode
= GetLastError();
263 if (uStyle
& OF_PARSE
)
265 lpReOpenBuff
->fFixedDisk
= (GetDriveTypeA(lpReOpenBuff
->szPathName
) != DRIVE_REMOVABLE
);
266 TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName
, lpReOpenBuff
->szPathName
);
270 if ((uStyle
& OF_EXIST
) && !(uStyle
& OF_CREATE
))
272 DWORD dwAttributes
= GetFileAttributesA(lpReOpenBuff
->szPathName
);
274 switch (dwAttributes
)
276 case 0xFFFFFFFF: /* File does not exist */
277 SetLastError(ERROR_FILE_NOT_FOUND
);
278 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_FILE_NOT_FOUND
;
281 case FILE_ATTRIBUTE_DIRECTORY
:
282 SetLastError(ERROR_ACCESS_DENIED
);
283 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_ACCESS_DENIED
;
287 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
291 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
292 if ((uStyle
& OF_CREATE
) == OF_CREATE
)
295 switch (uStyle
& 0x70)
297 case OF_SHARE_EXCLUSIVE
: Sharing
= 0; break;
298 case OF_SHARE_DENY_WRITE
: Sharing
= FILE_SHARE_READ
; break;
299 case OF_SHARE_DENY_READ
: Sharing
= FILE_SHARE_WRITE
; break;
300 case OF_SHARE_DENY_NONE
:
301 case OF_SHARE_COMPAT
:
303 Sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
305 return (HFILE
) CreateFileA (lpFileName
,
306 GENERIC_READ
| GENERIC_WRITE
,
310 FILE_ATTRIBUTE_NORMAL
,
314 RtlInitAnsiString (&FileName
, (LPSTR
)lpFileName
);
316 /* convert ansi (or oem) string to unicode */
318 RtlAnsiStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
320 RtlOemStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
322 Len
= SearchPathW (NULL
,
329 RtlFreeUnicodeString(&FileNameU
);
331 if (Len
== 0 || Len
> OFS_MAXPATHNAME
)
333 lpReOpenBuff
->nErrCode
= GetLastError();
334 return (HFILE
)INVALID_HANDLE_VALUE
;
337 if (uStyle
& OF_DELETE
)
339 if (!DeleteFileW(PathNameW
))
341 lpReOpenBuff
->nErrCode
= GetLastError();
344 TRACE("(%s): OF_DELETE return = OK\n", lpFileName
);
348 FileName
.Buffer
= lpReOpenBuff
->szPathName
;
350 FileName
.MaximumLength
= OFS_MAXPATHNAME
;
352 RtlInitUnicodeString(&FileNameU
, PathNameW
);
354 /* convert unicode string to ansi (or oem) */
356 RtlUnicodeStringToAnsiString (&FileName
, &FileNameU
, FALSE
);
358 RtlUnicodeStringToOemString (&FileName
, &FileNameU
, FALSE
);
360 if (!RtlDosPathNameToNtPathName_U (PathNameW
,
365 return (HFILE
)INVALID_HANDLE_VALUE
;
369 // FILE_NO_INTERMEDIATE_BUFFERING
371 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
372 ObjectAttributes
.RootDirectory
= NULL
;
373 ObjectAttributes
.ObjectName
= &FileNameString
;
374 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
375 ObjectAttributes
.SecurityDescriptor
= NULL
;
376 ObjectAttributes
.SecurityQualityOfService
= NULL
;
378 errCode
= NtOpenFile (&FileHandle
,
379 GENERIC_READ
|SYNCHRONIZE
,
383 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
385 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString
.Buffer
);
387 lpReOpenBuff
->nErrCode
= RtlNtStatusToDosError(errCode
);
389 if (!NT_SUCCESS(errCode
))
391 SetLastErrorByStatus (errCode
);
392 return (HFILE
)INVALID_HANDLE_VALUE
;
395 if (uStyle
& OF_EXIST
)
401 return (HFILE
)FileHandle
;
409 FlushFileBuffers(IN HANDLE hFile
)
412 IO_STATUS_BLOCK IoStatusBlock
;
414 hFile
= TranslateStdHandle(hFile
);
416 if (IsConsoleHandle(hFile
))
418 return FlushConsoleInputBuffer(hFile
);
421 Status
= NtFlushBuffersFile(hFile
,
423 if (!NT_SUCCESS(Status
))
425 BaseSetLastNTError(Status
);
436 SetFilePointer(HANDLE hFile
,
437 LONG lDistanceToMove
,
438 PLONG lpDistanceToMoveHigh
,
441 FILE_POSITION_INFORMATION FilePosition
;
442 FILE_STANDARD_INFORMATION FileStandard
;
444 IO_STATUS_BLOCK IoStatusBlock
;
445 LARGE_INTEGER Distance
;
447 TRACE("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
448 hFile
,lDistanceToMove
,dwMoveMethod
);
450 if(IsConsoleHandle(hFile
))
452 SetLastError(ERROR_INVALID_HANDLE
);
453 return INVALID_SET_FILE_POINTER
;
456 if (lpDistanceToMoveHigh
)
458 Distance
.u
.HighPart
= *lpDistanceToMoveHigh
;
459 Distance
.u
.LowPart
= lDistanceToMove
;
463 Distance
.QuadPart
= lDistanceToMove
;
469 errCode
= NtQueryInformationFile(hFile
,
472 sizeof(FILE_POSITION_INFORMATION
),
473 FilePositionInformation
);
474 FilePosition
.CurrentByteOffset
.QuadPart
+= Distance
.QuadPart
;
475 if (!NT_SUCCESS(errCode
))
477 if (lpDistanceToMoveHigh
!= NULL
)
478 *lpDistanceToMoveHigh
= -1;
479 SetLastErrorByStatus(errCode
);
480 return INVALID_SET_FILE_POINTER
;
484 errCode
= NtQueryInformationFile(hFile
,
487 sizeof(FILE_STANDARD_INFORMATION
),
488 FileStandardInformation
);
489 FilePosition
.CurrentByteOffset
.QuadPart
=
490 FileStandard
.EndOfFile
.QuadPart
+ Distance
.QuadPart
;
491 if (!NT_SUCCESS(errCode
))
493 if (lpDistanceToMoveHigh
!= NULL
)
494 *lpDistanceToMoveHigh
= -1;
495 SetLastErrorByStatus(errCode
);
496 return INVALID_SET_FILE_POINTER
;
500 FilePosition
.CurrentByteOffset
.QuadPart
= Distance
.QuadPart
;
503 SetLastError(ERROR_INVALID_PARAMETER
);
504 return INVALID_SET_FILE_POINTER
;
507 if(FilePosition
.CurrentByteOffset
.QuadPart
< 0)
509 SetLastError(ERROR_NEGATIVE_SEEK
);
510 return INVALID_SET_FILE_POINTER
;
513 if (lpDistanceToMoveHigh
== NULL
&& FilePosition
.CurrentByteOffset
.HighPart
!= 0)
515 /* If we're moving the pointer outside of the 32 bit boundaries but
516 the application only passed a 32 bit value we need to bail out! */
517 SetLastError(ERROR_INVALID_PARAMETER
);
518 return INVALID_SET_FILE_POINTER
;
521 errCode
= NtSetInformationFile(hFile
,
524 sizeof(FILE_POSITION_INFORMATION
),
525 FilePositionInformation
);
526 if (!NT_SUCCESS(errCode
))
528 if (lpDistanceToMoveHigh
!= NULL
)
529 *lpDistanceToMoveHigh
= -1;
531 SetLastErrorByStatus(errCode
);
532 return INVALID_SET_FILE_POINTER
;
535 if (lpDistanceToMoveHigh
!= NULL
)
537 *lpDistanceToMoveHigh
= FilePosition
.CurrentByteOffset
.u
.HighPart
;
540 if (FilePosition
.CurrentByteOffset
.u
.LowPart
== MAXDWORD
)
542 /* The value of -1 is valid here, especially when the new
543 file position is greater than 4 GB. Since NtSetInformationFile
544 succeeded we never set an error code and we explicitly need
545 to clear a previously set error code in this case, which
546 an application will check if INVALID_SET_FILE_POINTER is returned! */
547 SetLastError(ERROR_SUCCESS
);
550 return FilePosition
.CurrentByteOffset
.u
.LowPart
;
559 SetFilePointerEx(HANDLE hFile
,
560 LARGE_INTEGER liDistanceToMove
,
561 PLARGE_INTEGER lpNewFilePointer
,
564 FILE_POSITION_INFORMATION FilePosition
;
565 FILE_STANDARD_INFORMATION FileStandard
;
567 IO_STATUS_BLOCK IoStatusBlock
;
569 if(IsConsoleHandle(hFile
))
571 SetLastError(ERROR_INVALID_HANDLE
);
578 NtQueryInformationFile(hFile
,
581 sizeof(FILE_POSITION_INFORMATION
),
582 FilePositionInformation
);
583 FilePosition
.CurrentByteOffset
.QuadPart
+= liDistanceToMove
.QuadPart
;
586 NtQueryInformationFile(hFile
,
589 sizeof(FILE_STANDARD_INFORMATION
),
590 FileStandardInformation
);
591 FilePosition
.CurrentByteOffset
.QuadPart
=
592 FileStandard
.EndOfFile
.QuadPart
+ liDistanceToMove
.QuadPart
;
595 FilePosition
.CurrentByteOffset
.QuadPart
= liDistanceToMove
.QuadPart
;
598 SetLastError(ERROR_INVALID_PARAMETER
);
602 if(FilePosition
.CurrentByteOffset
.QuadPart
< 0)
604 SetLastError(ERROR_NEGATIVE_SEEK
);
608 errCode
= NtSetInformationFile(hFile
,
611 sizeof(FILE_POSITION_INFORMATION
),
612 FilePositionInformation
);
613 if (!NT_SUCCESS(errCode
))
615 SetLastErrorByStatus(errCode
);
619 if (lpNewFilePointer
)
621 *lpNewFilePointer
= FilePosition
.CurrentByteOffset
;
631 GetFileType(HANDLE hFile
)
633 FILE_FS_DEVICE_INFORMATION DeviceInfo
;
634 IO_STATUS_BLOCK StatusBlock
;
637 /* Get real handle */
638 hFile
= TranslateStdHandle(hFile
);
640 /* Check for console handle */
641 if (IsConsoleHandle(hFile
))
643 if (VerifyConsoleIoHandle(hFile
))
644 return FILE_TYPE_CHAR
;
647 Status
= NtQueryVolumeInformationFile(hFile
,
650 sizeof(FILE_FS_DEVICE_INFORMATION
),
651 FileFsDeviceInformation
);
652 if (!NT_SUCCESS(Status
))
654 SetLastErrorByStatus(Status
);
655 return FILE_TYPE_UNKNOWN
;
658 switch (DeviceInfo
.DeviceType
)
660 case FILE_DEVICE_CD_ROM
:
661 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
662 case FILE_DEVICE_CONTROLLER
:
663 case FILE_DEVICE_DATALINK
:
664 case FILE_DEVICE_DFS
:
665 case FILE_DEVICE_DISK
:
666 case FILE_DEVICE_DISK_FILE_SYSTEM
:
667 case FILE_DEVICE_VIRTUAL_DISK
:
668 return FILE_TYPE_DISK
;
670 case FILE_DEVICE_KEYBOARD
:
671 case FILE_DEVICE_MOUSE
:
672 case FILE_DEVICE_NULL
:
673 case FILE_DEVICE_PARALLEL_PORT
:
674 case FILE_DEVICE_PRINTER
:
675 case FILE_DEVICE_SERIAL_PORT
:
676 case FILE_DEVICE_SCREEN
:
677 case FILE_DEVICE_SOUND
:
678 case FILE_DEVICE_MODEM
:
679 return FILE_TYPE_CHAR
;
681 case FILE_DEVICE_NAMED_PIPE
:
682 return FILE_TYPE_PIPE
;
685 return FILE_TYPE_UNKNOWN
;
693 GetFileSize(HANDLE hFile
,
694 LPDWORD lpFileSizeHigh
)
697 FILE_STANDARD_INFORMATION FileStandard
;
698 IO_STATUS_BLOCK IoStatusBlock
;
700 errCode
= NtQueryInformationFile(hFile
,
703 sizeof(FILE_STANDARD_INFORMATION
),
704 FileStandardInformation
);
705 if (!NT_SUCCESS(errCode
))
707 SetLastErrorByStatus(errCode
);
708 if ( lpFileSizeHigh
== NULL
)
717 if ( lpFileSizeHigh
!= NULL
)
718 *lpFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
720 return FileStandard
.EndOfFile
.u
.LowPart
;
731 PLARGE_INTEGER lpFileSize
735 FILE_STANDARD_INFORMATION FileStandard
;
736 IO_STATUS_BLOCK IoStatusBlock
;
738 errCode
= NtQueryInformationFile(hFile
,
741 sizeof(FILE_STANDARD_INFORMATION
),
742 FileStandardInformation
);
743 if (!NT_SUCCESS(errCode
))
745 SetLastErrorByStatus(errCode
);
749 *lpFileSize
= FileStandard
.EndOfFile
;
759 GetCompressedFileSizeA(LPCSTR lpFileName
,
760 LPDWORD lpFileSizeHigh
)
764 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
765 return INVALID_FILE_SIZE
;
767 return GetCompressedFileSizeW(FileNameW
, lpFileSizeHigh
);
775 GetCompressedFileSizeW(LPCWSTR lpFileName
,
776 LPDWORD lpFileSizeHigh
)
778 FILE_COMPRESSION_INFORMATION FileCompression
;
780 IO_STATUS_BLOCK IoStatusBlock
;
783 hFile
= CreateFileW(lpFileName
,
788 FILE_ATTRIBUTE_NORMAL
,
791 if (hFile
== INVALID_HANDLE_VALUE
)
792 return INVALID_FILE_SIZE
;
794 errCode
= NtQueryInformationFile(hFile
,
797 sizeof(FILE_COMPRESSION_INFORMATION
),
798 FileCompressionInformation
);
802 if (!NT_SUCCESS(errCode
))
804 SetLastErrorByStatus(errCode
);
805 return INVALID_FILE_SIZE
;
809 *lpFileSizeHigh
= FileCompression
.CompressedFileSize
.u
.HighPart
;
811 SetLastError(NO_ERROR
);
812 return FileCompression
.CompressedFileSize
.u
.LowPart
;
820 GetFileInformationByHandle(HANDLE hFile
,
821 LPBY_HANDLE_FILE_INFORMATION lpFileInformation
)
825 FILE_FS_VOLUME_INFORMATION FileFsVolume
;
830 FILE_BASIC_INFORMATION FileBasic
;
831 FILE_INTERNAL_INFORMATION FileInternal
;
832 FILE_STANDARD_INFORMATION FileStandard
;
834 IO_STATUS_BLOCK IoStatusBlock
;
836 if(IsConsoleHandle(hFile
))
838 SetLastError(ERROR_INVALID_HANDLE
);
842 errCode
= NtQueryInformationFile(hFile
,
845 sizeof(FILE_BASIC_INFORMATION
),
846 FileBasicInformation
);
847 if (!NT_SUCCESS(errCode
))
849 SetLastErrorByStatus(errCode
);
853 lpFileInformation
->dwFileAttributes
= (DWORD
)FileBasic
.FileAttributes
;
855 lpFileInformation
->ftCreationTime
.dwHighDateTime
= FileBasic
.CreationTime
.u
.HighPart
;
856 lpFileInformation
->ftCreationTime
.dwLowDateTime
= FileBasic
.CreationTime
.u
.LowPart
;
858 lpFileInformation
->ftLastAccessTime
.dwHighDateTime
= FileBasic
.LastAccessTime
.u
.HighPart
;
859 lpFileInformation
->ftLastAccessTime
.dwLowDateTime
= FileBasic
.LastAccessTime
.u
.LowPart
;
861 lpFileInformation
->ftLastWriteTime
.dwHighDateTime
= FileBasic
.LastWriteTime
.u
.HighPart
;
862 lpFileInformation
->ftLastWriteTime
.dwLowDateTime
= FileBasic
.LastWriteTime
.u
.LowPart
;
864 errCode
= NtQueryInformationFile(hFile
,
867 sizeof(FILE_INTERNAL_INFORMATION
),
868 FileInternalInformation
);
869 if (!NT_SUCCESS(errCode
))
871 SetLastErrorByStatus(errCode
);
875 lpFileInformation
->nFileIndexHigh
= FileInternal
.IndexNumber
.u
.HighPart
;
876 lpFileInformation
->nFileIndexLow
= FileInternal
.IndexNumber
.u
.LowPart
;
878 errCode
= NtQueryVolumeInformationFile(hFile
,
881 sizeof(FileFsVolume
),
882 FileFsVolumeInformation
);
883 if (!NT_SUCCESS(errCode
))
885 SetLastErrorByStatus(errCode
);
889 lpFileInformation
->dwVolumeSerialNumber
= FileFsVolume
.FileFsVolume
.VolumeSerialNumber
;
891 errCode
= NtQueryInformationFile(hFile
,
894 sizeof(FILE_STANDARD_INFORMATION
),
895 FileStandardInformation
);
896 if (!NT_SUCCESS(errCode
))
898 SetLastErrorByStatus(errCode
);
902 lpFileInformation
->nNumberOfLinks
= FileStandard
.NumberOfLinks
;
903 lpFileInformation
->nFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
904 lpFileInformation
->nFileSizeLow
= FileStandard
.EndOfFile
.u
.LowPart
;
914 GetFileAttributesExW(LPCWSTR lpFileName
,
915 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
916 LPVOID lpFileInformation
)
918 FILE_NETWORK_OPEN_INFORMATION FileInformation
;
919 OBJECT_ATTRIBUTES ObjectAttributes
;
920 UNICODE_STRING FileName
;
922 WIN32_FILE_ATTRIBUTE_DATA
* FileAttributeData
;
924 TRACE("GetFileAttributesExW(%S) called\n", lpFileName
);
927 if (fInfoLevelId
!= GetFileExInfoStandard
|| lpFileInformation
== NULL
)
929 SetLastError(ERROR_INVALID_PARAMETER
);
933 /* Validate and translate the filename */
934 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
939 WARN ("Invalid path '%S'\n", lpFileName
);
940 SetLastError (ERROR_BAD_PATHNAME
);
944 /* build the object attributes */
945 InitializeObjectAttributes (&ObjectAttributes
,
947 OBJ_CASE_INSENSITIVE
,
951 /* Get file attributes */
952 Status
= NtQueryFullAttributesFile(&ObjectAttributes
,
955 RtlFreeUnicodeString (&FileName
);
956 if (!NT_SUCCESS (Status
))
958 WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status
);
959 SetLastErrorByStatus (Status
);
963 FileAttributeData
= (WIN32_FILE_ATTRIBUTE_DATA
*)lpFileInformation
;
964 FileAttributeData
->dwFileAttributes
= FileInformation
.FileAttributes
;
965 FileAttributeData
->ftCreationTime
.dwLowDateTime
= FileInformation
.CreationTime
.u
.LowPart
;
966 FileAttributeData
->ftCreationTime
.dwHighDateTime
= FileInformation
.CreationTime
.u
.HighPart
;
967 FileAttributeData
->ftLastAccessTime
.dwLowDateTime
= FileInformation
.LastAccessTime
.u
.LowPart
;
968 FileAttributeData
->ftLastAccessTime
.dwHighDateTime
= FileInformation
.LastAccessTime
.u
.HighPart
;
969 FileAttributeData
->ftLastWriteTime
.dwLowDateTime
= FileInformation
.LastWriteTime
.u
.LowPart
;
970 FileAttributeData
->ftLastWriteTime
.dwHighDateTime
= FileInformation
.LastWriteTime
.u
.HighPart
;
971 FileAttributeData
->nFileSizeLow
= FileInformation
.EndOfFile
.u
.LowPart
;
972 FileAttributeData
->nFileSizeHigh
= FileInformation
.EndOfFile
.u
.HighPart
;
981 GetFileAttributesExA(LPCSTR lpFileName
,
982 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
983 LPVOID lpFileInformation
)
987 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
990 return GetFileAttributesExW(FileNameW
, fInfoLevelId
, lpFileInformation
);
998 GetFileAttributesA(LPCSTR lpFileName
)
1000 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData
;
1004 if (!lpFileName
|| !(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
1005 return INVALID_FILE_ATTRIBUTES
;
1007 ret
= GetFileAttributesExW(FileNameW
, GetFileExInfoStandard
, &FileAttributeData
);
1009 return ret
? FileAttributeData
.dwFileAttributes
: INVALID_FILE_ATTRIBUTES
;
1017 GetFileAttributesW(LPCWSTR lpFileName
)
1019 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData
;
1022 TRACE ("GetFileAttributeW(%S) called\n", lpFileName
);
1024 Result
= GetFileAttributesExW(lpFileName
, GetFileExInfoStandard
, &FileAttributeData
);
1026 return Result
? FileAttributeData
.dwFileAttributes
: INVALID_FILE_ATTRIBUTES
;
1034 GetFileAttributesByHandle(IN HANDLE hFile
,
1035 OUT LPDWORD dwFileAttributes
,
1038 FILE_BASIC_INFORMATION FileBasic
;
1039 IO_STATUS_BLOCK IoStatusBlock
;
1042 UNREFERENCED_PARAMETER(dwFlags
);
1044 if (IsConsoleHandle(hFile
))
1046 SetLastError(ERROR_INVALID_HANDLE
);
1050 Status
= NtQueryInformationFile(hFile
,
1054 FileBasicInformation
);
1055 if (NT_SUCCESS(Status
))
1057 *dwFileAttributes
= FileBasic
.FileAttributes
;
1061 SetLastErrorByStatus(Status
);
1070 SetFileAttributesByHandle(IN HANDLE hFile
,
1071 IN DWORD dwFileAttributes
,
1074 FILE_BASIC_INFORMATION FileBasic
;
1075 IO_STATUS_BLOCK IoStatusBlock
;
1078 UNREFERENCED_PARAMETER(dwFlags
);
1080 if (IsConsoleHandle(hFile
))
1082 SetLastError(ERROR_INVALID_HANDLE
);
1086 Status
= NtQueryInformationFile(hFile
,
1090 FileBasicInformation
);
1091 if (NT_SUCCESS(Status
))
1093 FileBasic
.FileAttributes
= dwFileAttributes
;
1095 Status
= NtSetInformationFile(hFile
,
1099 FileBasicInformation
);
1102 if (!NT_SUCCESS(Status
))
1104 SetLastErrorByStatus(Status
);
1118 DWORD dwFileAttributes
)
1122 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
1125 return SetFileAttributesW(FileNameW
, dwFileAttributes
);
1133 SetFileAttributesW(LPCWSTR lpFileName
,
1134 DWORD dwFileAttributes
)
1136 FILE_BASIC_INFORMATION FileInformation
;
1137 OBJECT_ATTRIBUTES ObjectAttributes
;
1138 IO_STATUS_BLOCK IoStatusBlock
;
1139 UNICODE_STRING FileName
;
1143 TRACE ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName
, dwFileAttributes
);
1145 /* Validate and translate the filename */
1146 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
1151 WARN ("Invalid path\n");
1152 SetLastError (ERROR_BAD_PATHNAME
);
1155 TRACE ("FileName: \'%wZ\'\n", &FileName
);
1157 /* build the object attributes */
1158 InitializeObjectAttributes (&ObjectAttributes
,
1160 OBJ_CASE_INSENSITIVE
,
1165 Status
= NtOpenFile (&FileHandle
,
1166 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
,
1169 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1170 FILE_SYNCHRONOUS_IO_NONALERT
);
1171 RtlFreeUnicodeString (&FileName
);
1172 if (!NT_SUCCESS (Status
))
1174 WARN ("NtOpenFile() failed (Status %lx)\n", Status
);
1175 SetLastErrorByStatus (Status
);
1179 Status
= NtQueryInformationFile(FileHandle
,
1182 sizeof(FILE_BASIC_INFORMATION
),
1183 FileBasicInformation
);
1184 if (!NT_SUCCESS(Status
))
1186 WARN ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status
);
1187 NtClose (FileHandle
);
1188 SetLastErrorByStatus (Status
);
1192 FileInformation
.FileAttributes
= dwFileAttributes
;
1193 Status
= NtSetInformationFile(FileHandle
,
1196 sizeof(FILE_BASIC_INFORMATION
),
1197 FileBasicInformation
);
1198 NtClose (FileHandle
);
1199 if (!NT_SUCCESS(Status
))
1201 WARN ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status
);
1202 SetLastErrorByStatus (Status
);
1212 /***********************************************************************
1213 * GetTempFileNameA (KERNEL32.@)
1216 GetTempFileNameA(IN LPCSTR lpPathName
,
1217 IN LPCSTR lpPrefixString
,
1219 OUT LPSTR lpTempFileName
)
1223 LPWSTR lpTempFileNameW
;
1224 PUNICODE_STRING lpPathNameW
;
1225 ANSI_STRING TempFileNameStringA
;
1226 UNICODE_STRING lpPrefixStringW
, TempFileNameStringW
;
1228 /* Convert strings */
1229 lpPathNameW
= Basep8BitStringToStaticUnicodeString(lpPathName
);
1235 if (!Basep8BitStringToDynamicUnicodeString(&lpPrefixStringW
, lpPrefixString
))
1240 lpTempFileNameW
= RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
1241 if (!lpTempFileNameW
)
1243 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1244 RtlFreeUnicodeString(&lpPrefixStringW
);
1249 ID
= GetTempFileNameW(lpPathNameW
->Buffer
, lpPrefixStringW
.Buffer
, uUnique
, lpTempFileNameW
);
1252 RtlInitUnicodeString(&TempFileNameStringW
, lpTempFileNameW
);
1253 TempFileNameStringA
.Buffer
= lpTempFileName
;
1254 TempFileNameStringA
.MaximumLength
= MAX_PATH
;
1256 Status
= BasepUnicodeStringTo8BitString(&TempFileNameStringA
, &TempFileNameStringW
, FALSE
);
1257 if (!NT_SUCCESS(Status
))
1259 BaseSetLastNTError(Status
);
1265 RtlFreeUnicodeString(&lpPrefixStringW
);
1266 RtlFreeHeap(RtlGetProcessHeap(), 0, lpTempFileNameW
);
1270 /***********************************************************************
1271 * GetTempFileNameW (KERNEL32.@)
1274 GetTempFileNameW(IN LPCWSTR lpPathName
,
1275 IN LPCWSTR lpPrefixString
,
1277 OUT LPWSTR lpTempFileName
)
1283 WCHAR
* TempFileName
;
1284 CSR_API_MESSAGE ApiMessage
;
1285 DWORD FileAttributes
, LastError
;
1286 UNICODE_STRING PathNameString
, PrefixString
;
1287 static const WCHAR Ext
[] = { L
'.', 't', 'm', 'p', UNICODE_NULL
};
1289 RtlInitUnicodeString(&PathNameString
, lpPathName
);
1290 if (PathNameString
.Length
== 0 || PathNameString
.Buffer
[(PathNameString
.Length
/ sizeof(WCHAR
)) - 1] != L
'\\')
1292 PathNameString
.Length
+= sizeof(WCHAR
);
1295 /* lpTempFileName must be able to contain: PathName, Prefix (3), number(4), .tmp(4) & \0(1)
1296 * See: http://msdn.microsoft.com/en-us/library/aa364991%28v=vs.85%29.aspx
1298 if (PathNameString
.Length
> (MAX_PATH
- 3 - 4 - 4 - 1) * sizeof(WCHAR
))
1300 SetLastError(ERROR_BUFFER_OVERFLOW
);
1304 /* If PathName and TempFileName aren't the same buffer, move PathName to TempFileName */
1305 if (lpPathName
!= lpTempFileName
)
1307 memmove(lpTempFileName
, PathNameString
.Buffer
, PathNameString
.Length
);
1310 /* PathName MUST BE a path. Check it */
1311 lpTempFileName
[(PathNameString
.Length
/ sizeof(WCHAR
)) - 1] = UNICODE_NULL
;
1312 FileAttributes
= GetFileAttributesW(lpTempFileName
);
1313 if (FileAttributes
== INVALID_FILE_ATTRIBUTES
)
1315 /* Append a '\' if necessary */
1316 lpTempFileName
[(PathNameString
.Length
/ sizeof(WCHAR
)) - 1] = L
'\\';
1317 lpTempFileName
[PathNameString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1318 FileAttributes
= GetFileAttributesW(lpTempFileName
);
1319 if (FileAttributes
== INVALID_FILE_ATTRIBUTES
)
1321 SetLastError(ERROR_DIRECTORY
);
1325 if (!(FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
1327 SetLastError(ERROR_DIRECTORY
);
1331 /* Make sure not to mix path & prefix */
1332 lpTempFileName
[(PathNameString
.Length
/ sizeof(WCHAR
)) - 1] = L
'\\';
1333 RtlInitUnicodeString(&PrefixString
, lpPrefixString
);
1334 if (PrefixString
.Length
> 3 * sizeof(WCHAR
))
1336 PrefixString
.Length
= 3 * sizeof(WCHAR
);
1339 /* Append prefix to path */
1340 TempFileName
= lpTempFileName
+ PathNameString
.Length
/ sizeof(WCHAR
);
1341 memmove(TempFileName
, PrefixString
.Buffer
, PrefixString
.Length
);
1342 TempFileName
+= PrefixString
.Length
/ sizeof(WCHAR
);
1344 /* Then, generate filename */
1347 /* If user didn't gave any ID, ask Csrss to give one */
1350 CsrClientCallServer(&ApiMessage
, NULL
, MAKE_CSR_API(GET_TEMP_FILE
, CSR_NATIVE
), sizeof(CSR_API_MESSAGE
));
1351 if (ApiMessage
.Data
.GetTempFile
.UniqueID
== 0)
1357 ID
= ApiMessage
.Data
.GetTempFile
.UniqueID
;
1364 /* Convert that ID to wchar */
1365 RtlIntegerToChar(ID
, 0x10, sizeof(IDString
), IDString
);
1369 *(TempFileName
++) = RtlAnsiCharToUnicodeChar(&Let
);
1370 } while (*Let
!= 0);
1372 /* Append extension & UNICODE_NULL */
1373 memmove(TempFileName
, Ext
, sizeof(Ext
) + sizeof(WCHAR
));
1375 /* If user provided its ID, just return */
1381 /* Then, try to create file */
1382 if (!RtlIsDosDeviceName_U(lpTempFileName
))
1384 TempFile
= CreateFileW(lpTempFileName
,
1389 FILE_ATTRIBUTE_NORMAL
,
1391 if (TempFile
!= INVALID_HANDLE_VALUE
)
1394 DPRINT("Temp file: %S\n", lpTempFileName
);
1398 LastError
= GetLastError();
1399 /* There is no need to recover from those errors, they would hit next step */
1400 if (LastError
== ERROR_INVALID_PARAMETER
|| LastError
== ERROR_CANNOT_MAKE
||
1401 LastError
== ERROR_WRITE_PROTECT
|| LastError
== ERROR_NETWORK_ACCESS_DENIED
||
1402 LastError
== ERROR_DISK_FULL
|| LastError
== ERROR_INVALID_NAME
||
1403 LastError
== ERROR_BAD_PATHNAME
|| LastError
== ERROR_NO_INHERITANCE
||
1404 LastError
== ERROR_DISK_CORRUPT
||
1405 (LastError
== ERROR_ACCESS_DENIED
&& NtCurrentTeb()->LastStatusValue
!= STATUS_FILE_IS_A_DIRECTORY
))
1411 } while (Num
& 0xFFFF);
1424 GetFileTime(HANDLE hFile
,
1425 LPFILETIME lpCreationTime
,
1426 LPFILETIME lpLastAccessTime
,
1427 LPFILETIME lpLastWriteTime
)
1429 IO_STATUS_BLOCK IoStatusBlock
;
1430 FILE_BASIC_INFORMATION FileBasic
;
1433 if(IsConsoleHandle(hFile
))
1435 SetLastError(ERROR_INVALID_HANDLE
);
1439 Status
= NtQueryInformationFile(hFile
,
1442 sizeof(FILE_BASIC_INFORMATION
),
1443 FileBasicInformation
);
1444 if (!NT_SUCCESS(Status
))
1446 SetLastErrorByStatus(Status
);
1451 memcpy(lpCreationTime
, &FileBasic
.CreationTime
, sizeof(FILETIME
));
1452 if (lpLastAccessTime
)
1453 memcpy(lpLastAccessTime
, &FileBasic
.LastAccessTime
, sizeof(FILETIME
));
1454 if (lpLastWriteTime
)
1455 memcpy(lpLastWriteTime
, &FileBasic
.LastWriteTime
, sizeof(FILETIME
));
1465 SetFileTime(HANDLE hFile
,
1466 CONST FILETIME
*lpCreationTime
,
1467 CONST FILETIME
*lpLastAccessTime
,
1468 CONST FILETIME
*lpLastWriteTime
)
1470 FILE_BASIC_INFORMATION FileBasic
;
1471 IO_STATUS_BLOCK IoStatusBlock
;
1474 if(IsConsoleHandle(hFile
))
1476 SetLastError(ERROR_INVALID_HANDLE
);
1480 Status
= NtQueryInformationFile(hFile
,
1483 sizeof(FILE_BASIC_INFORMATION
),
1484 FileBasicInformation
);
1485 if (!NT_SUCCESS(Status
))
1487 SetLastErrorByStatus(Status
);
1492 memcpy(&FileBasic
.CreationTime
, lpCreationTime
, sizeof(FILETIME
));
1493 if (lpLastAccessTime
)
1494 memcpy(&FileBasic
.LastAccessTime
, lpLastAccessTime
, sizeof(FILETIME
));
1495 if (lpLastWriteTime
)
1496 memcpy(&FileBasic
.LastWriteTime
, lpLastWriteTime
, sizeof(FILETIME
));
1498 // should i initialize changetime ???
1500 Status
= NtSetInformationFile(hFile
,
1503 sizeof(FILE_BASIC_INFORMATION
),
1504 FileBasicInformation
);
1505 if (!NT_SUCCESS(Status
))
1507 SetLastErrorByStatus(Status
);
1516 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1521 SetEndOfFile(HANDLE hFile
)
1523 IO_STATUS_BLOCK IoStatusBlock
;
1524 FILE_END_OF_FILE_INFORMATION EndOfFileInfo
;
1525 FILE_ALLOCATION_INFORMATION FileAllocationInfo
;
1526 FILE_POSITION_INFORMATION FilePosInfo
;
1529 if(IsConsoleHandle(hFile
))
1531 SetLastError(ERROR_INVALID_HANDLE
);
1535 //get current position
1536 Status
= NtQueryInformationFile(
1540 sizeof(FILE_POSITION_INFORMATION
),
1541 FilePositionInformation
1544 if (!NT_SUCCESS(Status
)){
1545 SetLastErrorByStatus(Status
);
1549 EndOfFileInfo
.EndOfFile
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1553 This call is not supposed to free up any space after the eof marker
1554 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1555 But...most file systems dispatch both FileEndOfFileInformation
1556 and FileAllocationInformation as they were the same command.
1559 Status
= NtSetInformationFile(
1561 &IoStatusBlock
, //out
1563 sizeof(FILE_END_OF_FILE_INFORMATION
),
1564 FileEndOfFileInformation
1567 if (!NT_SUCCESS(Status
)){
1568 SetLastErrorByStatus(Status
);
1572 FileAllocationInfo
.AllocationSize
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1575 Status
= NtSetInformationFile(
1577 &IoStatusBlock
, //out
1578 &FileAllocationInfo
,
1579 sizeof(FILE_ALLOCATION_INFORMATION
),
1580 FileAllocationInformation
1583 if (!NT_SUCCESS(Status
)){
1584 SetLastErrorByStatus(Status
);
1600 LONGLONG ValidDataLength
1603 IO_STATUS_BLOCK IoStatusBlock
;
1604 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation
;
1607 ValidDataLengthInformation
.ValidDataLength
.QuadPart
= ValidDataLength
;
1609 Status
= NtSetInformationFile(
1611 &IoStatusBlock
, //out
1612 &ValidDataLengthInformation
,
1613 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION
),
1614 FileValidDataLengthInformation
1617 if (!NT_SUCCESS(Status
)){
1618 SetLastErrorByStatus(Status
);
1634 LPCWSTR lpShortName
)
1638 UNICODE_STRING ShortName
;
1639 IO_STATUS_BLOCK IoStatusBlock
;
1640 PFILE_NAME_INFORMATION FileNameInfo
;
1642 if(IsConsoleHandle(hFile
))
1644 SetLastError(ERROR_INVALID_HANDLE
);
1650 SetLastError(ERROR_INVALID_PARAMETER
);
1654 RtlInitUnicodeString(&ShortName
, lpShortName
);
1656 NeededSize
= sizeof(FILE_NAME_INFORMATION
) + ShortName
.Length
+ sizeof(WCHAR
);
1657 if(!(FileNameInfo
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
)))
1659 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1663 FileNameInfo
->FileNameLength
= ShortName
.Length
;
1664 RtlCopyMemory(FileNameInfo
->FileName
, ShortName
.Buffer
, ShortName
.Length
);
1666 Status
= NtSetInformationFile(hFile
,
1667 &IoStatusBlock
, //out
1670 FileShortNameInformation
);
1672 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo
);
1673 if(!NT_SUCCESS(Status
))
1675 SetLastErrorByStatus(Status
);
1695 if(IsConsoleHandle(hFile
))
1697 SetLastError(ERROR_INVALID_HANDLE
);
1703 SetLastError(ERROR_INVALID_PARAMETER
);
1707 if (!(ShortNameW
= FilenameA2W(lpShortName
, FALSE
)))
1710 return SetFileShortNameW(hFile
, ShortNameW
);
1719 CheckNameLegalDOS8Dot3W(
1721 LPSTR lpOemName OPTIONAL
,
1722 DWORD OemNameSize OPTIONAL
,
1723 PBOOL pbNameContainsSpaces OPTIONAL
,
1727 UNICODE_STRING Name
;
1728 ANSI_STRING AnsiName
;
1730 if(lpName
== NULL
||
1731 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
1732 pbNameLegal
== NULL
)
1734 SetLastError(ERROR_INVALID_PARAMETER
);
1738 if(lpOemName
!= NULL
)
1740 AnsiName
.Buffer
= lpOemName
;
1741 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
1742 AnsiName
.Length
= 0;
1745 RtlInitUnicodeString(&Name
, lpName
);
1747 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
1748 (lpOemName
? &AnsiName
: NULL
),
1749 (BOOLEAN
*)pbNameContainsSpaces
);
1760 CheckNameLegalDOS8Dot3A(
1762 LPSTR lpOemName OPTIONAL
,
1763 DWORD OemNameSize OPTIONAL
,
1764 PBOOL pbNameContainsSpaces OPTIONAL
,
1768 UNICODE_STRING Name
;
1769 ANSI_STRING AnsiName
, AnsiInputName
;
1772 if(lpName
== NULL
||
1773 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
1774 pbNameLegal
== NULL
)
1776 SetLastError(ERROR_INVALID_PARAMETER
);
1780 if(lpOemName
!= NULL
)
1782 AnsiName
.Buffer
= lpOemName
;
1783 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
1784 AnsiName
.Length
= 0;
1787 RtlInitAnsiString(&AnsiInputName
, (LPSTR
)lpName
);
1789 Status
= RtlAnsiStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
1791 Status
= RtlOemStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
1793 if(!NT_SUCCESS(Status
))
1795 SetLastErrorByStatus(Status
);
1799 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
1800 (lpOemName
? &AnsiName
: NULL
),
1801 (BOOLEAN
*)pbNameContainsSpaces
);
1803 RtlFreeUnicodeString(&Name
);
1814 GetFinalPathNameByHandleA(IN HANDLE hFile
,
1815 OUT LPSTR lpszFilePath
,
1816 IN DWORD cchFilePath
,
1819 WCHAR FilePathW
[MAX_PATH
];
1820 UNICODE_STRING FilePathU
;
1821 DWORD PrevLastError
;
1824 if (cchFilePath
!= 0 &&
1825 cchFilePath
> sizeof(FilePathW
) / sizeof(FilePathW
[0]))
1827 FilePathU
.Length
= 0;
1828 FilePathU
.MaximumLength
= (USHORT
)cchFilePath
* sizeof(WCHAR
);
1829 FilePathU
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
1831 FilePathU
.MaximumLength
);
1832 if (FilePathU
.Buffer
== NULL
)
1834 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1840 FilePathU
.Length
= 0;
1841 FilePathU
.MaximumLength
= sizeof(FilePathW
);
1842 FilePathU
.Buffer
= FilePathW
;
1845 /* save the last error code */
1846 PrevLastError
= GetLastError();
1847 SetLastError(ERROR_SUCCESS
);
1849 /* call the unicode version that does all the work */
1850 Ret
= GetFinalPathNameByHandleW(hFile
,
1855 if (GetLastError() == ERROR_SUCCESS
)
1857 /* no error, restore the last error code and convert the string */
1858 SetLastError(PrevLastError
);
1860 Ret
= FilenameU2A_FitOrFail(lpszFilePath
,
1865 /* free allocated memory if necessary */
1866 if (FilePathU
.Buffer
!= FilePathW
)
1868 RtlFreeHeap(RtlGetProcessHeap(),
1882 GetFinalPathNameByHandleW(IN HANDLE hFile
,
1883 OUT LPWSTR lpszFilePath
,
1884 IN DWORD cchFilePath
,
1887 if (dwFlags
& ~(VOLUME_NAME_DOS
| VOLUME_NAME_GUID
| VOLUME_NAME_NT
|
1888 VOLUME_NAME_NONE
| FILE_NAME_NORMALIZED
| FILE_NAME_OPENED
))
1890 SetLastError(ERROR_INVALID_PARAMETER
);
1904 SetFileBandwidthReservation(IN HANDLE hFile
,
1905 IN DWORD nPeriodMilliseconds
,
1906 IN DWORD nBytesPerPeriod
,
1907 IN BOOL bDiscardable
,
1908 OUT LPDWORD lpTransferSize
,
1909 OUT LPDWORD lpNumOutstandingRequests
)
1921 GetFileBandwidthReservation(IN HANDLE hFile
,
1922 OUT LPDWORD lpPeriodMilliseconds
,
1923 OUT LPDWORD lpBytesPerPeriod
,
1924 OUT LPBOOL pDiscardable
,
1925 OUT LPDWORD lpTransferSize
,
1926 OUT LPDWORD lpNumOutstandingRequests
)
1938 SetFileCompletionNotificationModes(IN HANDLE FileHandle
,
1941 if (Flags
& ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
| FILE_SKIP_SET_EVENT_ON_HANDLE
))
1943 SetLastError(ERROR_INVALID_PARAMETER
);
1957 OpenFileById(IN HANDLE hFile
,
1958 IN LPFILE_ID_DESCRIPTOR lpFileID
,
1959 IN DWORD dwDesiredAccess
,
1960 IN DWORD dwShareMode
,
1961 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL
,
1965 return INVALID_HANDLE_VALUE
;
1974 LPCSTR lpReplacedFileName
,
1975 LPCSTR lpReplacementFileName
,
1976 LPCSTR lpBackupFileName
,
1977 DWORD dwReplaceFlags
,
1982 WCHAR
*replacedW
, *replacementW
, *backupW
= NULL
;
1985 /* This function only makes sense when the first two parameters are defined */
1986 if (!lpReplacedFileName
|| !(replacedW
= FilenameA2W(lpReplacedFileName
, TRUE
)))
1988 SetLastError(ERROR_INVALID_PARAMETER
);
1992 if (!lpReplacementFileName
|| !(replacementW
= FilenameA2W(lpReplacementFileName
, TRUE
)))
1994 HeapFree(GetProcessHeap(), 0, replacedW
);
1995 SetLastError(ERROR_INVALID_PARAMETER
);
1999 /* The backup parameter, however, is optional */
2000 if (lpBackupFileName
)
2002 if (!(backupW
= FilenameA2W(lpBackupFileName
, TRUE
)))
2004 HeapFree(GetProcessHeap(), 0, replacedW
);
2005 HeapFree(GetProcessHeap(), 0, replacementW
);
2006 SetLastError(ERROR_INVALID_PARAMETER
);
2011 ret
= ReplaceFileW(replacedW
, replacementW
, backupW
, dwReplaceFlags
, lpExclude
, lpReserved
);
2012 HeapFree(GetProcessHeap(), 0, replacedW
);
2013 HeapFree(GetProcessHeap(), 0, replacementW
);
2014 HeapFree(GetProcessHeap(), 0, backupW
);
2025 LPCWSTR lpReplacedFileName
,
2026 LPCWSTR lpReplacementFileName
,
2027 LPCWSTR lpBackupFileName
,
2028 DWORD dwReplaceFlags
,
2033 HANDLE hReplaced
= NULL
, hReplacement
= NULL
;
2034 UNICODE_STRING NtReplacedName
= { 0, 0, NULL
};
2035 UNICODE_STRING NtReplacementName
= { 0, 0, NULL
};
2036 DWORD Error
= ERROR_SUCCESS
;
2039 IO_STATUS_BLOCK IoStatusBlock
;
2040 OBJECT_ATTRIBUTES ObjectAttributes
;
2041 PVOID Buffer
= NULL
;
2044 FIXME("Ignoring flags %x\n", dwReplaceFlags
);
2046 /* First two arguments are mandatory */
2047 if (!lpReplacedFileName
|| !lpReplacementFileName
)
2049 SetLastError(ERROR_INVALID_PARAMETER
);
2054 if(lpBackupFileName
)
2056 if(!CopyFileW(lpReplacedFileName
, lpBackupFileName
, FALSE
))
2058 Error
= GetLastError();
2063 /* Open the "replaced" file for reading and writing */
2064 if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName
, &NtReplacedName
, NULL
, NULL
)))
2066 Error
= ERROR_PATH_NOT_FOUND
;
2070 InitializeObjectAttributes(&ObjectAttributes
,
2072 OBJ_CASE_INSENSITIVE
,
2076 Status
= NtOpenFile(&hReplaced
,
2077 GENERIC_READ
| GENERIC_WRITE
| DELETE
| SYNCHRONIZE
| WRITE_DAC
,
2080 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2081 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
2083 if (!NT_SUCCESS(Status
))
2085 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2086 Error
= ERROR_FILE_NOT_FOUND
;
2088 Error
= ERROR_UNABLE_TO_REMOVE_REPLACED
;
2093 SetEndOfFile(hReplaced
) ;
2096 * Open the replacement file for reading, writing, and deleting
2097 * (deleting is needed when finished)
2099 if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName
, &NtReplacementName
, NULL
, NULL
)))
2101 Error
= ERROR_PATH_NOT_FOUND
;
2105 InitializeObjectAttributes(&ObjectAttributes
,
2107 OBJ_CASE_INSENSITIVE
,
2111 Status
= NtOpenFile(&hReplacement
,
2112 GENERIC_READ
| DELETE
| SYNCHRONIZE
,
2116 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
| FILE_DELETE_ON_CLOSE
);
2118 if (!NT_SUCCESS(Status
))
2120 Error
= RtlNtStatusToDosError(Status
);
2124 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, 0x10000) ;
2127 Error
= ERROR_NOT_ENOUGH_MEMORY
;
2130 while (Status
!= STATUS_END_OF_FILE
)
2132 Status
= NtReadFile(hReplacement
, NULL
, NULL
, NULL
, &IoStatusBlock
, Buffer
, 0x10000, NULL
, NULL
) ;
2133 if (NT_SUCCESS(Status
))
2135 Status
= NtWriteFile(hReplaced
, NULL
, NULL
, NULL
, &IoStatusBlock
, Buffer
,
2136 IoStatusBlock
.Information
, NULL
, NULL
) ;
2137 if (!NT_SUCCESS(Status
))
2139 Error
= RtlNtStatusToDosError(Status
);
2143 else if (Status
!= STATUS_END_OF_FILE
)
2145 Error
= RtlNtStatusToDosError(Status
);
2152 /* Perform resource cleanup */
2154 if (hReplaced
) NtClose(hReplaced
);
2155 if (hReplacement
) NtClose(hReplacement
);
2156 if (Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
2158 if (NtReplacementName
.Buffer
)
2159 RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName
.Buffer
);
2160 if (NtReplacedName
.Buffer
)
2161 RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName
.Buffer
);
2163 /* If there was an error, set the error code */
2166 TRACE("ReplaceFileW failed (error=%d)\n", Error
);
2167 SetLastError(Error
);