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;
\r
265 case STD_OUTPUT_HANDLE:
266 hFile = NtCurrentPeb()->ProcessParameters->hStdOutput;
\r
269 case STD_ERROR_HANDLE:
270 hFile = NtCurrentPeb()->ProcessParameters->hStdError;
\r
274 /* check console handles */
275 if (IsConsoleHandle(hFile))
277 // if (VerifyConsoleHandle(hFile))
278 return FILE_TYPE_CHAR;
281 Status = NtQueryVolumeInformationFile(hFile,
284 sizeof(FILE_FS_DEVICE_INFORMATION),
285 FileFsDeviceInformation);
286 if (!NT_SUCCESS(Status))
288 SetLastErrorByStatus(Status);
289 return FILE_TYPE_UNKNOWN;
292 switch (DeviceInfo.DeviceType)
294 case FILE_DEVICE_CD_ROM:
295 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
296 case FILE_DEVICE_CONTROLLER:
297 case FILE_DEVICE_DATALINK:
298 case FILE_DEVICE_DFS:
299 case FILE_DEVICE_DISK:
300 case FILE_DEVICE_DISK_FILE_SYSTEM:
301 case FILE_DEVICE_VIRTUAL_DISK:
302 return FILE_TYPE_DISK;
304 case FILE_DEVICE_KEYBOARD:
305 case FILE_DEVICE_MOUSE:
306 case FILE_DEVICE_NULL:
307 case FILE_DEVICE_PARALLEL_PORT:
308 case FILE_DEVICE_PRINTER:
309 case FILE_DEVICE_SERIAL_PORT:
310 case FILE_DEVICE_SCREEN:
311 case FILE_DEVICE_SOUND:
312 case FILE_DEVICE_MODEM:
313 return FILE_TYPE_CHAR;
315 case FILE_DEVICE_NAMED_PIPE:
316 return FILE_TYPE_PIPE;
319 return FILE_TYPE_UNKNOWN;
324 GetFileSize(HANDLE hFile,
325 LPDWORD lpFileSizeHigh)
328 FILE_STANDARD_INFORMATION FileStandard;
329 IO_STATUS_BLOCK IoStatusBlock;
331 errCode = NtQueryInformationFile(hFile,
334 sizeof(FILE_STANDARD_INFORMATION),
335 FileStandardInformation);
336 if (!NT_SUCCESS(errCode))
338 SetLastErrorByStatus(errCode);
339 if ( lpFileSizeHigh == NULL )
348 if ( lpFileSizeHigh != NULL )
349 *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
351 return FileStandard.EndOfFile.u.LowPart;
356 GetCompressedFileSizeA(LPCSTR lpFileName,
357 LPDWORD lpFileSizeHigh)
359 UNICODE_STRING FileNameU;
360 ANSI_STRING FileName;
363 RtlInitAnsiString(&FileName,
366 /* convert ansi (or oem) string to unicode */
368 RtlAnsiStringToUnicodeString(&FileNameU,
372 RtlOemStringToUnicodeString(&FileNameU,
376 Size = GetCompressedFileSizeW(FileNameU.Buffer,
379 RtlFreeUnicodeString (&FileNameU);
386 GetCompressedFileSizeW(LPCWSTR lpFileName,
387 LPDWORD lpFileSizeHigh)
389 FILE_COMPRESSION_INFORMATION FileCompression;
391 IO_STATUS_BLOCK IoStatusBlock;
394 hFile = CreateFileW(lpFileName,
399 FILE_ATTRIBUTE_NORMAL,
402 errCode = NtQueryInformationFile(hFile,
405 sizeof(FILE_COMPRESSION_INFORMATION),
406 FileCompressionInformation);
407 if (!NT_SUCCESS(errCode))
410 SetLastErrorByStatus(errCode);
419 GetFileInformationByHandle(HANDLE hFile,
420 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
424 FILE_FS_VOLUME_INFORMATION FileFsVolume;
429 FILE_BASIC_INFORMATION FileBasic;
430 FILE_INTERNAL_INFORMATION FileInternal;
431 FILE_STANDARD_INFORMATION FileStandard;
433 IO_STATUS_BLOCK IoStatusBlock;
435 errCode = NtQueryInformationFile(hFile,
438 sizeof(FILE_BASIC_INFORMATION),
439 FileBasicInformation);
440 if (!NT_SUCCESS(errCode))
442 SetLastErrorByStatus(errCode);
446 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
447 memcpy(&lpFileInformation->ftCreationTime,&FileBasic.CreationTime,sizeof(LARGE_INTEGER));
448 memcpy(&lpFileInformation->ftLastAccessTime,&FileBasic.LastAccessTime,sizeof(LARGE_INTEGER));
449 memcpy(&lpFileInformation->ftLastWriteTime, &FileBasic.LastWriteTime,sizeof(LARGE_INTEGER));
451 errCode = NtQueryInformationFile(hFile,
454 sizeof(FILE_INTERNAL_INFORMATION),
455 FileInternalInformation);
456 if (!NT_SUCCESS(errCode))
458 SetLastErrorByStatus(errCode);
462 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
463 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
465 errCode = NtQueryVolumeInformationFile(hFile,
468 sizeof(FileFsVolume),
469 FileFsVolumeInformation);
470 if (!NT_SUCCESS(errCode))
472 SetLastErrorByStatus(errCode);
476 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
478 errCode = NtQueryInformationFile(hFile,
481 sizeof(FILE_STANDARD_INFORMATION),
482 FileStandardInformation);
483 if (!NT_SUCCESS(errCode))
485 SetLastErrorByStatus(errCode);
489 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
490 lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
491 lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
498 GetFileAttributesA(LPCSTR lpFileName)
500 UNICODE_STRING FileNameU;
501 ANSI_STRING FileName;
504 RtlInitAnsiString (&FileName,
507 /* convert ansi (or oem) string to unicode */
509 RtlAnsiStringToUnicodeString (&FileNameU,
513 RtlOemStringToUnicodeString (&FileNameU,
517 Result = GetFileAttributesW (FileNameU.Buffer);
519 RtlFreeUnicodeString (&FileNameU);
526 GetFileAttributesW(LPCWSTR lpFileName)
528 IO_STATUS_BLOCK IoStatusBlock;
529 FILE_BASIC_INFORMATION FileBasic;
533 hFile = CreateFileW(lpFileName,
534 FILE_READ_ATTRIBUTES,
538 FILE_ATTRIBUTE_NORMAL,
540 if (hFile == INVALID_HANDLE_VALUE)
545 errCode = NtQueryInformationFile(hFile,
548 sizeof(FILE_BASIC_INFORMATION),
549 FileBasicInformation);
550 if (!NT_SUCCESS(errCode))
553 SetLastErrorByStatus(errCode);
557 return (DWORD)FileBasic.FileAttributes;
562 SetFileAttributesA(LPCSTR lpFileName,
563 DWORD dwFileAttributes)
565 UNICODE_STRING FileNameU;
566 ANSI_STRING FileName;
569 RtlInitAnsiString(&FileName,
572 /* convert ansi (or oem) string to unicode */
574 RtlAnsiStringToUnicodeString(&FileNameU,
578 RtlOemStringToUnicodeString(&FileNameU,
582 Result = SetFileAttributesW(FileNameU.Buffer,
585 RtlFreeUnicodeString(&FileNameU);
592 SetFileAttributesW(LPCWSTR lpFileName,
593 DWORD dwFileAttributes)
595 IO_STATUS_BLOCK IoStatusBlock;
596 FILE_BASIC_INFORMATION FileBasic;
600 hFile = CreateFileW(lpFileName,
601 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
605 FILE_ATTRIBUTE_NORMAL,
608 errCode = NtQueryInformationFile(hFile,
611 sizeof(FILE_BASIC_INFORMATION),
612 FileBasicInformation);
613 if (!NT_SUCCESS(errCode))
616 SetLastErrorByStatus(errCode);
619 FileBasic.FileAttributes = dwFileAttributes;
620 errCode = NtSetInformationFile(hFile,
623 sizeof(FILE_BASIC_INFORMATION),
624 FileBasicInformation);
625 if (!NT_SUCCESS(errCode))
628 SetLastErrorByStatus(errCode);
637 GetTempFileNameA(LPCSTR lpPathName,
638 LPCSTR lpPrefixString,
640 LPSTR lpTempFileName)
643 UINT unique = uUnique;
645 const char *format = "%.*s\\~%.3s%4.4x.TMP";
647 DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
648 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
649 lpPrefixString, uUnique, lpTempFileName);
651 if (lpPathName == NULL)
654 len = strlen(lpPathName);
655 if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
659 uUnique = GetCurrentTime();
661 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
666 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
667 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
668 0)) == INVALID_HANDLE_VALUE)
670 if (GetLastError() != ERROR_ALREADY_EXISTS)
674 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
682 GetTempFileNameW(LPCWSTR lpPathName,
683 LPCWSTR lpPrefixString,
685 LPWSTR lpTempFileName)
688 UINT unique = uUnique;
690 const WCHAR *format = L"%.*S\\~%.3S%4.4x.TMP";
692 DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
693 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
694 lpPrefixString, uUnique, lpTempFileName);
696 if (lpPathName == NULL)
699 len = wcslen(lpPathName);
700 if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
704 uUnique = GetCurrentTime();
706 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
711 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
712 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
713 0)) == INVALID_HANDLE_VALUE)
715 if (GetLastError() != ERROR_ALREADY_EXISTS)
719 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
727 GetFileTime(HANDLE hFile,
728 LPFILETIME lpCreationTime,
729 LPFILETIME lpLastAccessTime,
730 LPFILETIME lpLastWriteTime)
732 IO_STATUS_BLOCK IoStatusBlock;
733 FILE_BASIC_INFORMATION FileBasic;
736 Status = NtQueryInformationFile(hFile,
739 sizeof(FILE_BASIC_INFORMATION),
740 FileBasicInformation);
741 if (!NT_SUCCESS(Status))
743 SetLastErrorByStatus(Status);
748 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
749 if (lpLastAccessTime)
750 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
752 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
759 SetFileTime(HANDLE hFile,
760 CONST FILETIME *lpCreationTime,
761 CONST FILETIME *lpLastAccessTime,
762 CONST FILETIME *lpLastWriteTime)
764 FILE_BASIC_INFORMATION FileBasic;
765 IO_STATUS_BLOCK IoStatusBlock;
768 Status = NtQueryInformationFile(hFile,
771 sizeof(FILE_BASIC_INFORMATION),
772 FileBasicInformation);
773 if (!NT_SUCCESS(Status))
775 SetLastErrorByStatus(Status);
780 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
781 if (lpLastAccessTime)
782 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
784 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
786 // should i initialize changetime ???
788 Status = NtSetInformationFile(hFile,
791 sizeof(FILE_BASIC_INFORMATION),
792 FileBasicInformation);
793 if (!NT_SUCCESS(Status))
795 SetLastErrorByStatus(Status);
804 SetEndOfFile(HANDLE hFile)
808 return WriteFile(hFile,&x,1,&Num,NULL);