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 * GetTempFileName is modified from WINE [ Alexandre Juiliard ]
13 /* INCLUDES *****************************************************************/
16 #include <wine/debug.h>
18 WINE_DEFAULT_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 ret
= bIsFileApiAnsi
? RtlUnicodeStringToAnsiSize(SourceU
) : RtlUnicodeStringToOemSize(SourceU
);
76 /* ret incl. nullchar */
78 if (DestA
&& (INT
)ret
<= destLen
)
83 str
.MaximumLength
= (USHORT
)destLen
;
87 RtlUnicodeStringToAnsiString(&str
, SourceU
, FALSE
);
89 RtlUnicodeStringToOemString(&str
, SourceU
, FALSE
);
91 ret
= str
.Length
; /* SUCCESS: length without terminating 0 */
99 No copy/conversion is done if the dest. buffer is too small.
102 Success: number of TCHARS copied into dest. buffer NOT including nullterm
103 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
106 FilenameW2A_FitOrFail(
108 INT destLen
, /* buffer size in TCHARS incl. nullchar */
110 INT sourceLen
/* buffer size in TCHARS incl. nullchar */
115 if (sourceLen
< 0) sourceLen
= wcslen(SourceW
) + 1;
117 strW
.Buffer
= (PWCHAR
)SourceW
;
118 strW
.MaximumLength
= sourceLen
* sizeof(WCHAR
);
119 strW
.Length
= strW
.MaximumLength
- sizeof(WCHAR
);
121 return FilenameU2A_FitOrFail(DestA
, destLen
, &strW
);
126 Return: num. TCHARS copied into dest including nullterm
131 INT destlen
, /* buffer size in TCHARS incl. nullchar */
133 INT srclen
/* buffer size in TCHARS incl. nullchar */
138 if (srclen
< 0) srclen
= strlen( src
) + 1;
141 RtlMultiByteToUnicodeN( dest
, destlen
* sizeof(WCHAR
), &ret
, (LPSTR
)src
, srclen
);
143 RtlOemToUnicodeN( dest
, destlen
* sizeof(WCHAR
), &ret
, (LPSTR
)src
, srclen
);
145 if (ret
) dest
[(ret
/sizeof(WCHAR
))-1]=0;
147 return ret
/sizeof(WCHAR
);
151 Return: num. TCHARS copied into dest including nullterm
156 INT destlen
, /* buffer size in TCHARS incl. nullchar */
158 INT srclen
/* buffer size in TCHARS incl. nullchar */
163 if (srclen
< 0) srclen
= wcslen( src
) + 1;
166 RtlUnicodeToMultiByteN( dest
, destlen
, &ret
, (LPWSTR
) src
, srclen
* sizeof(WCHAR
));
168 RtlUnicodeToOemN( dest
, destlen
, &ret
, (LPWSTR
) src
, srclen
* sizeof(WCHAR
) );
170 if (ret
) dest
[ret
-1]=0;
181 SetFileApisToOEM(VOID
)
183 /* Set the correct Base Api */
184 Basep8BitStringToUnicodeString
= (PRTL_CONVERT_STRING
)RtlOemStringToUnicodeString
;
186 /* FIXME: Old, deprecated way */
187 bIsFileApiAnsi
= FALSE
;
196 SetFileApisToANSI(VOID
)
198 /* Set the correct Base Api */
199 Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
201 /* FIXME: Old, deprecated way */
202 bIsFileApiAnsi
= TRUE
;
210 AreFileApisANSI(VOID
)
212 return bIsFileApiAnsi
;
220 OpenFile(LPCSTR lpFileName
,
221 LPOFSTRUCT lpReOpenBuff
,
224 OBJECT_ATTRIBUTES ObjectAttributes
;
225 IO_STATUS_BLOCK IoStatusBlock
;
226 UNICODE_STRING FileNameString
;
227 UNICODE_STRING FileNameU
;
228 ANSI_STRING FileName
;
229 WCHAR PathNameW
[MAX_PATH
];
230 HANDLE FileHandle
= NULL
;
235 TRACE("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName
, lpReOpenBuff
, uStyle
);
237 if (lpReOpenBuff
== NULL
)
242 lpReOpenBuff
->nErrCode
= 0;
244 if (uStyle
& OF_REOPEN
) lpFileName
= lpReOpenBuff
->szPathName
;
251 if (!GetFullPathNameA(lpFileName
,
252 sizeof(lpReOpenBuff
->szPathName
),
253 lpReOpenBuff
->szPathName
,
256 lpReOpenBuff
->nErrCode
= GetLastError();
260 if (uStyle
& OF_PARSE
)
262 lpReOpenBuff
->fFixedDisk
= (GetDriveTypeA(lpReOpenBuff
->szPathName
) != DRIVE_REMOVABLE
);
263 TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName
, lpReOpenBuff
->szPathName
);
267 if ((uStyle
& OF_EXIST
) && !(uStyle
& OF_CREATE
))
269 DWORD dwAttributes
= GetFileAttributesA(lpReOpenBuff
->szPathName
);
271 switch (dwAttributes
)
273 case 0xFFFFFFFF: /* File does not exist */
274 SetLastError(ERROR_FILE_NOT_FOUND
);
275 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_FILE_NOT_FOUND
;
278 case FILE_ATTRIBUTE_DIRECTORY
:
279 SetLastError(ERROR_ACCESS_DENIED
);
280 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_ACCESS_DENIED
;
284 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
288 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
289 if ((uStyle
& OF_CREATE
) == OF_CREATE
)
292 switch (uStyle
& 0x70)
294 case OF_SHARE_EXCLUSIVE
: Sharing
= 0; break;
295 case OF_SHARE_DENY_WRITE
: Sharing
= FILE_SHARE_READ
; break;
296 case OF_SHARE_DENY_READ
: Sharing
= FILE_SHARE_WRITE
; break;
297 case OF_SHARE_DENY_NONE
:
298 case OF_SHARE_COMPAT
:
300 Sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
302 return (HFILE
) CreateFileA (lpFileName
,
303 GENERIC_READ
| GENERIC_WRITE
,
307 FILE_ATTRIBUTE_NORMAL
,
311 RtlInitAnsiString (&FileName
, (LPSTR
)lpFileName
);
313 /* convert ansi (or oem) string to unicode */
315 RtlAnsiStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
317 RtlOemStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
319 Len
= SearchPathW (NULL
,
326 RtlFreeUnicodeString(&FileNameU
);
328 if (Len
== 0 || Len
> OFS_MAXPATHNAME
)
330 lpReOpenBuff
->nErrCode
= GetLastError();
331 return (HFILE
)INVALID_HANDLE_VALUE
;
334 if (uStyle
& OF_DELETE
)
336 if (!DeleteFileW(PathNameW
))
338 lpReOpenBuff
->nErrCode
= GetLastError();
341 TRACE("(%s): OF_DELETE return = OK\n", lpFileName
);
345 FileName
.Buffer
= lpReOpenBuff
->szPathName
;
347 FileName
.MaximumLength
= OFS_MAXPATHNAME
;
349 RtlInitUnicodeString(&FileNameU
, PathNameW
);
351 /* convert unicode string to ansi (or oem) */
353 RtlUnicodeStringToAnsiString (&FileName
, &FileNameU
, FALSE
);
355 RtlUnicodeStringToOemString (&FileName
, &FileNameU
, FALSE
);
357 if (!RtlDosPathNameToNtPathName_U (PathNameW
,
362 return (HFILE
)INVALID_HANDLE_VALUE
;
366 // FILE_NO_INTERMEDIATE_BUFFERING
368 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
369 ObjectAttributes
.RootDirectory
= NULL
;
370 ObjectAttributes
.ObjectName
= &FileNameString
;
371 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
372 ObjectAttributes
.SecurityDescriptor
= NULL
;
373 ObjectAttributes
.SecurityQualityOfService
= NULL
;
375 errCode
= NtOpenFile (&FileHandle
,
376 GENERIC_READ
|SYNCHRONIZE
,
380 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
382 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString
.Buffer
);
384 lpReOpenBuff
->nErrCode
= RtlNtStatusToDosError(errCode
);
386 if (!NT_SUCCESS(errCode
))
388 SetLastErrorByStatus (errCode
);
389 return (HFILE
)INVALID_HANDLE_VALUE
;
392 if (uStyle
& OF_EXIST
)
398 return (HFILE
)FileHandle
;
406 FlushFileBuffers(HANDLE hFile
)
409 IO_STATUS_BLOCK IoStatusBlock
;
411 hFile
= TranslateStdHandle(hFile
);
413 if (IsConsoleHandle(hFile
))
418 errCode
= NtFlushBuffersFile(hFile
,
420 if (!NT_SUCCESS(errCode
))
422 SetLastErrorByStatus(errCode
);
433 SetFilePointer(HANDLE hFile
,
434 LONG lDistanceToMove
,
435 PLONG lpDistanceToMoveHigh
,
438 FILE_POSITION_INFORMATION FilePosition
;
439 FILE_STANDARD_INFORMATION FileStandard
;
441 IO_STATUS_BLOCK IoStatusBlock
;
442 LARGE_INTEGER Distance
;
444 TRACE("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
445 hFile
,lDistanceToMove
,dwMoveMethod
);
447 if(IsConsoleHandle(hFile
))
449 SetLastError(ERROR_INVALID_HANDLE
);
450 return INVALID_SET_FILE_POINTER
;
453 if (lpDistanceToMoveHigh
)
455 Distance
.u
.HighPart
= *lpDistanceToMoveHigh
;
456 Distance
.u
.LowPart
= lDistanceToMove
;
460 Distance
.QuadPart
= lDistanceToMove
;
466 errCode
= NtQueryInformationFile(hFile
,
469 sizeof(FILE_POSITION_INFORMATION
),
470 FilePositionInformation
);
471 FilePosition
.CurrentByteOffset
.QuadPart
+= Distance
.QuadPart
;
472 if (!NT_SUCCESS(errCode
))
474 if (lpDistanceToMoveHigh
!= NULL
)
475 *lpDistanceToMoveHigh
= -1;
476 SetLastErrorByStatus(errCode
);
477 return INVALID_SET_FILE_POINTER
;
481 errCode
= NtQueryInformationFile(hFile
,
484 sizeof(FILE_STANDARD_INFORMATION
),
485 FileStandardInformation
);
486 FilePosition
.CurrentByteOffset
.QuadPart
=
487 FileStandard
.EndOfFile
.QuadPart
+ Distance
.QuadPart
;
488 if (!NT_SUCCESS(errCode
))
490 if (lpDistanceToMoveHigh
!= NULL
)
491 *lpDistanceToMoveHigh
= -1;
492 SetLastErrorByStatus(errCode
);
493 return INVALID_SET_FILE_POINTER
;
497 FilePosition
.CurrentByteOffset
.QuadPart
= Distance
.QuadPart
;
500 SetLastError(ERROR_INVALID_PARAMETER
);
501 return INVALID_SET_FILE_POINTER
;
504 if(FilePosition
.CurrentByteOffset
.QuadPart
< 0)
506 SetLastError(ERROR_NEGATIVE_SEEK
);
507 return INVALID_SET_FILE_POINTER
;
510 if (lpDistanceToMoveHigh
== NULL
&& FilePosition
.CurrentByteOffset
.HighPart
!= 0)
512 /* If we're moving the pointer outside of the 32 bit boundaries but
513 the application only passed a 32 bit value we need to bail out! */
514 SetLastError(ERROR_INVALID_PARAMETER
);
515 return INVALID_SET_FILE_POINTER
;
518 errCode
= NtSetInformationFile(hFile
,
521 sizeof(FILE_POSITION_INFORMATION
),
522 FilePositionInformation
);
523 if (!NT_SUCCESS(errCode
))
525 if (lpDistanceToMoveHigh
!= NULL
)
526 *lpDistanceToMoveHigh
= -1;
528 SetLastErrorByStatus(errCode
);
529 return INVALID_SET_FILE_POINTER
;
532 if (lpDistanceToMoveHigh
!= NULL
)
534 *lpDistanceToMoveHigh
= FilePosition
.CurrentByteOffset
.u
.HighPart
;
537 if (FilePosition
.CurrentByteOffset
.u
.LowPart
== MAXDWORD
)
539 /* The value of -1 is valid here, especially when the new
540 file position is greater than 4 GB. Since NtSetInformationFile
541 succeeded we never set an error code and we explicitly need
542 to clear a previously set error code in this case, which
543 an application will check if INVALID_SET_FILE_POINTER is returned! */
544 SetLastError(ERROR_SUCCESS
);
547 return FilePosition
.CurrentByteOffset
.u
.LowPart
;
556 SetFilePointerEx(HANDLE hFile
,
557 LARGE_INTEGER liDistanceToMove
,
558 PLARGE_INTEGER lpNewFilePointer
,
561 FILE_POSITION_INFORMATION FilePosition
;
562 FILE_STANDARD_INFORMATION FileStandard
;
564 IO_STATUS_BLOCK IoStatusBlock
;
566 if(IsConsoleHandle(hFile
))
568 SetLastError(ERROR_INVALID_HANDLE
);
575 NtQueryInformationFile(hFile
,
578 sizeof(FILE_POSITION_INFORMATION
),
579 FilePositionInformation
);
580 FilePosition
.CurrentByteOffset
.QuadPart
+= liDistanceToMove
.QuadPart
;
583 NtQueryInformationFile(hFile
,
586 sizeof(FILE_STANDARD_INFORMATION
),
587 FileStandardInformation
);
588 FilePosition
.CurrentByteOffset
.QuadPart
=
589 FileStandard
.EndOfFile
.QuadPart
+ liDistanceToMove
.QuadPart
;
592 FilePosition
.CurrentByteOffset
.QuadPart
= liDistanceToMove
.QuadPart
;
595 SetLastError(ERROR_INVALID_PARAMETER
);
599 if(FilePosition
.CurrentByteOffset
.QuadPart
< 0)
601 SetLastError(ERROR_NEGATIVE_SEEK
);
605 errCode
= NtSetInformationFile(hFile
,
608 sizeof(FILE_POSITION_INFORMATION
),
609 FilePositionInformation
);
610 if (!NT_SUCCESS(errCode
))
612 SetLastErrorByStatus(errCode
);
616 if (lpNewFilePointer
)
618 *lpNewFilePointer
= FilePosition
.CurrentByteOffset
;
628 GetFileType(HANDLE hFile
)
630 FILE_FS_DEVICE_INFORMATION DeviceInfo
;
631 IO_STATUS_BLOCK StatusBlock
;
634 /* Get real handle */
635 hFile
= TranslateStdHandle(hFile
);
637 /* Check for console handle */
638 if (IsConsoleHandle(hFile
))
640 if (VerifyConsoleIoHandle(hFile
))
641 return FILE_TYPE_CHAR
;
644 Status
= NtQueryVolumeInformationFile(hFile
,
647 sizeof(FILE_FS_DEVICE_INFORMATION
),
648 FileFsDeviceInformation
);
649 if (!NT_SUCCESS(Status
))
651 SetLastErrorByStatus(Status
);
652 return FILE_TYPE_UNKNOWN
;
655 switch (DeviceInfo
.DeviceType
)
657 case FILE_DEVICE_CD_ROM
:
658 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
659 case FILE_DEVICE_CONTROLLER
:
660 case FILE_DEVICE_DATALINK
:
661 case FILE_DEVICE_DFS
:
662 case FILE_DEVICE_DISK
:
663 case FILE_DEVICE_DISK_FILE_SYSTEM
:
664 case FILE_DEVICE_VIRTUAL_DISK
:
665 return FILE_TYPE_DISK
;
667 case FILE_DEVICE_KEYBOARD
:
668 case FILE_DEVICE_MOUSE
:
669 case FILE_DEVICE_NULL
:
670 case FILE_DEVICE_PARALLEL_PORT
:
671 case FILE_DEVICE_PRINTER
:
672 case FILE_DEVICE_SERIAL_PORT
:
673 case FILE_DEVICE_SCREEN
:
674 case FILE_DEVICE_SOUND
:
675 case FILE_DEVICE_MODEM
:
676 return FILE_TYPE_CHAR
;
678 case FILE_DEVICE_NAMED_PIPE
:
679 return FILE_TYPE_PIPE
;
682 return FILE_TYPE_UNKNOWN
;
690 GetFileSize(HANDLE hFile
,
691 LPDWORD lpFileSizeHigh
)
694 FILE_STANDARD_INFORMATION FileStandard
;
695 IO_STATUS_BLOCK IoStatusBlock
;
697 errCode
= NtQueryInformationFile(hFile
,
700 sizeof(FILE_STANDARD_INFORMATION
),
701 FileStandardInformation
);
702 if (!NT_SUCCESS(errCode
))
704 SetLastErrorByStatus(errCode
);
705 if ( lpFileSizeHigh
== NULL
)
714 if ( lpFileSizeHigh
!= NULL
)
715 *lpFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
717 return FileStandard
.EndOfFile
.u
.LowPart
;
728 PLARGE_INTEGER lpFileSize
732 FILE_STANDARD_INFORMATION FileStandard
;
733 IO_STATUS_BLOCK IoStatusBlock
;
735 errCode
= NtQueryInformationFile(hFile
,
738 sizeof(FILE_STANDARD_INFORMATION
),
739 FileStandardInformation
);
740 if (!NT_SUCCESS(errCode
))
742 SetLastErrorByStatus(errCode
);
746 *lpFileSize
= FileStandard
.EndOfFile
;
756 GetCompressedFileSizeA(LPCSTR lpFileName
,
757 LPDWORD lpFileSizeHigh
)
761 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
762 return INVALID_FILE_SIZE
;
764 return GetCompressedFileSizeW(FileNameW
, lpFileSizeHigh
);
772 GetCompressedFileSizeW(LPCWSTR lpFileName
,
773 LPDWORD lpFileSizeHigh
)
775 FILE_COMPRESSION_INFORMATION FileCompression
;
777 IO_STATUS_BLOCK IoStatusBlock
;
780 hFile
= CreateFileW(lpFileName
,
785 FILE_ATTRIBUTE_NORMAL
,
788 if (hFile
== INVALID_HANDLE_VALUE
)
789 return INVALID_FILE_SIZE
;
791 errCode
= NtQueryInformationFile(hFile
,
794 sizeof(FILE_COMPRESSION_INFORMATION
),
795 FileCompressionInformation
);
799 if (!NT_SUCCESS(errCode
))
801 SetLastErrorByStatus(errCode
);
802 return INVALID_FILE_SIZE
;
806 *lpFileSizeHigh
= FileCompression
.CompressedFileSize
.u
.HighPart
;
808 SetLastError(NO_ERROR
);
809 return FileCompression
.CompressedFileSize
.u
.LowPart
;
817 GetFileInformationByHandle(HANDLE hFile
,
818 LPBY_HANDLE_FILE_INFORMATION lpFileInformation
)
822 FILE_FS_VOLUME_INFORMATION FileFsVolume
;
827 FILE_BASIC_INFORMATION FileBasic
;
828 FILE_INTERNAL_INFORMATION FileInternal
;
829 FILE_STANDARD_INFORMATION FileStandard
;
831 IO_STATUS_BLOCK IoStatusBlock
;
833 if(IsConsoleHandle(hFile
))
835 SetLastError(ERROR_INVALID_HANDLE
);
839 errCode
= NtQueryInformationFile(hFile
,
842 sizeof(FILE_BASIC_INFORMATION
),
843 FileBasicInformation
);
844 if (!NT_SUCCESS(errCode
))
846 SetLastErrorByStatus(errCode
);
850 lpFileInformation
->dwFileAttributes
= (DWORD
)FileBasic
.FileAttributes
;
852 lpFileInformation
->ftCreationTime
.dwHighDateTime
= FileBasic
.CreationTime
.u
.HighPart
;
853 lpFileInformation
->ftCreationTime
.dwLowDateTime
= FileBasic
.CreationTime
.u
.LowPart
;
855 lpFileInformation
->ftLastAccessTime
.dwHighDateTime
= FileBasic
.LastAccessTime
.u
.HighPart
;
856 lpFileInformation
->ftLastAccessTime
.dwLowDateTime
= FileBasic
.LastAccessTime
.u
.LowPart
;
858 lpFileInformation
->ftLastWriteTime
.dwHighDateTime
= FileBasic
.LastWriteTime
.u
.HighPart
;
859 lpFileInformation
->ftLastWriteTime
.dwLowDateTime
= FileBasic
.LastWriteTime
.u
.LowPart
;
861 errCode
= NtQueryInformationFile(hFile
,
864 sizeof(FILE_INTERNAL_INFORMATION
),
865 FileInternalInformation
);
866 if (!NT_SUCCESS(errCode
))
868 SetLastErrorByStatus(errCode
);
872 lpFileInformation
->nFileIndexHigh
= FileInternal
.IndexNumber
.u
.HighPart
;
873 lpFileInformation
->nFileIndexLow
= FileInternal
.IndexNumber
.u
.LowPart
;
875 errCode
= NtQueryVolumeInformationFile(hFile
,
878 sizeof(FileFsVolume
),
879 FileFsVolumeInformation
);
880 if (!NT_SUCCESS(errCode
))
882 SetLastErrorByStatus(errCode
);
886 lpFileInformation
->dwVolumeSerialNumber
= FileFsVolume
.FileFsVolume
.VolumeSerialNumber
;
888 errCode
= NtQueryInformationFile(hFile
,
891 sizeof(FILE_STANDARD_INFORMATION
),
892 FileStandardInformation
);
893 if (!NT_SUCCESS(errCode
))
895 SetLastErrorByStatus(errCode
);
899 lpFileInformation
->nNumberOfLinks
= FileStandard
.NumberOfLinks
;
900 lpFileInformation
->nFileSizeHigh
= FileStandard
.EndOfFile
.u
.HighPart
;
901 lpFileInformation
->nFileSizeLow
= FileStandard
.EndOfFile
.u
.LowPart
;
911 GetFileAttributesExW(LPCWSTR lpFileName
,
912 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
913 LPVOID lpFileInformation
)
915 FILE_NETWORK_OPEN_INFORMATION FileInformation
;
916 OBJECT_ATTRIBUTES ObjectAttributes
;
917 UNICODE_STRING FileName
;
919 WIN32_FILE_ATTRIBUTE_DATA
* FileAttributeData
;
921 TRACE("GetFileAttributesExW(%S) called\n", lpFileName
);
924 if (fInfoLevelId
!= GetFileExInfoStandard
|| lpFileInformation
== NULL
)
926 SetLastError(ERROR_INVALID_PARAMETER
);
930 /* Validate and translate the filename */
931 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
936 WARN ("Invalid path '%S'\n", lpFileName
);
937 SetLastError (ERROR_BAD_PATHNAME
);
941 /* build the object attributes */
942 InitializeObjectAttributes (&ObjectAttributes
,
944 OBJ_CASE_INSENSITIVE
,
948 /* Get file attributes */
949 Status
= NtQueryFullAttributesFile(&ObjectAttributes
,
952 RtlFreeUnicodeString (&FileName
);
953 if (!NT_SUCCESS (Status
))
955 WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status
);
956 SetLastErrorByStatus (Status
);
960 FileAttributeData
= (WIN32_FILE_ATTRIBUTE_DATA
*)lpFileInformation
;
961 FileAttributeData
->dwFileAttributes
= FileInformation
.FileAttributes
;
962 FileAttributeData
->ftCreationTime
.dwLowDateTime
= FileInformation
.CreationTime
.u
.LowPart
;
963 FileAttributeData
->ftCreationTime
.dwHighDateTime
= FileInformation
.CreationTime
.u
.HighPart
;
964 FileAttributeData
->ftLastAccessTime
.dwLowDateTime
= FileInformation
.LastAccessTime
.u
.LowPart
;
965 FileAttributeData
->ftLastAccessTime
.dwHighDateTime
= FileInformation
.LastAccessTime
.u
.HighPart
;
966 FileAttributeData
->ftLastWriteTime
.dwLowDateTime
= FileInformation
.LastWriteTime
.u
.LowPart
;
967 FileAttributeData
->ftLastWriteTime
.dwHighDateTime
= FileInformation
.LastWriteTime
.u
.HighPart
;
968 FileAttributeData
->nFileSizeLow
= FileInformation
.EndOfFile
.u
.LowPart
;
969 FileAttributeData
->nFileSizeHigh
= FileInformation
.EndOfFile
.u
.HighPart
;
978 GetFileAttributesExA(LPCSTR lpFileName
,
979 GET_FILEEX_INFO_LEVELS fInfoLevelId
,
980 LPVOID lpFileInformation
)
984 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
987 return GetFileAttributesExW(FileNameW
, fInfoLevelId
, lpFileInformation
);
995 GetFileAttributesA(LPCSTR lpFileName
)
997 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData
;
1001 if (!lpFileName
|| !(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
1002 return INVALID_FILE_ATTRIBUTES
;
1004 ret
= GetFileAttributesExW(FileNameW
, GetFileExInfoStandard
, &FileAttributeData
);
1006 return ret
? FileAttributeData
.dwFileAttributes
: INVALID_FILE_ATTRIBUTES
;
1014 GetFileAttributesW(LPCWSTR lpFileName
)
1016 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData
;
1019 TRACE ("GetFileAttributeW(%S) called\n", lpFileName
);
1021 Result
= GetFileAttributesExW(lpFileName
, GetFileExInfoStandard
, &FileAttributeData
);
1023 return Result
? FileAttributeData
.dwFileAttributes
: INVALID_FILE_ATTRIBUTES
;
1031 GetFileAttributesByHandle(IN HANDLE hFile
,
1032 OUT LPDWORD dwFileAttributes
,
1035 FILE_BASIC_INFORMATION FileBasic
;
1036 IO_STATUS_BLOCK IoStatusBlock
;
1039 UNREFERENCED_PARAMETER(dwFlags
);
1041 if (IsConsoleHandle(hFile
))
1043 SetLastError(ERROR_INVALID_HANDLE
);
1047 Status
= NtQueryInformationFile(hFile
,
1051 FileBasicInformation
);
1052 if (NT_SUCCESS(Status
))
1054 *dwFileAttributes
= FileBasic
.FileAttributes
;
1058 SetLastErrorByStatus(Status
);
1067 SetFileAttributesByHandle(IN HANDLE hFile
,
1068 IN DWORD dwFileAttributes
,
1071 FILE_BASIC_INFORMATION FileBasic
;
1072 IO_STATUS_BLOCK IoStatusBlock
;
1075 UNREFERENCED_PARAMETER(dwFlags
);
1077 if (IsConsoleHandle(hFile
))
1079 SetLastError(ERROR_INVALID_HANDLE
);
1083 Status
= NtQueryInformationFile(hFile
,
1087 FileBasicInformation
);
1088 if (NT_SUCCESS(Status
))
1090 FileBasic
.FileAttributes
= dwFileAttributes
;
1092 Status
= NtSetInformationFile(hFile
,
1096 FileBasicInformation
);
1099 if (!NT_SUCCESS(Status
))
1101 SetLastErrorByStatus(Status
);
1115 DWORD dwFileAttributes
)
1119 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
1122 return SetFileAttributesW(FileNameW
, dwFileAttributes
);
1130 SetFileAttributesW(LPCWSTR lpFileName
,
1131 DWORD dwFileAttributes
)
1133 FILE_BASIC_INFORMATION FileInformation
;
1134 OBJECT_ATTRIBUTES ObjectAttributes
;
1135 IO_STATUS_BLOCK IoStatusBlock
;
1136 UNICODE_STRING FileName
;
1140 TRACE ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName
, dwFileAttributes
);
1142 /* Validate and translate the filename */
1143 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
1148 WARN ("Invalid path\n");
1149 SetLastError (ERROR_BAD_PATHNAME
);
1152 TRACE ("FileName: \'%wZ\'\n", &FileName
);
1154 /* build the object attributes */
1155 InitializeObjectAttributes (&ObjectAttributes
,
1157 OBJ_CASE_INSENSITIVE
,
1162 Status
= NtOpenFile (&FileHandle
,
1163 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
,
1166 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1167 FILE_SYNCHRONOUS_IO_NONALERT
);
1168 RtlFreeUnicodeString (&FileName
);
1169 if (!NT_SUCCESS (Status
))
1171 WARN ("NtOpenFile() failed (Status %lx)\n", Status
);
1172 SetLastErrorByStatus (Status
);
1176 Status
= NtQueryInformationFile(FileHandle
,
1179 sizeof(FILE_BASIC_INFORMATION
),
1180 FileBasicInformation
);
1181 if (!NT_SUCCESS(Status
))
1183 WARN ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status
);
1184 NtClose (FileHandle
);
1185 SetLastErrorByStatus (Status
);
1189 FileInformation
.FileAttributes
= dwFileAttributes
;
1190 Status
= NtSetInformationFile(FileHandle
,
1193 sizeof(FILE_BASIC_INFORMATION
),
1194 FileBasicInformation
);
1195 NtClose (FileHandle
);
1196 if (!NT_SUCCESS(Status
))
1198 WARN ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status
);
1199 SetLastErrorByStatus (Status
);
1209 /***********************************************************************
1210 * GetTempFileNameA (KERNEL32.@)
1212 UINT WINAPI
GetTempFileNameA( LPCSTR path
, LPCSTR prefix
, UINT unique
, LPSTR buffer
)
1214 WCHAR BufferW
[MAX_PATH
];
1219 if (!(PathW
= FilenameA2W(path
, FALSE
)))
1223 FilenameA2W_N(PrefixW
, 3+1, prefix
, -1);
1225 ret
= GetTempFileNameW(PathW
, prefix
? PrefixW
: NULL
, unique
, BufferW
);
1228 FilenameW2A_N(buffer
, MAX_PATH
, BufferW
, -1);
1233 /***********************************************************************
1234 * GetTempFileNameW (KERNEL32.@)
1236 UINT WINAPI
GetTempFileNameW( LPCWSTR path
, LPCWSTR prefix
, UINT unique
, LPWSTR buffer
)
1238 static const WCHAR formatW
[] = L
"%x.tmp";
1243 if ( !path
|| !buffer
)
1245 SetLastError( ERROR_INVALID_PARAMETER
);
1249 wcscpy( buffer
, path
);
1250 p
= buffer
+ wcslen(buffer
);
1252 /* add a \, if there isn't one */
1253 if ((p
== buffer
) || (p
[-1] != '\\')) *p
++ = '\\';
1256 for (i
= 3; (i
> 0) && (*prefix
); i
--) *p
++ = *prefix
++;
1260 if (unique
) swprintf( p
, formatW
, unique
);
1263 /* get a "random" unique number and try to create the file */
1265 UINT num
= GetTickCount() & 0xffff;
1271 swprintf( p
, formatW
, unique
);
1272 handle
= CreateFileW( buffer
, GENERIC_WRITE
, 0, NULL
,
1273 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
1274 if (handle
!= INVALID_HANDLE_VALUE
)
1275 { /* We created it */
1276 TRACE("created %S\n", buffer
);
1277 CloseHandle( handle
);
1280 if (GetLastError() != ERROR_FILE_EXISTS
&&
1281 GetLastError() != ERROR_SHARING_VIOLATION
)
1282 break; /* No need to go on */
1283 if (!(++unique
& 0xffff)) unique
= 1;
1284 } while (unique
!= num
);
1287 TRACE("returning %S\n", buffer
);
1299 GetFileTime(HANDLE hFile
,
1300 LPFILETIME lpCreationTime
,
1301 LPFILETIME lpLastAccessTime
,
1302 LPFILETIME lpLastWriteTime
)
1304 IO_STATUS_BLOCK IoStatusBlock
;
1305 FILE_BASIC_INFORMATION FileBasic
;
1308 if(IsConsoleHandle(hFile
))
1310 SetLastError(ERROR_INVALID_HANDLE
);
1314 Status
= NtQueryInformationFile(hFile
,
1317 sizeof(FILE_BASIC_INFORMATION
),
1318 FileBasicInformation
);
1319 if (!NT_SUCCESS(Status
))
1321 SetLastErrorByStatus(Status
);
1326 memcpy(lpCreationTime
, &FileBasic
.CreationTime
, sizeof(FILETIME
));
1327 if (lpLastAccessTime
)
1328 memcpy(lpLastAccessTime
, &FileBasic
.LastAccessTime
, sizeof(FILETIME
));
1329 if (lpLastWriteTime
)
1330 memcpy(lpLastWriteTime
, &FileBasic
.LastWriteTime
, sizeof(FILETIME
));
1340 SetFileTime(HANDLE hFile
,
1341 CONST FILETIME
*lpCreationTime
,
1342 CONST FILETIME
*lpLastAccessTime
,
1343 CONST FILETIME
*lpLastWriteTime
)
1345 FILE_BASIC_INFORMATION FileBasic
;
1346 IO_STATUS_BLOCK IoStatusBlock
;
1349 if(IsConsoleHandle(hFile
))
1351 SetLastError(ERROR_INVALID_HANDLE
);
1355 Status
= NtQueryInformationFile(hFile
,
1358 sizeof(FILE_BASIC_INFORMATION
),
1359 FileBasicInformation
);
1360 if (!NT_SUCCESS(Status
))
1362 SetLastErrorByStatus(Status
);
1367 memcpy(&FileBasic
.CreationTime
, lpCreationTime
, sizeof(FILETIME
));
1368 if (lpLastAccessTime
)
1369 memcpy(&FileBasic
.LastAccessTime
, lpLastAccessTime
, sizeof(FILETIME
));
1370 if (lpLastWriteTime
)
1371 memcpy(&FileBasic
.LastWriteTime
, lpLastWriteTime
, sizeof(FILETIME
));
1373 // should i initialize changetime ???
1375 Status
= NtSetInformationFile(hFile
,
1378 sizeof(FILE_BASIC_INFORMATION
),
1379 FileBasicInformation
);
1380 if (!NT_SUCCESS(Status
))
1382 SetLastErrorByStatus(Status
);
1391 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1396 SetEndOfFile(HANDLE hFile
)
1398 IO_STATUS_BLOCK IoStatusBlock
;
1399 FILE_END_OF_FILE_INFORMATION EndOfFileInfo
;
1400 FILE_ALLOCATION_INFORMATION FileAllocationInfo
;
1401 FILE_POSITION_INFORMATION FilePosInfo
;
1404 if(IsConsoleHandle(hFile
))
1406 SetLastError(ERROR_INVALID_HANDLE
);
1410 //get current position
1411 Status
= NtQueryInformationFile(
1415 sizeof(FILE_POSITION_INFORMATION
),
1416 FilePositionInformation
1419 if (!NT_SUCCESS(Status
)){
1420 SetLastErrorByStatus(Status
);
1424 EndOfFileInfo
.EndOfFile
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1428 This call is not supposed to free up any space after the eof marker
1429 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1430 But...most file systems dispatch both FileEndOfFileInformation
1431 and FileAllocationInformation as they were the same command.
1434 Status
= NtSetInformationFile(
1436 &IoStatusBlock
, //out
1438 sizeof(FILE_END_OF_FILE_INFORMATION
),
1439 FileEndOfFileInformation
1442 if (!NT_SUCCESS(Status
)){
1443 SetLastErrorByStatus(Status
);
1447 FileAllocationInfo
.AllocationSize
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1450 Status
= NtSetInformationFile(
1452 &IoStatusBlock
, //out
1453 &FileAllocationInfo
,
1454 sizeof(FILE_ALLOCATION_INFORMATION
),
1455 FileAllocationInformation
1458 if (!NT_SUCCESS(Status
)){
1459 SetLastErrorByStatus(Status
);
1475 LONGLONG ValidDataLength
1478 IO_STATUS_BLOCK IoStatusBlock
;
1479 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation
;
1482 ValidDataLengthInformation
.ValidDataLength
.QuadPart
= ValidDataLength
;
1484 Status
= NtSetInformationFile(
1486 &IoStatusBlock
, //out
1487 &ValidDataLengthInformation
,
1488 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION
),
1489 FileValidDataLengthInformation
1492 if (!NT_SUCCESS(Status
)){
1493 SetLastErrorByStatus(Status
);
1509 LPCWSTR lpShortName
)
1513 UNICODE_STRING ShortName
;
1514 IO_STATUS_BLOCK IoStatusBlock
;
1515 PFILE_NAME_INFORMATION FileNameInfo
;
1517 if(IsConsoleHandle(hFile
))
1519 SetLastError(ERROR_INVALID_HANDLE
);
1525 SetLastError(ERROR_INVALID_PARAMETER
);
1529 RtlInitUnicodeString(&ShortName
, lpShortName
);
1531 NeededSize
= sizeof(FILE_NAME_INFORMATION
) + ShortName
.Length
+ sizeof(WCHAR
);
1532 if(!(FileNameInfo
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
)))
1534 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1538 FileNameInfo
->FileNameLength
= ShortName
.Length
;
1539 RtlCopyMemory(FileNameInfo
->FileName
, ShortName
.Buffer
, ShortName
.Length
);
1541 Status
= NtSetInformationFile(hFile
,
1542 &IoStatusBlock
, //out
1545 FileShortNameInformation
);
1547 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo
);
1548 if(!NT_SUCCESS(Status
))
1550 SetLastErrorByStatus(Status
);
1570 if(IsConsoleHandle(hFile
))
1572 SetLastError(ERROR_INVALID_HANDLE
);
1578 SetLastError(ERROR_INVALID_PARAMETER
);
1582 if (!(ShortNameW
= FilenameA2W(lpShortName
, FALSE
)))
1585 return SetFileShortNameW(hFile
, ShortNameW
);
1594 CheckNameLegalDOS8Dot3W(
1596 LPSTR lpOemName OPTIONAL
,
1597 DWORD OemNameSize OPTIONAL
,
1598 PBOOL pbNameContainsSpaces OPTIONAL
,
1602 UNICODE_STRING Name
;
1603 ANSI_STRING AnsiName
;
1605 if(lpName
== NULL
||
1606 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
1607 pbNameLegal
== NULL
)
1609 SetLastError(ERROR_INVALID_PARAMETER
);
1613 if(lpOemName
!= NULL
)
1615 AnsiName
.Buffer
= lpOemName
;
1616 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
1617 AnsiName
.Length
= 0;
1620 RtlInitUnicodeString(&Name
, lpName
);
1622 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
1623 (lpOemName
? &AnsiName
: NULL
),
1624 (BOOLEAN
*)pbNameContainsSpaces
);
1635 CheckNameLegalDOS8Dot3A(
1637 LPSTR lpOemName OPTIONAL
,
1638 DWORD OemNameSize OPTIONAL
,
1639 PBOOL pbNameContainsSpaces OPTIONAL
,
1643 UNICODE_STRING Name
;
1644 ANSI_STRING AnsiName
, AnsiInputName
;
1647 if(lpName
== NULL
||
1648 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
1649 pbNameLegal
== NULL
)
1651 SetLastError(ERROR_INVALID_PARAMETER
);
1655 if(lpOemName
!= NULL
)
1657 AnsiName
.Buffer
= lpOemName
;
1658 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
1659 AnsiName
.Length
= 0;
1662 RtlInitAnsiString(&AnsiInputName
, (LPSTR
)lpName
);
1664 Status
= RtlAnsiStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
1666 Status
= RtlOemStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
1668 if(!NT_SUCCESS(Status
))
1670 SetLastErrorByStatus(Status
);
1674 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
1675 (lpOemName
? &AnsiName
: NULL
),
1676 (BOOLEAN
*)pbNameContainsSpaces
);
1678 RtlFreeUnicodeString(&Name
);
1689 GetFinalPathNameByHandleA(IN HANDLE hFile
,
1690 OUT LPSTR lpszFilePath
,
1691 IN DWORD cchFilePath
,
1694 WCHAR FilePathW
[MAX_PATH
];
1695 UNICODE_STRING FilePathU
;
1696 DWORD PrevLastError
;
1699 if (cchFilePath
!= 0 &&
1700 cchFilePath
> sizeof(FilePathW
) / sizeof(FilePathW
[0]))
1702 FilePathU
.Length
= 0;
1703 FilePathU
.MaximumLength
= (USHORT
)cchFilePath
* sizeof(WCHAR
);
1704 FilePathU
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
1706 FilePathU
.MaximumLength
);
1707 if (FilePathU
.Buffer
== NULL
)
1709 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1715 FilePathU
.Length
= 0;
1716 FilePathU
.MaximumLength
= sizeof(FilePathW
);
1717 FilePathU
.Buffer
= FilePathW
;
1720 /* save the last error code */
1721 PrevLastError
= GetLastError();
1722 SetLastError(ERROR_SUCCESS
);
1724 /* call the unicode version that does all the work */
1725 Ret
= GetFinalPathNameByHandleW(hFile
,
1730 if (GetLastError() == ERROR_SUCCESS
)
1732 /* no error, restore the last error code and convert the string */
1733 SetLastError(PrevLastError
);
1735 Ret
= FilenameU2A_FitOrFail(lpszFilePath
,
1740 /* free allocated memory if necessary */
1741 if (FilePathU
.Buffer
!= FilePathW
)
1743 RtlFreeHeap(RtlGetProcessHeap(),
1757 GetFinalPathNameByHandleW(IN HANDLE hFile
,
1758 OUT LPWSTR lpszFilePath
,
1759 IN DWORD cchFilePath
,
1762 if (dwFlags
& ~(VOLUME_NAME_DOS
| VOLUME_NAME_GUID
| VOLUME_NAME_NT
|
1763 VOLUME_NAME_NONE
| FILE_NAME_NORMALIZED
| FILE_NAME_OPENED
))
1765 SetLastError(ERROR_INVALID_PARAMETER
);
1779 SetFileBandwidthReservation(IN HANDLE hFile
,
1780 IN DWORD nPeriodMilliseconds
,
1781 IN DWORD nBytesPerPeriod
,
1782 IN BOOL bDiscardable
,
1783 OUT LPDWORD lpTransferSize
,
1784 OUT LPDWORD lpNumOutstandingRequests
)
1796 GetFileBandwidthReservation(IN HANDLE hFile
,
1797 OUT LPDWORD lpPeriodMilliseconds
,
1798 OUT LPDWORD lpBytesPerPeriod
,
1799 OUT LPBOOL pDiscardable
,
1800 OUT LPDWORD lpTransferSize
,
1801 OUT LPDWORD lpNumOutstandingRequests
)
1813 SetFileCompletionNotificationModes(IN HANDLE FileHandle
,
1816 if (Flags
& ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
| FILE_SKIP_SET_EVENT_ON_HANDLE
))
1818 SetLastError(ERROR_INVALID_PARAMETER
);
1832 OpenFileById(IN HANDLE hFile
,
1833 IN LPFILE_ID_DESCRIPTOR lpFileID
,
1834 IN DWORD dwDesiredAccess
,
1835 IN DWORD dwShareMode
,
1836 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL
,
1840 return INVALID_HANDLE_VALUE
;
1849 LPCSTR lpReplacedFileName
,
1850 LPCSTR lpReplacementFileName
,
1851 LPCSTR lpBackupFileName
,
1852 DWORD dwReplaceFlags
,
1857 WCHAR
*replacedW
, *replacementW
, *backupW
= NULL
;
1860 /* This function only makes sense when the first two parameters are defined */
1861 if (!lpReplacedFileName
|| !(replacedW
= FilenameA2W(lpReplacedFileName
, TRUE
)))
1863 SetLastError(ERROR_INVALID_PARAMETER
);
1867 if (!lpReplacementFileName
|| !(replacementW
= FilenameA2W(lpReplacementFileName
, TRUE
)))
1869 HeapFree(GetProcessHeap(), 0, replacedW
);
1870 SetLastError(ERROR_INVALID_PARAMETER
);
1874 /* The backup parameter, however, is optional */
1875 if (lpBackupFileName
)
1877 if (!(backupW
= FilenameA2W(lpBackupFileName
, TRUE
)))
1879 HeapFree(GetProcessHeap(), 0, replacedW
);
1880 HeapFree(GetProcessHeap(), 0, replacementW
);
1881 SetLastError(ERROR_INVALID_PARAMETER
);
1886 ret
= ReplaceFileW(replacedW
, replacementW
, backupW
, dwReplaceFlags
, lpExclude
, lpReserved
);
1887 HeapFree(GetProcessHeap(), 0, replacedW
);
1888 HeapFree(GetProcessHeap(), 0, replacementW
);
1889 HeapFree(GetProcessHeap(), 0, backupW
);
1900 LPCWSTR lpReplacedFileName
,
1901 LPCWSTR lpReplacementFileName
,
1902 LPCWSTR lpBackupFileName
,
1903 DWORD dwReplaceFlags
,
1908 HANDLE hReplaced
= NULL
, hReplacement
= NULL
;
1909 UNICODE_STRING NtReplacedName
= { 0, 0, NULL
};
1910 UNICODE_STRING NtReplacementName
= { 0, 0, NULL
};
1911 DWORD Error
= ERROR_SUCCESS
;
1914 IO_STATUS_BLOCK IoStatusBlock
;
1915 OBJECT_ATTRIBUTES ObjectAttributes
;
1916 PVOID Buffer
= NULL
;
1919 FIXME("Ignoring flags %x\n", dwReplaceFlags
);
1921 /* First two arguments are mandatory */
1922 if (!lpReplacedFileName
|| !lpReplacementFileName
)
1924 SetLastError(ERROR_INVALID_PARAMETER
);
1929 if(lpBackupFileName
)
1931 if(!CopyFileW(lpReplacedFileName
, lpBackupFileName
, FALSE
))
1933 Error
= GetLastError();
1938 /* Open the "replaced" file for reading and writing */
1939 if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName
, &NtReplacedName
, NULL
, NULL
)))
1941 Error
= ERROR_PATH_NOT_FOUND
;
1945 InitializeObjectAttributes(&ObjectAttributes
,
1947 OBJ_CASE_INSENSITIVE
,
1951 Status
= NtOpenFile(&hReplaced
,
1952 GENERIC_READ
| GENERIC_WRITE
| DELETE
| SYNCHRONIZE
| WRITE_DAC
,
1955 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1956 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
1958 if (!NT_SUCCESS(Status
))
1960 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1961 Error
= ERROR_FILE_NOT_FOUND
;
1963 Error
= ERROR_UNABLE_TO_REMOVE_REPLACED
;
1968 SetEndOfFile(hReplaced
) ;
1971 * Open the replacement file for reading, writing, and deleting
1972 * (deleting is needed when finished)
1974 if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName
, &NtReplacementName
, NULL
, NULL
)))
1976 Error
= ERROR_PATH_NOT_FOUND
;
1980 InitializeObjectAttributes(&ObjectAttributes
,
1982 OBJ_CASE_INSENSITIVE
,
1986 Status
= NtOpenFile(&hReplacement
,
1987 GENERIC_READ
| DELETE
| SYNCHRONIZE
,
1991 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
| FILE_DELETE_ON_CLOSE
);
1993 if (!NT_SUCCESS(Status
))
1995 Error
= RtlNtStatusToDosError(Status
);
1999 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, 0x10000) ;
2002 Error
= ERROR_NOT_ENOUGH_MEMORY
;
2005 while (Status
!= STATUS_END_OF_FILE
)
2007 Status
= NtReadFile(hReplacement
, NULL
, NULL
, NULL
, &IoStatusBlock
, Buffer
, 0x10000, NULL
, NULL
) ;
2008 if (NT_SUCCESS(Status
))
2010 Status
= NtWriteFile(hReplaced
, NULL
, NULL
, NULL
, &IoStatusBlock
, Buffer
,
2011 IoStatusBlock
.Information
, NULL
, NULL
) ;
2012 if (!NT_SUCCESS(Status
))
2014 Error
= RtlNtStatusToDosError(Status
);
2018 else if (Status
!= STATUS_END_OF_FILE
)
2020 Error
= RtlNtStatusToDosError(Status
);
2027 /* Perform resource cleanup */
2029 if (hReplaced
) NtClose(hReplaced
);
2030 if (hReplacement
) NtClose(hReplacement
);
2031 if (Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
2033 if (NtReplacementName
.Buffer
)
2034 RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName
.Buffer
);
2035 if (NtReplacedName
.Buffer
)
2036 RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName
.Buffer
);
2038 /* If there was an error, set the error code */
2041 TRACE("ReplaceFileW failed (error=%d)\n", Error
);
2042 SetLastError(Error
);