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 #include <kernel32/kernel32.h>
21 /* GLOBALS ******************************************************************/
23 WINBOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
26 /* FUNCTIONS ****************************************************************/
29 SetFileApisToOEM(VOID)
31 bIsFileApiAnsi = FALSE;
36 SetFileApisToANSI(VOID)
38 bIsFileApiAnsi = TRUE;
45 return bIsFileApiAnsi;
50 OpenFile(LPCSTR lpFileName,
51 LPOFSTRUCT lpReOpenBuff,
54 OBJECT_ATTRIBUTES ObjectAttributes;
55 IO_STATUS_BLOCK IoStatusBlock;
56 UNICODE_STRING FileNameString;
57 UNICODE_STRING FileNameU;
59 WCHAR PathNameW[MAX_PATH];
60 HANDLE FileHandle = NULL;
65 DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
67 if (lpReOpenBuff == NULL)
72 RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
74 /* convert ansi (or oem) string to unicode */
76 RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
78 RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
80 Len = SearchPathW (NULL,
87 RtlFreeUnicodeString(&FileNameU);
89 if (Len == 0 || Len > OFS_MAXPATHNAME)
91 return (HFILE)INVALID_HANDLE_VALUE;
94 FileName.Buffer = lpReOpenBuff->szPathName;
96 FileName.MaximumLength = OFS_MAXPATHNAME;
98 RtlInitUnicodeString(&FileNameU, PathNameW);
100 /* convert unicode string to ansi (or oem) */
102 RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
104 RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
106 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)PathNameW,
111 return (HFILE)INVALID_HANDLE_VALUE;
114 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
115 ObjectAttributes.RootDirectory = NULL;
116 ObjectAttributes.ObjectName = &FileNameString;
117 ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
118 ObjectAttributes.SecurityDescriptor = NULL;
119 ObjectAttributes.SecurityQualityOfService = NULL;
122 // FILE_NO_INTERMEDIATE_BUFFERING
124 if ((uStyle & OF_PARSE) == OF_PARSE)
126 RtlFreeUnicodeString(&FileNameString);
130 errCode = NtOpenFile (&FileHandle,
131 GENERIC_READ|SYNCHRONIZE,
135 FILE_NON_DIRECTORY_FILE);
137 RtlFreeUnicodeString(&FileNameString);
139 lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
141 if (!NT_SUCCESS(errCode))
143 SetLastErrorByStatus (errCode);
144 return (HFILE)INVALID_HANDLE_VALUE;
147 return (HFILE)FileHandle;
152 FlushFileBuffers(HANDLE hFile)
155 IO_STATUS_BLOCK IoStatusBlock;
157 if (IsConsoleHandle(hFile))
162 errCode = NtFlushBuffersFile(hFile,
164 if (!NT_SUCCESS(errCode))
166 SetLastErrorByStatus(errCode);
174 SetFilePointer(HANDLE hFile,
175 LONG lDistanceToMove,
176 PLONG lpDistanceToMoveHigh,
179 FILE_POSITION_INFORMATION FilePosition;
180 FILE_STANDARD_INFORMATION FileStandart;
182 IO_STATUS_BLOCK IoStatusBlock;
183 LARGE_INTEGER Distance;
185 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
186 hFile,lDistanceToMove,dwMoveMethod);
188 Distance.u.LowPart = lDistanceToMove;
189 if (lpDistanceToMoveHigh)
191 Distance.u.HighPart = *lpDistanceToMoveHigh;
193 else if (lDistanceToMove >= 0)
195 Distance.u.HighPart = 0;
199 Distance.u.HighPart = -1;
202 if (dwMoveMethod == FILE_CURRENT)
204 NtQueryInformationFile(hFile,
207 sizeof(FILE_POSITION_INFORMATION),
208 FilePositionInformation);
209 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
211 else if (dwMoveMethod == FILE_END)
213 NtQueryInformationFile(hFile,
216 sizeof(FILE_STANDARD_INFORMATION),
217 FileStandardInformation);
218 FilePosition.CurrentByteOffset.QuadPart =
219 FileStandart.EndOfFile.QuadPart + Distance.QuadPart;
221 else if ( dwMoveMethod == FILE_BEGIN )
223 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
226 errCode = NtSetInformationFile(hFile,
229 sizeof(FILE_POSITION_INFORMATION),
230 FilePositionInformation);
231 if (!NT_SUCCESS(errCode))
233 SetLastErrorByStatus(errCode);
237 if (lpDistanceToMoveHigh != NULL)
239 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
241 return FilePosition.CurrentByteOffset.u.LowPart;
246 GetFileType(HANDLE hFile)
248 FILE_FS_DEVICE_INFORMATION DeviceInfo;
249 IO_STATUS_BLOCK StatusBlock;
252 /* get real handle */
253 switch ((ULONG)hFile)
255 case STD_INPUT_HANDLE:
256 hFile = NtCurrentPeb()->ProcessParameters->hStdInput;
260 case STD_OUTPUT_HANDLE:
261 hFile = NtCurrentPeb()->ProcessParameters->hStdOutput;
265 case STD_ERROR_HANDLE:
266 hFile = NtCurrentPeb()->ProcessParameters->hStdError;
271 /* check console handles */
272 if (IsConsoleHandle(hFile))
274 // if (VerifyConsoleHandle(hFile))
275 return FILE_TYPE_CHAR;
278 Status = NtQueryVolumeInformationFile(hFile,
281 sizeof(FILE_FS_DEVICE_INFORMATION),
282 FileFsDeviceInformation);
283 if (!NT_SUCCESS(Status))
285 SetLastErrorByStatus(Status);
286 return FILE_TYPE_UNKNOWN;
289 switch (DeviceInfo.DeviceType)
291 case FILE_DEVICE_CD_ROM:
292 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
293 case FILE_DEVICE_CONTROLLER:
294 case FILE_DEVICE_DATALINK:
295 case FILE_DEVICE_DFS:
296 case FILE_DEVICE_DISK:
297 case FILE_DEVICE_DISK_FILE_SYSTEM:
298 case FILE_DEVICE_VIRTUAL_DISK:
299 return FILE_TYPE_DISK;
301 case FILE_DEVICE_KEYBOARD:
302 case FILE_DEVICE_MOUSE:
303 case FILE_DEVICE_NULL:
304 case FILE_DEVICE_PARALLEL_PORT:
305 case FILE_DEVICE_PRINTER:
306 case FILE_DEVICE_SERIAL_PORT:
307 case FILE_DEVICE_SCREEN:
308 case FILE_DEVICE_SOUND:
309 case FILE_DEVICE_MODEM:
310 return FILE_TYPE_CHAR;
312 case FILE_DEVICE_NAMED_PIPE:
313 return FILE_TYPE_PIPE;
316 return FILE_TYPE_UNKNOWN;
321 GetFileSize(HANDLE hFile,
322 LPDWORD lpFileSizeHigh)
325 FILE_STANDARD_INFORMATION FileStandard;
326 IO_STATUS_BLOCK IoStatusBlock;
328 errCode = NtQueryInformationFile(hFile,
331 sizeof(FILE_STANDARD_INFORMATION),
332 FileStandardInformation);
333 if (!NT_SUCCESS(errCode))
335 SetLastErrorByStatus(errCode);
336 if ( lpFileSizeHigh == NULL )
345 if ( lpFileSizeHigh != NULL )
346 *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
348 return FileStandard.EndOfFile.u.LowPart;
353 GetCompressedFileSizeA(LPCSTR lpFileName,
354 LPDWORD lpFileSizeHigh)
356 UNICODE_STRING FileNameU;
357 ANSI_STRING FileName;
360 RtlInitAnsiString(&FileName,
363 /* convert ansi (or oem) string to unicode */
365 RtlAnsiStringToUnicodeString(&FileNameU,
369 RtlOemStringToUnicodeString(&FileNameU,
373 Size = GetCompressedFileSizeW(FileNameU.Buffer,
376 RtlFreeUnicodeString (&FileNameU);
383 GetCompressedFileSizeW(LPCWSTR lpFileName,
384 LPDWORD lpFileSizeHigh)
386 FILE_COMPRESSION_INFORMATION FileCompression;
388 IO_STATUS_BLOCK IoStatusBlock;
391 hFile = CreateFileW(lpFileName,
396 FILE_ATTRIBUTE_NORMAL,
399 errCode = NtQueryInformationFile(hFile,
402 sizeof(FILE_COMPRESSION_INFORMATION),
403 FileCompressionInformation);
404 if (!NT_SUCCESS(errCode))
407 SetLastErrorByStatus(errCode);
408 return INVALID_FILE_SIZE;
413 *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
415 return FileCompression.CompressedFileSize.u.LowPart;
420 GetFileInformationByHandle(HANDLE hFile,
421 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
425 FILE_FS_VOLUME_INFORMATION FileFsVolume;
430 FILE_BASIC_INFORMATION FileBasic;
431 FILE_INTERNAL_INFORMATION FileInternal;
432 FILE_STANDARD_INFORMATION FileStandard;
434 IO_STATUS_BLOCK IoStatusBlock;
436 errCode = NtQueryInformationFile(hFile,
439 sizeof(FILE_BASIC_INFORMATION),
440 FileBasicInformation);
441 if (!NT_SUCCESS(errCode))
443 SetLastErrorByStatus(errCode);
447 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
448 memcpy(&lpFileInformation->ftCreationTime,&FileBasic.CreationTime,sizeof(LARGE_INTEGER));
449 memcpy(&lpFileInformation->ftLastAccessTime,&FileBasic.LastAccessTime,sizeof(LARGE_INTEGER));
450 memcpy(&lpFileInformation->ftLastWriteTime, &FileBasic.LastWriteTime,sizeof(LARGE_INTEGER));
452 errCode = NtQueryInformationFile(hFile,
455 sizeof(FILE_INTERNAL_INFORMATION),
456 FileInternalInformation);
457 if (!NT_SUCCESS(errCode))
459 SetLastErrorByStatus(errCode);
463 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
464 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
466 errCode = NtQueryVolumeInformationFile(hFile,
469 sizeof(FileFsVolume),
470 FileFsVolumeInformation);
471 if (!NT_SUCCESS(errCode))
473 SetLastErrorByStatus(errCode);
477 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
479 errCode = NtQueryInformationFile(hFile,
482 sizeof(FILE_STANDARD_INFORMATION),
483 FileStandardInformation);
484 if (!NT_SUCCESS(errCode))
486 SetLastErrorByStatus(errCode);
490 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
491 lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
492 lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
499 GetFileAttributesA(LPCSTR lpFileName)
501 UNICODE_STRING FileNameU;
502 ANSI_STRING FileName;
505 RtlInitAnsiString (&FileName,
508 /* convert ansi (or oem) string to unicode */
510 RtlAnsiStringToUnicodeString (&FileNameU,
514 RtlOemStringToUnicodeString (&FileNameU,
518 Result = GetFileAttributesW (FileNameU.Buffer);
520 RtlFreeUnicodeString (&FileNameU);
527 GetFileAttributesW(LPCWSTR lpFileName)
529 IO_STATUS_BLOCK IoStatusBlock;
530 FILE_BASIC_INFORMATION FileBasic;
534 hFile = CreateFileW(lpFileName,
535 FILE_READ_ATTRIBUTES,
539 FILE_ATTRIBUTE_NORMAL,
541 if (hFile == INVALID_HANDLE_VALUE)
546 errCode = NtQueryInformationFile(hFile,
549 sizeof(FILE_BASIC_INFORMATION),
550 FileBasicInformation);
551 if (!NT_SUCCESS(errCode))
554 SetLastErrorByStatus(errCode);
558 return (DWORD)FileBasic.FileAttributes;
563 SetFileAttributesA(LPCSTR lpFileName,
564 DWORD dwFileAttributes)
566 UNICODE_STRING FileNameU;
567 ANSI_STRING FileName;
570 RtlInitAnsiString(&FileName,
573 /* convert ansi (or oem) string to unicode */
575 RtlAnsiStringToUnicodeString(&FileNameU,
579 RtlOemStringToUnicodeString(&FileNameU,
583 Result = SetFileAttributesW(FileNameU.Buffer,
586 RtlFreeUnicodeString(&FileNameU);
593 SetFileAttributesW(LPCWSTR lpFileName,
594 DWORD dwFileAttributes)
596 IO_STATUS_BLOCK IoStatusBlock;
597 FILE_BASIC_INFORMATION FileBasic;
601 hFile = CreateFileW(lpFileName,
602 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
606 FILE_ATTRIBUTE_NORMAL,
608 if (INVALID_HANDLE_VALUE == hFile)
610 DPRINT("SetFileAttributes CreateFileW failed with code %d\n", GetLastError());
614 errCode = NtQueryInformationFile(hFile,
617 sizeof(FILE_BASIC_INFORMATION),
618 FileBasicInformation);
619 if (!NT_SUCCESS(errCode))
622 DPRINT("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", errCode);
623 SetLastErrorByStatus(errCode);
626 FileBasic.FileAttributes = dwFileAttributes;
627 errCode = NtSetInformationFile(hFile,
630 sizeof(FILE_BASIC_INFORMATION),
631 FileBasicInformation);
632 if (!NT_SUCCESS(errCode))
635 DPRINT("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", errCode);
636 SetLastErrorByStatus(errCode);
645 GetTempFileNameA(LPCSTR lpPathName,
646 LPCSTR lpPrefixString,
648 LPSTR lpTempFileName)
651 UINT unique = uUnique;
653 const char *format = "%.*s\\~%.3s%4.4x.TMP";
655 DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
656 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
657 lpPrefixString, uUnique, lpTempFileName);
659 if (lpPathName == NULL)
662 len = strlen(lpPathName);
663 if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
667 uUnique = GetCurrentTime();
669 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
674 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
675 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
676 0)) == INVALID_HANDLE_VALUE)
678 if (GetLastError() != ERROR_ALREADY_EXISTS)
682 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
690 GetTempFileNameW(LPCWSTR lpPathName,
691 LPCWSTR lpPrefixString,
693 LPWSTR lpTempFileName)
696 UINT unique = uUnique;
698 const WCHAR *format = L"%.*S\\~%.3S%4.4x.TMP";
700 DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
701 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
702 lpPrefixString, uUnique, lpTempFileName);
704 if (lpPathName == NULL)
707 len = wcslen(lpPathName);
708 if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
712 uUnique = GetCurrentTime();
714 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
719 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
720 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
721 0)) == INVALID_HANDLE_VALUE)
723 if (GetLastError() != ERROR_ALREADY_EXISTS)
727 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
735 GetFileTime(HANDLE hFile,
736 LPFILETIME lpCreationTime,
737 LPFILETIME lpLastAccessTime,
738 LPFILETIME lpLastWriteTime)
740 IO_STATUS_BLOCK IoStatusBlock;
741 FILE_BASIC_INFORMATION FileBasic;
744 Status = NtQueryInformationFile(hFile,
747 sizeof(FILE_BASIC_INFORMATION),
748 FileBasicInformation);
749 if (!NT_SUCCESS(Status))
751 SetLastErrorByStatus(Status);
756 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
757 if (lpLastAccessTime)
758 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
760 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
767 SetFileTime(HANDLE hFile,
768 CONST FILETIME *lpCreationTime,
769 CONST FILETIME *lpLastAccessTime,
770 CONST FILETIME *lpLastWriteTime)
772 FILE_BASIC_INFORMATION FileBasic;
773 IO_STATUS_BLOCK IoStatusBlock;
776 Status = NtQueryInformationFile(hFile,
779 sizeof(FILE_BASIC_INFORMATION),
780 FileBasicInformation);
781 if (!NT_SUCCESS(Status))
783 SetLastErrorByStatus(Status);
788 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
789 if (lpLastAccessTime)
790 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
792 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
794 // should i initialize changetime ???
796 Status = NtSetInformationFile(hFile,
799 sizeof(FILE_BASIC_INFORMATION),
800 FileBasicInformation);
801 if (!NT_SUCCESS(Status))
803 SetLastErrorByStatus(Status);
812 The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
815 SetEndOfFile(HANDLE hFile)
817 IO_STATUS_BLOCK IoStatusBlock;
818 FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
819 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
820 FILE_POSITION_INFORMATION FilePosInfo;
823 //get current position
824 Status = NtQueryInformationFile(
828 sizeof(FILE_POSITION_INFORMATION),
829 FilePositionInformation
832 if (!NT_SUCCESS(Status)){
833 SetLastErrorByStatus(Status);
837 EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
841 This call is not supposed to free up any space after the eof marker
842 if the file gets truncated. We have to deallocate the space explicitly afterwards.
843 But...most file systems dispatch both FileEndOfFileInformation
844 and FileAllocationInformation as they were the same command.
847 Status = NtSetInformationFile(
849 &IoStatusBlock, //out
851 sizeof(FILE_END_OF_FILE_INFORMATION),
852 FileEndOfFileInformation
855 if (!NT_SUCCESS(Status)){
856 SetLastErrorByStatus(Status);
860 FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
863 Status = NtSetInformationFile(
865 &IoStatusBlock, //out
867 sizeof(FILE_ALLOCATION_INFORMATION),
868 FileAllocationInformation
871 if (!NT_SUCCESS(Status)){
872 SetLastErrorByStatus(Status);