1 /* $Id: file.c,v 1.27 2001/08/06 18:35:15 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 Distance
.u
.HighPart
= (lpDistanceToMoveHigh
) ? *lpDistanceToMoveHigh
: 0;
177 if (dwMoveMethod
== FILE_CURRENT
)
179 NtQueryInformationFile(hFile
,
182 sizeof(FILE_POSITION_INFORMATION
),
183 FilePositionInformation
);
184 FilePosition
.CurrentByteOffset
.QuadPart
+= Distance
.QuadPart
;
186 else if (dwMoveMethod
== FILE_END
)
188 NtQueryInformationFile(hFile
,
191 sizeof(FILE_STANDARD_INFORMATION
),
192 FileStandardInformation
);
193 FilePosition
.CurrentByteOffset
.QuadPart
=
194 FileStandart
.EndOfFile
.QuadPart
+ Distance
.QuadPart
;
196 else if ( dwMoveMethod
== FILE_BEGIN
)
198 FilePosition
.CurrentByteOffset
.QuadPart
= Distance
.QuadPart
;
201 errCode
= NtSetInformationFile(hFile
,
204 sizeof(FILE_POSITION_INFORMATION
),
205 FilePositionInformation
);
206 if (!NT_SUCCESS(errCode
))
208 SetLastErrorByStatus(errCode
);
212 if (lpDistanceToMoveHigh
!= NULL
)
214 *lpDistanceToMoveHigh
= FilePosition
.CurrentByteOffset
.u
.HighPart
;
216 return FilePosition
.CurrentByteOffset
.u
.LowPart
;
221 GetFileType(HANDLE hFile
)
223 FILE_FS_DEVICE_INFORMATION DeviceInfo
;
224 IO_STATUS_BLOCK StatusBlock
;
227 /* get real handle */
228 switch ((ULONG
)hFile
)
230 case STD_INPUT_HANDLE
:
231 hFile
= NtCurrentPeb()->ProcessParameters
->InputHandle
;
234 case STD_OUTPUT_HANDLE
:
235 hFile
= NtCurrentPeb()->ProcessParameters
->OutputHandle
;
238 case STD_ERROR_HANDLE
:
239 hFile
= NtCurrentPeb()->ProcessParameters
->ErrorHandle
;
243 /* check console handles */
244 if (((ULONG
)hFile
& 3) == 3)
246 // if (VerifyConsoleHandle(hFile))
247 return FILE_TYPE_CHAR
;
250 Status
= NtQueryVolumeInformationFile(hFile
,
253 sizeof(FILE_FS_DEVICE_INFORMATION
),
254 FileFsDeviceInformation
);
255 if (!NT_SUCCESS(Status
))
257 SetLastErrorByStatus(Status
);
258 return FILE_TYPE_UNKNOWN
;
261 switch (DeviceInfo
.DeviceType
)
263 case FILE_DEVICE_CD_ROM
:
264 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
265 case FILE_DEVICE_CONTROLLER
:
266 case FILE_DEVICE_DATALINK
:
267 case FILE_DEVICE_DFS
:
268 case FILE_DEVICE_DISK
:
269 case FILE_DEVICE_DISK_FILE_SYSTEM
:
270 case FILE_DEVICE_VIRTUAL_DISK
:
271 return FILE_TYPE_DISK
;
273 case FILE_DEVICE_KEYBOARD
:
274 case FILE_DEVICE_MOUSE
:
275 case FILE_DEVICE_NULL
:
276 case FILE_DEVICE_PARALLEL_PORT
:
277 case FILE_DEVICE_PRINTER
:
278 case FILE_DEVICE_SERIAL_PORT
:
279 case FILE_DEVICE_SCREEN
:
280 case FILE_DEVICE_SOUND
:
281 case FILE_DEVICE_MODEM
:
282 return FILE_TYPE_CHAR
;
284 case FILE_DEVICE_NAMED_PIPE
:
285 return FILE_TYPE_PIPE
;
288 return FILE_TYPE_UNKNOWN
;
293 GetFileSize(HANDLE hFile
,
294 LPDWORD lpFileSizeHigh
)
297 FILE_STANDARD_INFORMATION FileStandard
;
298 IO_STATUS_BLOCK IoStatusBlock
;
300 errCode
= NtQueryInformationFile(hFile
,
303 sizeof(FILE_STANDARD_INFORMATION
),
304 FileStandardInformation
);
305 if (!NT_SUCCESS(errCode
))
307 SetLastErrorByStatus(errCode
);
308 if ( lpFileSizeHigh
== NULL
)
317 if ( lpFileSizeHigh
!= NULL
)
318 *lpFileSizeHigh
= FileStandard
.AllocationSize
.u
.HighPart
;
320 return FileStandard
.AllocationSize
.u
.LowPart
;
325 GetCompressedFileSizeA(LPCSTR lpFileName
,
326 LPDWORD lpFileSizeHigh
)
328 UNICODE_STRING FileNameU
;
329 ANSI_STRING FileName
;
332 RtlInitAnsiString(&FileName
,
335 /* convert ansi (or oem) string to unicode */
337 RtlAnsiStringToUnicodeString(&FileNameU
,
341 RtlOemStringToUnicodeString(&FileNameU
,
345 Size
= GetCompressedFileSizeW(FileNameU
.Buffer
,
348 RtlFreeUnicodeString (&FileNameU
);
355 GetCompressedFileSizeW(LPCWSTR lpFileName
,
356 LPDWORD lpFileSizeHigh
)
358 FILE_COMPRESSION_INFORMATION FileCompression
;
360 IO_STATUS_BLOCK IoStatusBlock
;
363 hFile
= CreateFileW(lpFileName
,
368 FILE_ATTRIBUTE_NORMAL
,
371 errCode
= NtQueryInformationFile(hFile
,
374 sizeof(FILE_COMPRESSION_INFORMATION
),
375 FileCompressionInformation
);
376 if (!NT_SUCCESS(errCode
))
379 SetLastErrorByStatus(errCode
);
388 GetFileInformationByHandle(HANDLE hFile
,
389 LPBY_HANDLE_FILE_INFORMATION lpFileInformation
)
391 FILE_DIRECTORY_INFORMATION FileDirectory
;
392 FILE_INTERNAL_INFORMATION FileInternal
;
393 FILE_FS_VOLUME_INFORMATION FileFsVolume
;
394 FILE_STANDARD_INFORMATION FileStandard
;
396 IO_STATUS_BLOCK IoStatusBlock
;
398 errCode
= NtQueryInformationFile(hFile
,
401 sizeof(FILE_DIRECTORY_INFORMATION
),
402 FileDirectoryInformation
);
403 if (!NT_SUCCESS(errCode
))
405 SetLastErrorByStatus(errCode
);
409 lpFileInformation
->dwFileAttributes
= (DWORD
)FileDirectory
.FileAttributes
;
410 memcpy(&lpFileInformation
->ftCreationTime
,&FileDirectory
.CreationTime
,sizeof(LARGE_INTEGER
));
411 memcpy(&lpFileInformation
->ftLastAccessTime
,&FileDirectory
.LastAccessTime
,sizeof(LARGE_INTEGER
));
412 memcpy(&lpFileInformation
->ftLastWriteTime
, &FileDirectory
.LastWriteTime
,sizeof(LARGE_INTEGER
));
413 lpFileInformation
->nFileSizeHigh
= FileDirectory
.AllocationSize
.u
.HighPart
;
414 lpFileInformation
->nFileSizeLow
= FileDirectory
.AllocationSize
.u
.LowPart
;
416 errCode
= NtQueryInformationFile(hFile
,
419 sizeof(FILE_INTERNAL_INFORMATION
),
420 FileInternalInformation
);
421 if (!NT_SUCCESS(errCode
))
423 SetLastErrorByStatus(errCode
);
427 lpFileInformation
->nFileIndexHigh
= FileInternal
.IndexNumber
.u
.HighPart
;
428 lpFileInformation
->nFileIndexLow
= FileInternal
.IndexNumber
.u
.LowPart
;
430 errCode
= NtQueryVolumeInformationFile(hFile
,
433 sizeof(FILE_FS_VOLUME_INFORMATION
),
434 FileFsVolumeInformation
);
435 if (!NT_SUCCESS(errCode
))
437 SetLastErrorByStatus(errCode
);
441 lpFileInformation
->dwVolumeSerialNumber
= FileFsVolume
.VolumeSerialNumber
;
443 errCode
= NtQueryInformationFile(hFile
,
446 sizeof(FILE_STANDARD_INFORMATION
),
447 FileStandardInformation
);
448 if (!NT_SUCCESS(errCode
))
450 SetLastErrorByStatus(errCode
);
454 lpFileInformation
->nNumberOfLinks
= FileStandard
.NumberOfLinks
;
461 GetFileAttributesA(LPCSTR lpFileName
)
463 UNICODE_STRING FileNameU
;
464 ANSI_STRING FileName
;
467 RtlInitAnsiString (&FileName
,
470 /* convert ansi (or oem) string to unicode */
472 RtlAnsiStringToUnicodeString (&FileNameU
,
476 RtlOemStringToUnicodeString (&FileNameU
,
480 Result
= GetFileAttributesW (FileNameU
.Buffer
);
482 RtlFreeUnicodeString (&FileNameU
);
489 GetFileAttributesW(LPCWSTR lpFileName
)
491 IO_STATUS_BLOCK IoStatusBlock
;
492 FILE_BASIC_INFORMATION FileBasic
;
496 hFile
= CreateFileW(lpFileName
,
497 FILE_READ_ATTRIBUTES
,
501 FILE_ATTRIBUTE_NORMAL
,
503 if (hFile
== INVALID_HANDLE_VALUE
)
508 errCode
= NtQueryInformationFile(hFile
,
511 sizeof(FILE_BASIC_INFORMATION
),
512 FileBasicInformation
);
513 if (!NT_SUCCESS(errCode
))
516 SetLastErrorByStatus(errCode
);
520 return (DWORD
)FileBasic
.FileAttributes
;
525 SetFileAttributesA(LPCSTR lpFileName
,
526 DWORD dwFileAttributes
)
528 UNICODE_STRING FileNameU
;
529 ANSI_STRING FileName
;
532 RtlInitAnsiString(&FileName
,
535 /* convert ansi (or oem) string to unicode */
537 RtlAnsiStringToUnicodeString(&FileNameU
,
541 RtlOemStringToUnicodeString(&FileNameU
,
545 Result
= SetFileAttributesW(FileNameU
.Buffer
,
548 RtlFreeUnicodeString(&FileNameU
);
555 SetFileAttributesW(LPCWSTR lpFileName
,
556 DWORD dwFileAttributes
)
558 IO_STATUS_BLOCK IoStatusBlock
;
559 FILE_BASIC_INFORMATION FileBasic
;
563 hFile
= CreateFileW(lpFileName
,
564 FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
,
568 FILE_ATTRIBUTE_NORMAL
,
571 errCode
= NtQueryInformationFile(hFile
,
574 sizeof(FILE_BASIC_INFORMATION
),
575 FileBasicInformation
);
576 if (!NT_SUCCESS(errCode
))
579 SetLastErrorByStatus(errCode
);
582 FileBasic
.FileAttributes
= dwFileAttributes
;
583 errCode
= NtSetInformationFile(hFile
,
586 sizeof(FILE_BASIC_INFORMATION
),
587 FileBasicInformation
);
588 if (!NT_SUCCESS(errCode
))
591 SetLastErrorByStatus(errCode
);
600 GetTempFileNameA(LPCSTR lpPathName
,
601 LPCSTR lpPrefixString
,
603 LPSTR lpTempFileName
)
606 UINT unique
= uUnique
;
608 if (lpPathName
== NULL
)
612 uUnique
= GetCurrentTime();
614 * sprintf(lpTempFileName,"%s\\%c%.3s%4.4x%s",
615 * lpPathName,'~',lpPrefixString,uUnique,".tmp");
620 while ((hFile
= CreateFileA(lpTempFileName
, GENERIC_WRITE
, 0, NULL
,
621 CREATE_NEW
, FILE_ATTRIBUTE_TEMPORARY
,
622 0)) == INVALID_HANDLE_VALUE
)
624 // wsprintfA(lpTempFileName,"%s\\%c%.3s%4.4x%s",
625 // lpPathName,'~',lpPrefixString,++uUnique,".tmp");
628 CloseHandle((HANDLE
)hFile
);
634 GetTempFileNameW(LPCWSTR lpPathName
,
635 LPCWSTR lpPrefixString
,
637 LPWSTR lpTempFileName
)
640 UINT unique
= uUnique
;
642 if (lpPathName
== NULL
)
646 uUnique
= GetCurrentTime();
648 // swprintf(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
649 // lpPathName,'~',lpPrefixString,uUnique,L".tmp");
654 while ((hFile
= CreateFileW(lpTempFileName
, GENERIC_WRITE
, 0, NULL
,
655 CREATE_NEW
, FILE_ATTRIBUTE_TEMPORARY
,
656 0)) == INVALID_HANDLE_VALUE
)
658 // wsprintfW(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
659 // lpPathName,'~',lpPrefixString,++uUnique,L".tmp");
662 CloseHandle((HANDLE
)hFile
);
668 GetFileTime(HANDLE hFile
,
669 LPFILETIME lpCreationTime
,
670 LPFILETIME lpLastAccessTime
,
671 LPFILETIME lpLastWriteTime
)
673 IO_STATUS_BLOCK IoStatusBlock
;
674 FILE_BASIC_INFORMATION FileBasic
;
677 Status
= NtQueryInformationFile(hFile
,
680 sizeof(FILE_BASIC_INFORMATION
),
681 FileBasicInformation
);
682 if (!NT_SUCCESS(Status
))
684 SetLastErrorByStatus(Status
);
689 memcpy(lpCreationTime
, &FileBasic
.CreationTime
, sizeof(FILETIME
));
690 if (lpLastAccessTime
)
691 memcpy(lpLastAccessTime
, &FileBasic
.LastAccessTime
, sizeof(FILETIME
));
693 memcpy(lpLastWriteTime
, &FileBasic
.LastWriteTime
, sizeof(FILETIME
));
700 SetFileTime(HANDLE hFile
,
701 CONST FILETIME
*lpCreationTime
,
702 CONST FILETIME
*lpLastAccessTime
,
703 CONST FILETIME
*lpLastWriteTime
)
705 FILE_BASIC_INFORMATION FileBasic
;
706 IO_STATUS_BLOCK IoStatusBlock
;
709 Status
= NtQueryInformationFile(hFile
,
712 sizeof(FILE_BASIC_INFORMATION
),
713 FileBasicInformation
);
714 if (!NT_SUCCESS(Status
))
716 SetLastErrorByStatus(Status
);
721 memcpy(&FileBasic
.CreationTime
, lpCreationTime
, sizeof(FILETIME
));
722 if (lpLastAccessTime
)
723 memcpy(&FileBasic
.LastAccessTime
, lpLastAccessTime
, sizeof(FILETIME
));
725 memcpy(&FileBasic
.LastWriteTime
, lpLastWriteTime
, sizeof(FILETIME
));
727 // should i initialize changetime ???
729 Status
= NtSetInformationFile(hFile
,
732 sizeof(FILE_BASIC_INFORMATION
),
733 FileBasicInformation
);
734 if (!NT_SUCCESS(Status
))
736 SetLastErrorByStatus(Status
);
745 SetEndOfFile(HANDLE hFile
)
749 return WriteFile(hFile
,&x
,1,&Num
,NULL
);