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 *****************************************************************/
15 #include <ddk/ntddk.h>
21 #include <kernel32/kernel32.h>
22 #include <kernel32/error.h>
24 #define LPPROGRESS_ROUTINE void*
27 /* GLOBALS ******************************************************************/
29 WINBOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
32 /* FUNCTIONS ****************************************************************/
35 SetFileApisToOEM(VOID)
37 bIsFileApiAnsi = FALSE;
42 SetFileApisToANSI(VOID)
44 bIsFileApiAnsi = TRUE;
51 return bIsFileApiAnsi;
56 OpenFile(LPCSTR lpFileName,
57 LPOFSTRUCT lpReOpenBuff,
60 OBJECT_ATTRIBUTES ObjectAttributes;
61 IO_STATUS_BLOCK IoStatusBlock;
62 UNICODE_STRING FileNameString;
63 UNICODE_STRING FileNameU;
65 WCHAR PathNameW[MAX_PATH];
66 HANDLE FileHandle = NULL;
71 DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
73 if (lpReOpenBuff == NULL)
78 RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
80 /* convert ansi (or oem) string to unicode */
82 RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
84 RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
86 Len = SearchPathW (NULL,
93 RtlFreeUnicodeString(&FileNameU);
95 if (Len == 0 || Len > OFS_MAXPATHNAME)
97 return (HFILE)INVALID_HANDLE_VALUE;
100 FileName.Buffer = lpReOpenBuff->szPathName;
102 FileName.MaximumLength = OFS_MAXPATHNAME;
104 RtlInitUnicodeString(&FileNameU, PathNameW);
106 /* convert unicode string to ansi (or oem) */
108 RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
110 RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
112 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)PathNameW,
117 return (HFILE)INVALID_HANDLE_VALUE;
120 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
121 ObjectAttributes.RootDirectory = NULL;
122 ObjectAttributes.ObjectName = &FileNameString;
123 ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
124 ObjectAttributes.SecurityDescriptor = NULL;
125 ObjectAttributes.SecurityQualityOfService = NULL;
128 // FILE_NO_INTERMEDIATE_BUFFERING
130 if ((uStyle & OF_PARSE) == OF_PARSE)
132 RtlFreeUnicodeString(&FileNameString);
136 errCode = NtOpenFile (&FileHandle,
137 GENERIC_READ|SYNCHRONIZE,
141 FILE_NON_DIRECTORY_FILE);
143 RtlFreeUnicodeString(&FileNameString);
145 lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
147 if (!NT_SUCCESS(errCode))
149 SetLastErrorByStatus (errCode);
150 return (HFILE)INVALID_HANDLE_VALUE;
153 return (HFILE)FileHandle;
158 FlushFileBuffers(HANDLE hFile)
161 IO_STATUS_BLOCK IoStatusBlock;
163 if (IsConsoleHandle(hFile))
168 errCode = NtFlushBuffersFile(hFile,
170 if (!NT_SUCCESS(errCode))
172 SetLastErrorByStatus(errCode);
180 SetFilePointer(HANDLE hFile,
181 LONG lDistanceToMove,
182 PLONG lpDistanceToMoveHigh,
185 FILE_POSITION_INFORMATION FilePosition;
186 FILE_STANDARD_INFORMATION FileStandart;
188 IO_STATUS_BLOCK IoStatusBlock;
189 LARGE_INTEGER Distance;
191 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
192 hFile,lDistanceToMove,dwMoveMethod);
194 Distance.u.LowPart = lDistanceToMove;
195 if (lpDistanceToMoveHigh)
197 Distance.u.HighPart = *lpDistanceToMoveHigh;
199 else if (lDistanceToMove >= 0)
201 Distance.u.HighPart = 0;
205 Distance.u.HighPart = -1;
208 if (dwMoveMethod == FILE_CURRENT)
210 NtQueryInformationFile(hFile,
213 sizeof(FILE_POSITION_INFORMATION),
214 FilePositionInformation);
215 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
217 else if (dwMoveMethod == FILE_END)
219 NtQueryInformationFile(hFile,
222 sizeof(FILE_STANDARD_INFORMATION),
223 FileStandardInformation);
224 FilePosition.CurrentByteOffset.QuadPart =
225 FileStandart.EndOfFile.QuadPart + Distance.QuadPart;
227 else if ( dwMoveMethod == FILE_BEGIN )
229 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
232 errCode = NtSetInformationFile(hFile,
235 sizeof(FILE_POSITION_INFORMATION),
236 FilePositionInformation);
237 if (!NT_SUCCESS(errCode))
239 SetLastErrorByStatus(errCode);
243 if (lpDistanceToMoveHigh != NULL)
245 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
247 return FilePosition.CurrentByteOffset.u.LowPart;
252 GetFileType(HANDLE hFile)
254 FILE_FS_DEVICE_INFORMATION DeviceInfo;
255 IO_STATUS_BLOCK StatusBlock;
258 /* get real handle */
259 switch ((ULONG)hFile)
261 case STD_INPUT_HANDLE:
262 hFile = NtCurrentPeb()->ProcessParameters->hStdInput;
266 case STD_OUTPUT_HANDLE:
267 hFile = NtCurrentPeb()->ProcessParameters->hStdOutput;
271 case STD_ERROR_HANDLE:
272 hFile = NtCurrentPeb()->ProcessParameters->hStdError;
277 /* check console handles */
278 if (IsConsoleHandle(hFile))
280 // if (VerifyConsoleHandle(hFile))
281 return FILE_TYPE_CHAR;
284 Status = NtQueryVolumeInformationFile(hFile,
287 sizeof(FILE_FS_DEVICE_INFORMATION),
288 FileFsDeviceInformation);
289 if (!NT_SUCCESS(Status))
291 SetLastErrorByStatus(Status);
292 return FILE_TYPE_UNKNOWN;
295 switch (DeviceInfo.DeviceType)
297 case FILE_DEVICE_CD_ROM:
298 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
299 case FILE_DEVICE_CONTROLLER:
300 case FILE_DEVICE_DATALINK:
301 case FILE_DEVICE_DFS:
302 case FILE_DEVICE_DISK:
303 case FILE_DEVICE_DISK_FILE_SYSTEM:
304 case FILE_DEVICE_VIRTUAL_DISK:
305 return FILE_TYPE_DISK;
307 case FILE_DEVICE_KEYBOARD:
308 case FILE_DEVICE_MOUSE:
309 case FILE_DEVICE_NULL:
310 case FILE_DEVICE_PARALLEL_PORT:
311 case FILE_DEVICE_PRINTER:
312 case FILE_DEVICE_SERIAL_PORT:
313 case FILE_DEVICE_SCREEN:
314 case FILE_DEVICE_SOUND:
315 case FILE_DEVICE_MODEM:
316 return FILE_TYPE_CHAR;
318 case FILE_DEVICE_NAMED_PIPE:
319 return FILE_TYPE_PIPE;
322 return FILE_TYPE_UNKNOWN;
327 GetFileSize(HANDLE hFile,
328 LPDWORD lpFileSizeHigh)
331 FILE_STANDARD_INFORMATION FileStandard;
332 IO_STATUS_BLOCK IoStatusBlock;
334 errCode = NtQueryInformationFile(hFile,
337 sizeof(FILE_STANDARD_INFORMATION),
338 FileStandardInformation);
339 if (!NT_SUCCESS(errCode))
341 SetLastErrorByStatus(errCode);
342 if ( lpFileSizeHigh == NULL )
351 if ( lpFileSizeHigh != NULL )
352 *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
354 return FileStandard.EndOfFile.u.LowPart;
359 GetCompressedFileSizeA(LPCSTR lpFileName,
360 LPDWORD lpFileSizeHigh)
362 UNICODE_STRING FileNameU;
363 ANSI_STRING FileName;
366 RtlInitAnsiString(&FileName,
369 /* convert ansi (or oem) string to unicode */
371 RtlAnsiStringToUnicodeString(&FileNameU,
375 RtlOemStringToUnicodeString(&FileNameU,
379 Size = GetCompressedFileSizeW(FileNameU.Buffer,
382 RtlFreeUnicodeString (&FileNameU);
389 GetCompressedFileSizeW(LPCWSTR lpFileName,
390 LPDWORD lpFileSizeHigh)
392 FILE_COMPRESSION_INFORMATION FileCompression;
394 IO_STATUS_BLOCK IoStatusBlock;
397 hFile = CreateFileW(lpFileName,
402 FILE_ATTRIBUTE_NORMAL,
405 errCode = NtQueryInformationFile(hFile,
408 sizeof(FILE_COMPRESSION_INFORMATION),
409 FileCompressionInformation);
410 if (!NT_SUCCESS(errCode))
413 SetLastErrorByStatus(errCode);
422 GetFileInformationByHandle(HANDLE hFile,
423 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
427 FILE_FS_VOLUME_INFORMATION FileFsVolume;
432 FILE_BASIC_INFORMATION FileBasic;
433 FILE_INTERNAL_INFORMATION FileInternal;
434 FILE_STANDARD_INFORMATION FileStandard;
436 IO_STATUS_BLOCK IoStatusBlock;
438 errCode = NtQueryInformationFile(hFile,
441 sizeof(FILE_BASIC_INFORMATION),
442 FileBasicInformation);
443 if (!NT_SUCCESS(errCode))
445 SetLastErrorByStatus(errCode);
449 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
450 memcpy(&lpFileInformation->ftCreationTime,&FileBasic.CreationTime,sizeof(LARGE_INTEGER));
451 memcpy(&lpFileInformation->ftLastAccessTime,&FileBasic.LastAccessTime,sizeof(LARGE_INTEGER));
452 memcpy(&lpFileInformation->ftLastWriteTime, &FileBasic.LastWriteTime,sizeof(LARGE_INTEGER));
454 errCode = NtQueryInformationFile(hFile,
457 sizeof(FILE_INTERNAL_INFORMATION),
458 FileInternalInformation);
459 if (!NT_SUCCESS(errCode))
461 SetLastErrorByStatus(errCode);
465 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
466 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
468 errCode = NtQueryVolumeInformationFile(hFile,
471 sizeof(FileFsVolume),
472 FileFsVolumeInformation);
473 if (!NT_SUCCESS(errCode))
475 SetLastErrorByStatus(errCode);
479 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
481 errCode = NtQueryInformationFile(hFile,
484 sizeof(FILE_STANDARD_INFORMATION),
485 FileStandardInformation);
486 if (!NT_SUCCESS(errCode))
488 SetLastErrorByStatus(errCode);
492 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
493 lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
494 lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
501 GetFileAttributesA(LPCSTR lpFileName)
503 UNICODE_STRING FileNameU;
504 ANSI_STRING FileName;
507 RtlInitAnsiString (&FileName,
510 /* convert ansi (or oem) string to unicode */
512 RtlAnsiStringToUnicodeString (&FileNameU,
516 RtlOemStringToUnicodeString (&FileNameU,
520 Result = GetFileAttributesW (FileNameU.Buffer);
522 RtlFreeUnicodeString (&FileNameU);
529 GetFileAttributesW(LPCWSTR lpFileName)
531 IO_STATUS_BLOCK IoStatusBlock;
532 FILE_BASIC_INFORMATION FileBasic;
536 hFile = CreateFileW(lpFileName,
537 FILE_READ_ATTRIBUTES,
541 FILE_ATTRIBUTE_NORMAL,
543 if (hFile == INVALID_HANDLE_VALUE)
548 errCode = NtQueryInformationFile(hFile,
551 sizeof(FILE_BASIC_INFORMATION),
552 FileBasicInformation);
553 if (!NT_SUCCESS(errCode))
556 SetLastErrorByStatus(errCode);
560 return (DWORD)FileBasic.FileAttributes;
565 SetFileAttributesA(LPCSTR lpFileName,
566 DWORD dwFileAttributes)
568 UNICODE_STRING FileNameU;
569 ANSI_STRING FileName;
572 RtlInitAnsiString(&FileName,
575 /* convert ansi (or oem) string to unicode */
577 RtlAnsiStringToUnicodeString(&FileNameU,
581 RtlOemStringToUnicodeString(&FileNameU,
585 Result = SetFileAttributesW(FileNameU.Buffer,
588 RtlFreeUnicodeString(&FileNameU);
595 SetFileAttributesW(LPCWSTR lpFileName,
596 DWORD dwFileAttributes)
598 IO_STATUS_BLOCK IoStatusBlock;
599 FILE_BASIC_INFORMATION FileBasic;
603 hFile = CreateFileW(lpFileName,
604 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
608 FILE_ATTRIBUTE_NORMAL,
611 errCode = NtQueryInformationFile(hFile,
614 sizeof(FILE_BASIC_INFORMATION),
615 FileBasicInformation);
616 if (!NT_SUCCESS(errCode))
619 SetLastErrorByStatus(errCode);
622 FileBasic.FileAttributes = dwFileAttributes;
623 errCode = NtSetInformationFile(hFile,
626 sizeof(FILE_BASIC_INFORMATION),
627 FileBasicInformation);
628 if (!NT_SUCCESS(errCode))
631 SetLastErrorByStatus(errCode);
640 GetTempFileNameA(LPCSTR lpPathName,
641 LPCSTR lpPrefixString,
643 LPSTR lpTempFileName)
646 UINT unique = uUnique;
648 const char *format = "%.*s\\~%.3s%4.4x.TMP";
650 DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
651 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
652 lpPrefixString, uUnique, lpTempFileName);
654 if (lpPathName == NULL)
657 len = strlen(lpPathName);
658 if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
662 uUnique = GetCurrentTime();
664 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
669 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
670 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
671 0)) == INVALID_HANDLE_VALUE)
673 if (GetLastError() != ERROR_ALREADY_EXISTS)
677 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
685 GetTempFileNameW(LPCWSTR lpPathName,
686 LPCWSTR lpPrefixString,
688 LPWSTR lpTempFileName)
691 UINT unique = uUnique;
693 const WCHAR *format = L"%.*S\\~%.3S%4.4x.TMP";
695 DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
696 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
697 lpPrefixString, uUnique, lpTempFileName);
699 if (lpPathName == NULL)
702 len = wcslen(lpPathName);
703 if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
707 uUnique = GetCurrentTime();
709 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
714 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
715 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
716 0)) == INVALID_HANDLE_VALUE)
718 if (GetLastError() != ERROR_ALREADY_EXISTS)
722 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
730 GetFileTime(HANDLE hFile,
731 LPFILETIME lpCreationTime,
732 LPFILETIME lpLastAccessTime,
733 LPFILETIME lpLastWriteTime)
735 IO_STATUS_BLOCK IoStatusBlock;
736 FILE_BASIC_INFORMATION FileBasic;
739 Status = NtQueryInformationFile(hFile,
742 sizeof(FILE_BASIC_INFORMATION),
743 FileBasicInformation);
744 if (!NT_SUCCESS(Status))
746 SetLastErrorByStatus(Status);
751 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
752 if (lpLastAccessTime)
753 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
755 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
762 SetFileTime(HANDLE hFile,
763 CONST FILETIME *lpCreationTime,
764 CONST FILETIME *lpLastAccessTime,
765 CONST FILETIME *lpLastWriteTime)
767 FILE_BASIC_INFORMATION FileBasic;
768 IO_STATUS_BLOCK IoStatusBlock;
771 Status = NtQueryInformationFile(hFile,
774 sizeof(FILE_BASIC_INFORMATION),
775 FileBasicInformation);
776 if (!NT_SUCCESS(Status))
778 SetLastErrorByStatus(Status);
783 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
784 if (lpLastAccessTime)
785 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
787 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
789 // should i initialize changetime ???
791 Status = NtSetInformationFile(hFile,
794 sizeof(FILE_BASIC_INFORMATION),
795 FileBasicInformation);
796 if (!NT_SUCCESS(Status))
798 SetLastErrorByStatus(Status);
807 The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
810 SetEndOfFile(HANDLE hFile)
812 IO_STATUS_BLOCK IoStatusBlock;
813 FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
814 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
815 FILE_POSITION_INFORMATION FilePosInfo;
818 //get current position
819 Status = NtQueryInformationFile(
823 sizeof(FILE_POSITION_INFORMATION),
824 FilePositionInformation
827 if (!NT_SUCCESS(Status)){
828 SetLastErrorByStatus(Status);
832 EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
836 This call is not supposed to free up any space after the eof marker
837 if the file gets truncated. We have to deallocate the space explicitly afterwards.
838 But...most file systems dispatch both FileEndOfFileInformation
839 and FileAllocationInformation as they were the same command.
842 Status = NtSetInformationFile(
844 &IoStatusBlock, //out
846 sizeof(FILE_END_OF_FILE_INFORMATION),
847 FileEndOfFileInformation
850 if (!NT_SUCCESS(Status)){
851 SetLastErrorByStatus(Status);
855 FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
858 Status = NtSetInformationFile(
860 &IoStatusBlock, //out
862 sizeof(FILE_ALLOCATION_INFORMATION),
863 FileAllocationInformation
866 if (!NT_SUCCESS(Status)){
867 SetLastErrorByStatus(Status);