1 /* $Id: file.c,v 1.29 2002/03/25 21:07:17 hbirr Exp $
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 if (lpReOpenBuff
== NULL
)
76 RtlInitAnsiString (&FileName
,
79 /* convert ansi (or oem) string to unicode */
81 RtlAnsiStringToUnicodeString (&FileNameU
,
85 RtlOemStringToUnicodeString (&FileNameU
,
89 Len
= SearchPathW (NULL
,
96 RtlFreeHeap (RtlGetProcessHeap (),
106 FileNameString
.Length
= lstrlenW(PathNameW
) * sizeof(WCHAR
);
107 FileNameString
.Buffer
= PathNameW
;
108 FileNameString
.MaximumLength
= FileNameString
.Length
+ sizeof(WCHAR
);
110 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
111 ObjectAttributes
.RootDirectory
= NULL
;
112 ObjectAttributes
.ObjectName
= &FileNameString
;
113 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
114 ObjectAttributes
.SecurityDescriptor
= NULL
;
115 ObjectAttributes
.SecurityQualityOfService
= NULL
;
118 // FILE_NO_INTERMEDIATE_BUFFERING
120 if ((uStyle
& OF_PARSE
) == OF_PARSE
)
123 errCode
= NtOpenFile (&FileHandle
,
124 GENERIC_READ
|SYNCHRONIZE
,
128 FILE_NON_DIRECTORY_FILE
);
130 lpReOpenBuff
->nErrCode
= RtlNtStatusToDosError(errCode
);
132 if (!NT_SUCCESS(errCode
))
134 SetLastErrorByStatus (errCode
);
135 return (HFILE
)INVALID_HANDLE_VALUE
;
138 return (HFILE
)FileHandle
;
143 FlushFileBuffers(HANDLE hFile
)
146 IO_STATUS_BLOCK IoStatusBlock
;
148 errCode
= NtFlushBuffersFile(hFile
,
150 if (!NT_SUCCESS(errCode
))
152 SetLastErrorByStatus(errCode
);
160 SetFilePointer(HANDLE hFile
,
161 LONG lDistanceToMove
,
162 PLONG lpDistanceToMoveHigh
,
165 FILE_POSITION_INFORMATION FilePosition
;
166 FILE_STANDARD_INFORMATION FileStandart
;
168 IO_STATUS_BLOCK IoStatusBlock
;
169 LARGE_INTEGER Distance
;
171 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
172 hFile
,lDistanceToMove
,dwMoveMethod
);
174 Distance
.u
.LowPart
= lDistanceToMove
;
175 if (lpDistanceToMoveHigh
)
177 Distance
.u
.HighPart
= *lpDistanceToMoveHigh
;
179 else if (lDistanceToMove
>= 0)
181 Distance
.u
.HighPart
= 0;
185 Distance
.u
.HighPart
= -1;
188 if (dwMoveMethod
== FILE_CURRENT
)
190 NtQueryInformationFile(hFile
,
193 sizeof(FILE_POSITION_INFORMATION
),
194 FilePositionInformation
);
195 FilePosition
.CurrentByteOffset
.QuadPart
+= Distance
.QuadPart
;
197 else if (dwMoveMethod
== FILE_END
)
199 NtQueryInformationFile(hFile
,
202 sizeof(FILE_STANDARD_INFORMATION
),
203 FileStandardInformation
);
204 FilePosition
.CurrentByteOffset
.QuadPart
=
205 FileStandart
.EndOfFile
.QuadPart
+ Distance
.QuadPart
;
207 else if ( dwMoveMethod
== FILE_BEGIN
)
209 FilePosition
.CurrentByteOffset
.QuadPart
= Distance
.QuadPart
;
212 errCode
= NtSetInformationFile(hFile
,
215 sizeof(FILE_POSITION_INFORMATION
),
216 FilePositionInformation
);
217 if (!NT_SUCCESS(errCode
))
219 SetLastErrorByStatus(errCode
);
223 if (lpDistanceToMoveHigh
!= NULL
)
225 *lpDistanceToMoveHigh
= FilePosition
.CurrentByteOffset
.u
.HighPart
;
227 return FilePosition
.CurrentByteOffset
.u
.LowPart
;
232 GetFileType(HANDLE hFile
)
234 FILE_FS_DEVICE_INFORMATION DeviceInfo
;
235 IO_STATUS_BLOCK StatusBlock
;
238 /* get real handle */
239 switch ((ULONG
)hFile
)
241 case STD_INPUT_HANDLE
:
242 hFile
= NtCurrentPeb()->ProcessParameters
->InputHandle
;
245 case STD_OUTPUT_HANDLE
:
246 hFile
= NtCurrentPeb()->ProcessParameters
->OutputHandle
;
249 case STD_ERROR_HANDLE
:
250 hFile
= NtCurrentPeb()->ProcessParameters
->ErrorHandle
;
254 /* check console handles */
255 if (((ULONG
)hFile
& 3) == 3)
257 // if (VerifyConsoleHandle(hFile))
258 return FILE_TYPE_CHAR
;
261 Status
= NtQueryVolumeInformationFile(hFile
,
264 sizeof(FILE_FS_DEVICE_INFORMATION
),
265 FileFsDeviceInformation
);
266 if (!NT_SUCCESS(Status
))
268 SetLastErrorByStatus(Status
);
269 return FILE_TYPE_UNKNOWN
;
272 switch (DeviceInfo
.DeviceType
)
274 case FILE_DEVICE_CD_ROM
:
275 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
276 case FILE_DEVICE_CONTROLLER
:
277 case FILE_DEVICE_DATALINK
:
278 case FILE_DEVICE_DFS
:
279 case FILE_DEVICE_DISK
:
280 case FILE_DEVICE_DISK_FILE_SYSTEM
:
281 case FILE_DEVICE_VIRTUAL_DISK
:
282 return FILE_TYPE_DISK
;
284 case FILE_DEVICE_KEYBOARD
:
285 case FILE_DEVICE_MOUSE
:
286 case FILE_DEVICE_NULL
:
287 case FILE_DEVICE_PARALLEL_PORT
:
288 case FILE_DEVICE_PRINTER
:
289 case FILE_DEVICE_SERIAL_PORT
:
290 case FILE_DEVICE_SCREEN
:
291 case FILE_DEVICE_SOUND
:
292 case FILE_DEVICE_MODEM
:
293 return FILE_TYPE_CHAR
;
295 case FILE_DEVICE_NAMED_PIPE
:
296 return FILE_TYPE_PIPE
;
299 return FILE_TYPE_UNKNOWN
;
304 GetFileSize(HANDLE hFile
,
305 LPDWORD lpFileSizeHigh
)
308 FILE_STANDARD_INFORMATION FileStandard
;
309 IO_STATUS_BLOCK IoStatusBlock
;
311 errCode
= NtQueryInformationFile(hFile
,
314 sizeof(FILE_STANDARD_INFORMATION
),
315 FileStandardInformation
);
316 if (!NT_SUCCESS(errCode
))
318 SetLastErrorByStatus(errCode
);
319 if ( lpFileSizeHigh
== NULL
)
328 if ( lpFileSizeHigh
!= NULL
)
329 *lpFileSizeHigh
= FileStandard
.AllocationSize
.u
.HighPart
;
331 return FileStandard
.AllocationSize
.u
.LowPart
;
336 GetCompressedFileSizeA(LPCSTR lpFileName
,
337 LPDWORD lpFileSizeHigh
)
339 UNICODE_STRING FileNameU
;
340 ANSI_STRING FileName
;
343 RtlInitAnsiString(&FileName
,
346 /* convert ansi (or oem) string to unicode */
348 RtlAnsiStringToUnicodeString(&FileNameU
,
352 RtlOemStringToUnicodeString(&FileNameU
,
356 Size
= GetCompressedFileSizeW(FileNameU
.Buffer
,
359 RtlFreeUnicodeString (&FileNameU
);
366 GetCompressedFileSizeW(LPCWSTR lpFileName
,
367 LPDWORD lpFileSizeHigh
)
369 FILE_COMPRESSION_INFORMATION FileCompression
;
371 IO_STATUS_BLOCK IoStatusBlock
;
374 hFile
= CreateFileW(lpFileName
,
379 FILE_ATTRIBUTE_NORMAL
,
382 errCode
= NtQueryInformationFile(hFile
,
385 sizeof(FILE_COMPRESSION_INFORMATION
),
386 FileCompressionInformation
);
387 if (!NT_SUCCESS(errCode
))
390 SetLastErrorByStatus(errCode
);
399 GetFileInformationByHandle(HANDLE hFile
,
400 LPBY_HANDLE_FILE_INFORMATION lpFileInformation
)
404 FILE_FS_VOLUME_INFORMATION FileFsVolume
;
409 FILE_BASIC_INFORMATION FileBasic
;
410 FILE_INTERNAL_INFORMATION FileInternal
;
411 FILE_STANDARD_INFORMATION FileStandard
;
413 IO_STATUS_BLOCK IoStatusBlock
;
415 errCode
= NtQueryInformationFile(hFile
,
418 sizeof(FILE_BASIC_INFORMATION
),
419 FileBasicInformation
);
420 if (!NT_SUCCESS(errCode
))
422 SetLastErrorByStatus(errCode
);
426 lpFileInformation
->dwFileAttributes
= (DWORD
)FileBasic
.FileAttributes
;
427 memcpy(&lpFileInformation
->ftCreationTime
,&FileBasic
.CreationTime
,sizeof(LARGE_INTEGER
));
428 memcpy(&lpFileInformation
->ftLastAccessTime
,&FileBasic
.LastAccessTime
,sizeof(LARGE_INTEGER
));
429 memcpy(&lpFileInformation
->ftLastWriteTime
, &FileBasic
.LastWriteTime
,sizeof(LARGE_INTEGER
));
431 errCode
= NtQueryInformationFile(hFile
,
434 sizeof(FILE_INTERNAL_INFORMATION
),
435 FileInternalInformation
);
436 if (!NT_SUCCESS(errCode
))
438 SetLastErrorByStatus(errCode
);
442 lpFileInformation
->nFileIndexHigh
= FileInternal
.IndexNumber
.u
.HighPart
;
443 lpFileInformation
->nFileIndexLow
= FileInternal
.IndexNumber
.u
.LowPart
;
445 errCode
= NtQueryVolumeInformationFile(hFile
,
448 sizeof(FileFsVolume
),
449 FileFsVolumeInformation
);
450 if (!NT_SUCCESS(errCode
))
452 SetLastErrorByStatus(errCode
);
456 lpFileInformation
->dwVolumeSerialNumber
= FileFsVolume
.FileFsVolume
.VolumeSerialNumber
;
458 errCode
= NtQueryInformationFile(hFile
,
461 sizeof(FILE_STANDARD_INFORMATION
),
462 FileStandardInformation
);
463 if (!NT_SUCCESS(errCode
))
465 SetLastErrorByStatus(errCode
);
469 lpFileInformation
->nNumberOfLinks
= FileStandard
.NumberOfLinks
;
470 lpFileInformation
->nFileSizeHigh
= FileStandard
.AllocationSize
.u
.HighPart
;
471 lpFileInformation
->nFileSizeLow
= FileStandard
.AllocationSize
.u
.LowPart
;
478 GetFileAttributesA(LPCSTR lpFileName
)
480 UNICODE_STRING FileNameU
;
481 ANSI_STRING FileName
;
484 RtlInitAnsiString (&FileName
,
487 /* convert ansi (or oem) string to unicode */
489 RtlAnsiStringToUnicodeString (&FileNameU
,
493 RtlOemStringToUnicodeString (&FileNameU
,
497 Result
= GetFileAttributesW (FileNameU
.Buffer
);
499 RtlFreeUnicodeString (&FileNameU
);
506 GetFileAttributesW(LPCWSTR lpFileName
)
508 IO_STATUS_BLOCK IoStatusBlock
;
509 FILE_BASIC_INFORMATION FileBasic
;
513 hFile
= CreateFileW(lpFileName
,
514 FILE_READ_ATTRIBUTES
,
518 FILE_ATTRIBUTE_NORMAL
,
520 if (hFile
== INVALID_HANDLE_VALUE
)
525 errCode
= NtQueryInformationFile(hFile
,
528 sizeof(FILE_BASIC_INFORMATION
),
529 FileBasicInformation
);
530 if (!NT_SUCCESS(errCode
))
533 SetLastErrorByStatus(errCode
);
537 return (DWORD
)FileBasic
.FileAttributes
;
542 SetFileAttributesA(LPCSTR lpFileName
,
543 DWORD dwFileAttributes
)
545 UNICODE_STRING FileNameU
;
546 ANSI_STRING FileName
;
549 RtlInitAnsiString(&FileName
,
552 /* convert ansi (or oem) string to unicode */
554 RtlAnsiStringToUnicodeString(&FileNameU
,
558 RtlOemStringToUnicodeString(&FileNameU
,
562 Result
= SetFileAttributesW(FileNameU
.Buffer
,
565 RtlFreeUnicodeString(&FileNameU
);
572 SetFileAttributesW(LPCWSTR lpFileName
,
573 DWORD dwFileAttributes
)
575 IO_STATUS_BLOCK IoStatusBlock
;
576 FILE_BASIC_INFORMATION FileBasic
;
580 hFile
= CreateFileW(lpFileName
,
581 FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
,
585 FILE_ATTRIBUTE_NORMAL
,
588 errCode
= NtQueryInformationFile(hFile
,
591 sizeof(FILE_BASIC_INFORMATION
),
592 FileBasicInformation
);
593 if (!NT_SUCCESS(errCode
))
596 SetLastErrorByStatus(errCode
);
599 FileBasic
.FileAttributes
= dwFileAttributes
;
600 errCode
= NtSetInformationFile(hFile
,
603 sizeof(FILE_BASIC_INFORMATION
),
604 FileBasicInformation
);
605 if (!NT_SUCCESS(errCode
))
608 SetLastErrorByStatus(errCode
);
617 GetTempFileNameA(LPCSTR lpPathName
,
618 LPCSTR lpPrefixString
,
620 LPSTR lpTempFileName
)
623 UINT unique
= uUnique
;
625 if (lpPathName
== NULL
)
629 uUnique
= GetCurrentTime();
631 * sprintf(lpTempFileName,"%s\\%c%.3s%4.4x%s",
632 * lpPathName,'~',lpPrefixString,uUnique,".tmp");
637 while ((hFile
= CreateFileA(lpTempFileName
, GENERIC_WRITE
, 0, NULL
,
638 CREATE_NEW
, FILE_ATTRIBUTE_TEMPORARY
,
639 0)) == INVALID_HANDLE_VALUE
)
641 // wsprintfA(lpTempFileName,"%s\\%c%.3s%4.4x%s",
642 // lpPathName,'~',lpPrefixString,++uUnique,".tmp");
645 CloseHandle((HANDLE
)hFile
);
651 GetTempFileNameW(LPCWSTR lpPathName
,
652 LPCWSTR lpPrefixString
,
654 LPWSTR lpTempFileName
)
657 UINT unique
= uUnique
;
659 if (lpPathName
== NULL
)
663 uUnique
= GetCurrentTime();
665 // swprintf(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
666 // lpPathName,'~',lpPrefixString,uUnique,L".tmp");
671 while ((hFile
= CreateFileW(lpTempFileName
, GENERIC_WRITE
, 0, NULL
,
672 CREATE_NEW
, FILE_ATTRIBUTE_TEMPORARY
,
673 0)) == INVALID_HANDLE_VALUE
)
675 // wsprintfW(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
676 // lpPathName,'~',lpPrefixString,++uUnique,L".tmp");
679 CloseHandle((HANDLE
)hFile
);
685 GetFileTime(HANDLE hFile
,
686 LPFILETIME lpCreationTime
,
687 LPFILETIME lpLastAccessTime
,
688 LPFILETIME lpLastWriteTime
)
690 IO_STATUS_BLOCK IoStatusBlock
;
691 FILE_BASIC_INFORMATION FileBasic
;
694 Status
= NtQueryInformationFile(hFile
,
697 sizeof(FILE_BASIC_INFORMATION
),
698 FileBasicInformation
);
699 if (!NT_SUCCESS(Status
))
701 SetLastErrorByStatus(Status
);
706 memcpy(lpCreationTime
, &FileBasic
.CreationTime
, sizeof(FILETIME
));
707 if (lpLastAccessTime
)
708 memcpy(lpLastAccessTime
, &FileBasic
.LastAccessTime
, sizeof(FILETIME
));
710 memcpy(lpLastWriteTime
, &FileBasic
.LastWriteTime
, sizeof(FILETIME
));
717 SetFileTime(HANDLE hFile
,
718 CONST FILETIME
*lpCreationTime
,
719 CONST FILETIME
*lpLastAccessTime
,
720 CONST FILETIME
*lpLastWriteTime
)
722 FILE_BASIC_INFORMATION FileBasic
;
723 IO_STATUS_BLOCK IoStatusBlock
;
726 Status
= NtQueryInformationFile(hFile
,
729 sizeof(FILE_BASIC_INFORMATION
),
730 FileBasicInformation
);
731 if (!NT_SUCCESS(Status
))
733 SetLastErrorByStatus(Status
);
738 memcpy(&FileBasic
.CreationTime
, lpCreationTime
, sizeof(FILETIME
));
739 if (lpLastAccessTime
)
740 memcpy(&FileBasic
.LastAccessTime
, lpLastAccessTime
, sizeof(FILETIME
));
742 memcpy(&FileBasic
.LastWriteTime
, lpLastWriteTime
, sizeof(FILETIME
));
744 // should i initialize changetime ???
746 Status
= NtSetInformationFile(hFile
,
749 sizeof(FILE_BASIC_INFORMATION
),
750 FileBasicInformation
);
751 if (!NT_SUCCESS(Status
))
753 SetLastErrorByStatus(Status
);
762 SetEndOfFile(HANDLE hFile
)
766 return WriteFile(hFile
,&x
,1,&Num
,NULL
);