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 *****************************************************************/
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(HANDLE hFile
)
412 IO_STATUS_BLOCK IoStatusBlock
;
414 hFile
= TranslateStdHandle(hFile
);
416 if (IsConsoleHandle(hFile
))
421 errCode
= NtFlushBuffersFile(hFile
,
423 if (!NT_SUCCESS(errCode
))
425 SetLastErrorByStatus(errCode
);
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.@)
1215 UINT WINAPI
GetTempFileNameA( LPCSTR path
, LPCSTR prefix
, UINT unique
, LPSTR buffer
)
1217 WCHAR BufferW
[MAX_PATH
];
1222 if (!(PathW
= FilenameA2W(path
, FALSE
)))
1226 FilenameA2W_N(PrefixW
, 3+1, prefix
, -1);
1228 ret
= GetTempFileNameW(PathW
, prefix
? PrefixW
: NULL
, unique
, BufferW
);
1231 FilenameW2A_N(buffer
, MAX_PATH
, BufferW
, -1);
1236 /***********************************************************************
1237 * GetTempFileNameW (KERNEL32.@)
1239 UINT WINAPI
GetTempFileNameW( LPCWSTR path
, LPCWSTR prefix
, UINT unique
, LPWSTR buffer
)
1241 static const WCHAR formatW
[] = L
"%x.tmp";
1246 if ( !path
|| !buffer
)
1248 SetLastError( ERROR_INVALID_PARAMETER
);
1252 wcscpy( buffer
, path
);
1253 p
= buffer
+ wcslen(buffer
);
1255 /* add a \, if there isn't one */
1256 if ((p
== buffer
) || (p
[-1] != '\\')) *p
++ = '\\';
1259 for (i
= 3; (i
> 0) && (*prefix
); i
--) *p
++ = *prefix
++;
1263 if (unique
) swprintf( p
, formatW
, unique
);
1266 /* get a "random" unique number and try to create the file */
1268 UINT num
= GetTickCount() & 0xffff;
1274 swprintf( p
, formatW
, unique
);
1275 handle
= CreateFileW( buffer
, GENERIC_WRITE
, 0, NULL
,
1276 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
1277 if (handle
!= INVALID_HANDLE_VALUE
)
1278 { /* We created it */
1279 TRACE("created %S\n", buffer
);
1280 CloseHandle( handle
);
1283 if (GetLastError() != ERROR_FILE_EXISTS
&&
1284 GetLastError() != ERROR_SHARING_VIOLATION
)
1285 break; /* No need to go on */
1286 if (!(++unique
& 0xffff)) unique
= 1;
1287 } while (unique
!= num
);
1290 TRACE("returning %S\n", buffer
);
1302 GetFileTime(HANDLE hFile
,
1303 LPFILETIME lpCreationTime
,
1304 LPFILETIME lpLastAccessTime
,
1305 LPFILETIME lpLastWriteTime
)
1307 IO_STATUS_BLOCK IoStatusBlock
;
1308 FILE_BASIC_INFORMATION FileBasic
;
1311 if(IsConsoleHandle(hFile
))
1313 SetLastError(ERROR_INVALID_HANDLE
);
1317 Status
= NtQueryInformationFile(hFile
,
1320 sizeof(FILE_BASIC_INFORMATION
),
1321 FileBasicInformation
);
1322 if (!NT_SUCCESS(Status
))
1324 SetLastErrorByStatus(Status
);
1329 memcpy(lpCreationTime
, &FileBasic
.CreationTime
, sizeof(FILETIME
));
1330 if (lpLastAccessTime
)
1331 memcpy(lpLastAccessTime
, &FileBasic
.LastAccessTime
, sizeof(FILETIME
));
1332 if (lpLastWriteTime
)
1333 memcpy(lpLastWriteTime
, &FileBasic
.LastWriteTime
, sizeof(FILETIME
));
1343 SetFileTime(HANDLE hFile
,
1344 CONST FILETIME
*lpCreationTime
,
1345 CONST FILETIME
*lpLastAccessTime
,
1346 CONST FILETIME
*lpLastWriteTime
)
1348 FILE_BASIC_INFORMATION FileBasic
;
1349 IO_STATUS_BLOCK IoStatusBlock
;
1352 if(IsConsoleHandle(hFile
))
1354 SetLastError(ERROR_INVALID_HANDLE
);
1358 Status
= NtQueryInformationFile(hFile
,
1361 sizeof(FILE_BASIC_INFORMATION
),
1362 FileBasicInformation
);
1363 if (!NT_SUCCESS(Status
))
1365 SetLastErrorByStatus(Status
);
1370 memcpy(&FileBasic
.CreationTime
, lpCreationTime
, sizeof(FILETIME
));
1371 if (lpLastAccessTime
)
1372 memcpy(&FileBasic
.LastAccessTime
, lpLastAccessTime
, sizeof(FILETIME
));
1373 if (lpLastWriteTime
)
1374 memcpy(&FileBasic
.LastWriteTime
, lpLastWriteTime
, sizeof(FILETIME
));
1376 // should i initialize changetime ???
1378 Status
= NtSetInformationFile(hFile
,
1381 sizeof(FILE_BASIC_INFORMATION
),
1382 FileBasicInformation
);
1383 if (!NT_SUCCESS(Status
))
1385 SetLastErrorByStatus(Status
);
1394 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1399 SetEndOfFile(HANDLE hFile
)
1401 IO_STATUS_BLOCK IoStatusBlock
;
1402 FILE_END_OF_FILE_INFORMATION EndOfFileInfo
;
1403 FILE_ALLOCATION_INFORMATION FileAllocationInfo
;
1404 FILE_POSITION_INFORMATION FilePosInfo
;
1407 if(IsConsoleHandle(hFile
))
1409 SetLastError(ERROR_INVALID_HANDLE
);
1413 //get current position
1414 Status
= NtQueryInformationFile(
1418 sizeof(FILE_POSITION_INFORMATION
),
1419 FilePositionInformation
1422 if (!NT_SUCCESS(Status
)){
1423 SetLastErrorByStatus(Status
);
1427 EndOfFileInfo
.EndOfFile
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1431 This call is not supposed to free up any space after the eof marker
1432 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1433 But...most file systems dispatch both FileEndOfFileInformation
1434 and FileAllocationInformation as they were the same command.
1437 Status
= NtSetInformationFile(
1439 &IoStatusBlock
, //out
1441 sizeof(FILE_END_OF_FILE_INFORMATION
),
1442 FileEndOfFileInformation
1445 if (!NT_SUCCESS(Status
)){
1446 SetLastErrorByStatus(Status
);
1450 FileAllocationInfo
.AllocationSize
.QuadPart
= FilePosInfo
.CurrentByteOffset
.QuadPart
;
1453 Status
= NtSetInformationFile(
1455 &IoStatusBlock
, //out
1456 &FileAllocationInfo
,
1457 sizeof(FILE_ALLOCATION_INFORMATION
),
1458 FileAllocationInformation
1461 if (!NT_SUCCESS(Status
)){
1462 SetLastErrorByStatus(Status
);
1478 LONGLONG ValidDataLength
1481 IO_STATUS_BLOCK IoStatusBlock
;
1482 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation
;
1485 ValidDataLengthInformation
.ValidDataLength
.QuadPart
= ValidDataLength
;
1487 Status
= NtSetInformationFile(
1489 &IoStatusBlock
, //out
1490 &ValidDataLengthInformation
,
1491 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION
),
1492 FileValidDataLengthInformation
1495 if (!NT_SUCCESS(Status
)){
1496 SetLastErrorByStatus(Status
);
1512 LPCWSTR lpShortName
)
1516 UNICODE_STRING ShortName
;
1517 IO_STATUS_BLOCK IoStatusBlock
;
1518 PFILE_NAME_INFORMATION FileNameInfo
;
1520 if(IsConsoleHandle(hFile
))
1522 SetLastError(ERROR_INVALID_HANDLE
);
1528 SetLastError(ERROR_INVALID_PARAMETER
);
1532 RtlInitUnicodeString(&ShortName
, lpShortName
);
1534 NeededSize
= sizeof(FILE_NAME_INFORMATION
) + ShortName
.Length
+ sizeof(WCHAR
);
1535 if(!(FileNameInfo
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
)))
1537 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1541 FileNameInfo
->FileNameLength
= ShortName
.Length
;
1542 RtlCopyMemory(FileNameInfo
->FileName
, ShortName
.Buffer
, ShortName
.Length
);
1544 Status
= NtSetInformationFile(hFile
,
1545 &IoStatusBlock
, //out
1548 FileShortNameInformation
);
1550 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo
);
1551 if(!NT_SUCCESS(Status
))
1553 SetLastErrorByStatus(Status
);
1573 if(IsConsoleHandle(hFile
))
1575 SetLastError(ERROR_INVALID_HANDLE
);
1581 SetLastError(ERROR_INVALID_PARAMETER
);
1585 if (!(ShortNameW
= FilenameA2W(lpShortName
, FALSE
)))
1588 return SetFileShortNameW(hFile
, ShortNameW
);
1597 CheckNameLegalDOS8Dot3W(
1599 LPSTR lpOemName OPTIONAL
,
1600 DWORD OemNameSize OPTIONAL
,
1601 PBOOL pbNameContainsSpaces OPTIONAL
,
1605 UNICODE_STRING Name
;
1606 ANSI_STRING AnsiName
;
1608 if(lpName
== NULL
||
1609 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
1610 pbNameLegal
== NULL
)
1612 SetLastError(ERROR_INVALID_PARAMETER
);
1616 if(lpOemName
!= NULL
)
1618 AnsiName
.Buffer
= lpOemName
;
1619 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
1620 AnsiName
.Length
= 0;
1623 RtlInitUnicodeString(&Name
, lpName
);
1625 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
1626 (lpOemName
? &AnsiName
: NULL
),
1627 (BOOLEAN
*)pbNameContainsSpaces
);
1638 CheckNameLegalDOS8Dot3A(
1640 LPSTR lpOemName OPTIONAL
,
1641 DWORD OemNameSize OPTIONAL
,
1642 PBOOL pbNameContainsSpaces OPTIONAL
,
1646 UNICODE_STRING Name
;
1647 ANSI_STRING AnsiName
, AnsiInputName
;
1650 if(lpName
== NULL
||
1651 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
1652 pbNameLegal
== NULL
)
1654 SetLastError(ERROR_INVALID_PARAMETER
);
1658 if(lpOemName
!= NULL
)
1660 AnsiName
.Buffer
= lpOemName
;
1661 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
1662 AnsiName
.Length
= 0;
1665 RtlInitAnsiString(&AnsiInputName
, (LPSTR
)lpName
);
1667 Status
= RtlAnsiStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
1669 Status
= RtlOemStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
1671 if(!NT_SUCCESS(Status
))
1673 SetLastErrorByStatus(Status
);
1677 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
1678 (lpOemName
? &AnsiName
: NULL
),
1679 (BOOLEAN
*)pbNameContainsSpaces
);
1681 RtlFreeUnicodeString(&Name
);
1692 GetFinalPathNameByHandleA(IN HANDLE hFile
,
1693 OUT LPSTR lpszFilePath
,
1694 IN DWORD cchFilePath
,
1697 WCHAR FilePathW
[MAX_PATH
];
1698 UNICODE_STRING FilePathU
;
1699 DWORD PrevLastError
;
1702 if (cchFilePath
!= 0 &&
1703 cchFilePath
> sizeof(FilePathW
) / sizeof(FilePathW
[0]))
1705 FilePathU
.Length
= 0;
1706 FilePathU
.MaximumLength
= (USHORT
)cchFilePath
* sizeof(WCHAR
);
1707 FilePathU
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
1709 FilePathU
.MaximumLength
);
1710 if (FilePathU
.Buffer
== NULL
)
1712 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1718 FilePathU
.Length
= 0;
1719 FilePathU
.MaximumLength
= sizeof(FilePathW
);
1720 FilePathU
.Buffer
= FilePathW
;
1723 /* save the last error code */
1724 PrevLastError
= GetLastError();
1725 SetLastError(ERROR_SUCCESS
);
1727 /* call the unicode version that does all the work */
1728 Ret
= GetFinalPathNameByHandleW(hFile
,
1733 if (GetLastError() == ERROR_SUCCESS
)
1735 /* no error, restore the last error code and convert the string */
1736 SetLastError(PrevLastError
);
1738 Ret
= FilenameU2A_FitOrFail(lpszFilePath
,
1743 /* free allocated memory if necessary */
1744 if (FilePathU
.Buffer
!= FilePathW
)
1746 RtlFreeHeap(RtlGetProcessHeap(),
1760 GetFinalPathNameByHandleW(IN HANDLE hFile
,
1761 OUT LPWSTR lpszFilePath
,
1762 IN DWORD cchFilePath
,
1765 if (dwFlags
& ~(VOLUME_NAME_DOS
| VOLUME_NAME_GUID
| VOLUME_NAME_NT
|
1766 VOLUME_NAME_NONE
| FILE_NAME_NORMALIZED
| FILE_NAME_OPENED
))
1768 SetLastError(ERROR_INVALID_PARAMETER
);
1782 SetFileBandwidthReservation(IN HANDLE hFile
,
1783 IN DWORD nPeriodMilliseconds
,
1784 IN DWORD nBytesPerPeriod
,
1785 IN BOOL bDiscardable
,
1786 OUT LPDWORD lpTransferSize
,
1787 OUT LPDWORD lpNumOutstandingRequests
)
1799 GetFileBandwidthReservation(IN HANDLE hFile
,
1800 OUT LPDWORD lpPeriodMilliseconds
,
1801 OUT LPDWORD lpBytesPerPeriod
,
1802 OUT LPBOOL pDiscardable
,
1803 OUT LPDWORD lpTransferSize
,
1804 OUT LPDWORD lpNumOutstandingRequests
)
1816 SetFileCompletionNotificationModes(IN HANDLE FileHandle
,
1819 if (Flags
& ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
| FILE_SKIP_SET_EVENT_ON_HANDLE
))
1821 SetLastError(ERROR_INVALID_PARAMETER
);
1835 OpenFileById(IN HANDLE hFile
,
1836 IN LPFILE_ID_DESCRIPTOR lpFileID
,
1837 IN DWORD dwDesiredAccess
,
1838 IN DWORD dwShareMode
,
1839 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL
,
1843 return INVALID_HANDLE_VALUE
;
1852 LPCSTR lpReplacedFileName
,
1853 LPCSTR lpReplacementFileName
,
1854 LPCSTR lpBackupFileName
,
1855 DWORD dwReplaceFlags
,
1860 WCHAR
*replacedW
, *replacementW
, *backupW
= NULL
;
1863 /* This function only makes sense when the first two parameters are defined */
1864 if (!lpReplacedFileName
|| !(replacedW
= FilenameA2W(lpReplacedFileName
, TRUE
)))
1866 SetLastError(ERROR_INVALID_PARAMETER
);
1870 if (!lpReplacementFileName
|| !(replacementW
= FilenameA2W(lpReplacementFileName
, TRUE
)))
1872 HeapFree(GetProcessHeap(), 0, replacedW
);
1873 SetLastError(ERROR_INVALID_PARAMETER
);
1877 /* The backup parameter, however, is optional */
1878 if (lpBackupFileName
)
1880 if (!(backupW
= FilenameA2W(lpBackupFileName
, TRUE
)))
1882 HeapFree(GetProcessHeap(), 0, replacedW
);
1883 HeapFree(GetProcessHeap(), 0, replacementW
);
1884 SetLastError(ERROR_INVALID_PARAMETER
);
1889 ret
= ReplaceFileW(replacedW
, replacementW
, backupW
, dwReplaceFlags
, lpExclude
, lpReserved
);
1890 HeapFree(GetProcessHeap(), 0, replacedW
);
1891 HeapFree(GetProcessHeap(), 0, replacementW
);
1892 HeapFree(GetProcessHeap(), 0, backupW
);
1903 LPCWSTR lpReplacedFileName
,
1904 LPCWSTR lpReplacementFileName
,
1905 LPCWSTR lpBackupFileName
,
1906 DWORD dwReplaceFlags
,
1911 HANDLE hReplaced
= NULL
, hReplacement
= NULL
;
1912 UNICODE_STRING NtReplacedName
= { 0, 0, NULL
};
1913 UNICODE_STRING NtReplacementName
= { 0, 0, NULL
};
1914 DWORD Error
= ERROR_SUCCESS
;
1917 IO_STATUS_BLOCK IoStatusBlock
;
1918 OBJECT_ATTRIBUTES ObjectAttributes
;
1919 PVOID Buffer
= NULL
;
1922 FIXME("Ignoring flags %x\n", dwReplaceFlags
);
1924 /* First two arguments are mandatory */
1925 if (!lpReplacedFileName
|| !lpReplacementFileName
)
1927 SetLastError(ERROR_INVALID_PARAMETER
);
1932 if(lpBackupFileName
)
1934 if(!CopyFileW(lpReplacedFileName
, lpBackupFileName
, FALSE
))
1936 Error
= GetLastError();
1941 /* Open the "replaced" file for reading and writing */
1942 if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName
, &NtReplacedName
, NULL
, NULL
)))
1944 Error
= ERROR_PATH_NOT_FOUND
;
1948 InitializeObjectAttributes(&ObjectAttributes
,
1950 OBJ_CASE_INSENSITIVE
,
1954 Status
= NtOpenFile(&hReplaced
,
1955 GENERIC_READ
| GENERIC_WRITE
| DELETE
| SYNCHRONIZE
| WRITE_DAC
,
1958 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1959 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
1961 if (!NT_SUCCESS(Status
))
1963 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1964 Error
= ERROR_FILE_NOT_FOUND
;
1966 Error
= ERROR_UNABLE_TO_REMOVE_REPLACED
;
1971 SetEndOfFile(hReplaced
) ;
1974 * Open the replacement file for reading, writing, and deleting
1975 * (deleting is needed when finished)
1977 if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName
, &NtReplacementName
, NULL
, NULL
)))
1979 Error
= ERROR_PATH_NOT_FOUND
;
1983 InitializeObjectAttributes(&ObjectAttributes
,
1985 OBJ_CASE_INSENSITIVE
,
1989 Status
= NtOpenFile(&hReplacement
,
1990 GENERIC_READ
| DELETE
| SYNCHRONIZE
,
1994 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
| FILE_DELETE_ON_CLOSE
);
1996 if (!NT_SUCCESS(Status
))
1998 Error
= RtlNtStatusToDosError(Status
);
2002 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, 0x10000) ;
2005 Error
= ERROR_NOT_ENOUGH_MEMORY
;
2008 while (Status
!= STATUS_END_OF_FILE
)
2010 Status
= NtReadFile(hReplacement
, NULL
, NULL
, NULL
, &IoStatusBlock
, Buffer
, 0x10000, NULL
, NULL
) ;
2011 if (NT_SUCCESS(Status
))
2013 Status
= NtWriteFile(hReplaced
, NULL
, NULL
, NULL
, &IoStatusBlock
, Buffer
,
2014 IoStatusBlock
.Information
, NULL
, NULL
) ;
2015 if (!NT_SUCCESS(Status
))
2017 Error
= RtlNtStatusToDosError(Status
);
2021 else if (Status
!= STATUS_END_OF_FILE
)
2023 Error
= RtlNtStatusToDosError(Status
);
2030 /* Perform resource cleanup */
2032 if (hReplaced
) NtClose(hReplaced
);
2033 if (hReplacement
) NtClose(hReplacement
);
2034 if (Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
2036 if (NtReplacementName
.Buffer
)
2037 RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName
.Buffer
);
2038 if (NtReplacedName
.Buffer
)
2039 RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName
.Buffer
);
2041 /* If there was an error, set the error code */
2044 TRACE("ReplaceFileW failed (error=%d)\n", Error
);
2045 SetLastError(Error
);