Do not call NtFlushBuffersFile for console handles.
[reactos.git] / reactos / lib / kernel32 / file / file.c
1 /* $Id: file.c,v 1.32 2002/05/07 22:21:47 hbirr Exp $
2 *
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 ]
9 * UPDATE HISTORY:
10 * Created 01/11/98
11 */
12
13 /* INCLUDES *****************************************************************/
14
15 #include <ddk/ntddk.h>
16 #include <windows.h>
17 #include <wchar.h>
18 #include <string.h>
19
20 #define NDEBUG
21 #include <kernel32/kernel32.h>
22 #include <kernel32/error.h>
23
24 #define LPPROGRESS_ROUTINE void*
25
26
27 /* GLOBALS ******************************************************************/
28
29 WINBOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
30
31
32 /* FUNCTIONS ****************************************************************/
33
34 VOID STDCALL
35 SetFileApisToOEM(VOID)
36 {
37 bIsFileApiAnsi = FALSE;
38 }
39
40
41 VOID STDCALL
42 SetFileApisToANSI(VOID)
43 {
44 bIsFileApiAnsi = TRUE;
45 }
46
47
48 WINBOOL STDCALL
49 AreFileApisANSI(VOID)
50 {
51 return bIsFileApiAnsi;
52 }
53
54
55 HFILE STDCALL
56 OpenFile(LPCSTR lpFileName,
57 LPOFSTRUCT lpReOpenBuff,
58 UINT uStyle)
59 {
60 OBJECT_ATTRIBUTES ObjectAttributes;
61 IO_STATUS_BLOCK IoStatusBlock;
62 UNICODE_STRING FileNameString;
63 UNICODE_STRING FileNameU;
64 ANSI_STRING FileName;
65 WCHAR PathNameW[MAX_PATH];
66 HANDLE FileHandle = NULL;
67 NTSTATUS errCode;
68 PWCHAR FilePart;
69 ULONG Len;
70
71 DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
72
73 if (lpReOpenBuff == NULL)
74 {
75 return FALSE;
76 }
77
78 RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
79
80 /* convert ansi (or oem) string to unicode */
81 if (bIsFileApiAnsi)
82 RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
83 else
84 RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
85
86 Len = SearchPathW (NULL,
87 FileNameU.Buffer,
88 NULL,
89 OFS_MAXPATHNAME,
90 PathNameW,
91 &FilePart);
92
93 RtlFreeUnicodeString(&FileNameU);
94
95 if (Len == 0 || Len > OFS_MAXPATHNAME)
96 {
97 return (HFILE)INVALID_HANDLE_VALUE;
98 }
99
100 FileName.Buffer = lpReOpenBuff->szPathName;
101 FileName.Length = 0;
102 FileName.MaximumLength = OFS_MAXPATHNAME;
103
104 RtlInitUnicodeString(&FileNameU, PathNameW);
105
106 /* convert unicode string to ansi (or oem) */
107 if (bIsFileApiAnsi)
108 RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
109 else
110 RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
111
112 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)PathNameW,
113 &FileNameString,
114 NULL,
115 NULL))
116 {
117 return (HFILE)INVALID_HANDLE_VALUE;
118 }
119
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;
126
127 // FILE_SHARE_READ
128 // FILE_NO_INTERMEDIATE_BUFFERING
129
130 if ((uStyle & OF_PARSE) == OF_PARSE)
131 {
132 RtlFreeUnicodeString(&FileNameString);
133 return (HFILE)NULL;
134 }
135
136 errCode = NtOpenFile (&FileHandle,
137 GENERIC_READ|SYNCHRONIZE,
138 &ObjectAttributes,
139 &IoStatusBlock,
140 FILE_SHARE_READ,
141 FILE_NON_DIRECTORY_FILE);
142
143 RtlFreeUnicodeString(&FileNameString);
144
145 lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
146
147 if (!NT_SUCCESS(errCode))
148 {
149 SetLastErrorByStatus (errCode);
150 return (HFILE)INVALID_HANDLE_VALUE;
151 }
152
153 return (HFILE)FileHandle;
154 }
155
156
157 WINBOOL STDCALL
158 FlushFileBuffers(HANDLE hFile)
159 {
160 NTSTATUS errCode;
161 IO_STATUS_BLOCK IoStatusBlock;
162
163 if (IsConsoleHandle(hFile))
164 {
165 return FALSE;
166 }
167
168 errCode = NtFlushBuffersFile(hFile,
169 &IoStatusBlock);
170 if (!NT_SUCCESS(errCode))
171 {
172 SetLastErrorByStatus(errCode);
173 return(FALSE);
174 }
175 return(TRUE);
176 }
177
178
179 DWORD STDCALL
180 SetFilePointer(HANDLE hFile,
181 LONG lDistanceToMove,
182 PLONG lpDistanceToMoveHigh,
183 DWORD dwMoveMethod)
184 {
185 FILE_POSITION_INFORMATION FilePosition;
186 FILE_STANDARD_INFORMATION FileStandart;
187 NTSTATUS errCode;
188 IO_STATUS_BLOCK IoStatusBlock;
189 LARGE_INTEGER Distance;
190
191 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
192 hFile,lDistanceToMove,dwMoveMethod);
193
194 Distance.u.LowPart = lDistanceToMove;
195 if (lpDistanceToMoveHigh)
196 {
197 Distance.u.HighPart = *lpDistanceToMoveHigh;
198 }
199 else if (lDistanceToMove >= 0)
200 {
201 Distance.u.HighPart = 0;
202 }
203 else
204 {
205 Distance.u.HighPart = -1;
206 }
207
208 if (dwMoveMethod == FILE_CURRENT)
209 {
210 NtQueryInformationFile(hFile,
211 &IoStatusBlock,
212 &FilePosition,
213 sizeof(FILE_POSITION_INFORMATION),
214 FilePositionInformation);
215 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
216 }
217 else if (dwMoveMethod == FILE_END)
218 {
219 NtQueryInformationFile(hFile,
220 &IoStatusBlock,
221 &FileStandart,
222 sizeof(FILE_STANDARD_INFORMATION),
223 FileStandardInformation);
224 FilePosition.CurrentByteOffset.QuadPart =
225 FileStandart.EndOfFile.QuadPart + Distance.QuadPart;
226 }
227 else if ( dwMoveMethod == FILE_BEGIN )
228 {
229 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
230 }
231
232 errCode = NtSetInformationFile(hFile,
233 &IoStatusBlock,
234 &FilePosition,
235 sizeof(FILE_POSITION_INFORMATION),
236 FilePositionInformation);
237 if (!NT_SUCCESS(errCode))
238 {
239 SetLastErrorByStatus(errCode);
240 return -1;
241 }
242
243 if (lpDistanceToMoveHigh != NULL)
244 {
245 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
246 }
247 return FilePosition.CurrentByteOffset.u.LowPart;
248 }
249
250
251 DWORD STDCALL
252 GetFileType(HANDLE hFile)
253 {
254 FILE_FS_DEVICE_INFORMATION DeviceInfo;
255 IO_STATUS_BLOCK StatusBlock;
256 NTSTATUS Status;
257
258 /* get real handle */
259 switch ((ULONG)hFile)
260 {
261 case STD_INPUT_HANDLE:
262 hFile = NtCurrentPeb()->ProcessParameters->InputHandle;
263 break;
264
265 case STD_OUTPUT_HANDLE:
266 hFile = NtCurrentPeb()->ProcessParameters->OutputHandle;
267 break;
268
269 case STD_ERROR_HANDLE:
270 hFile = NtCurrentPeb()->ProcessParameters->ErrorHandle;
271 break;
272 }
273
274 /* check console handles */
275 if (IsConsoleHandle(hFile))
276 {
277 // if (VerifyConsoleHandle(hFile))
278 return FILE_TYPE_CHAR;
279 }
280
281 Status = NtQueryVolumeInformationFile(hFile,
282 &StatusBlock,
283 &DeviceInfo,
284 sizeof(FILE_FS_DEVICE_INFORMATION),
285 FileFsDeviceInformation);
286 if (!NT_SUCCESS(Status))
287 {
288 SetLastErrorByStatus(Status);
289 return FILE_TYPE_UNKNOWN;
290 }
291
292 switch (DeviceInfo.DeviceType)
293 {
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;
303
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;
314
315 case FILE_DEVICE_NAMED_PIPE:
316 return FILE_TYPE_PIPE;
317 }
318
319 return FILE_TYPE_UNKNOWN;
320 }
321
322
323 DWORD STDCALL
324 GetFileSize(HANDLE hFile,
325 LPDWORD lpFileSizeHigh)
326 {
327 NTSTATUS errCode;
328 FILE_STANDARD_INFORMATION FileStandard;
329 IO_STATUS_BLOCK IoStatusBlock;
330
331 errCode = NtQueryInformationFile(hFile,
332 &IoStatusBlock,
333 &FileStandard,
334 sizeof(FILE_STANDARD_INFORMATION),
335 FileStandardInformation);
336 if (!NT_SUCCESS(errCode))
337 {
338 SetLastErrorByStatus(errCode);
339 if ( lpFileSizeHigh == NULL )
340 {
341 return -1;
342 }
343 else
344 {
345 return 0;
346 }
347 }
348 if ( lpFileSizeHigh != NULL )
349 *lpFileSizeHigh = FileStandard.AllocationSize.u.HighPart;
350
351 return FileStandard.AllocationSize.u.LowPart;
352 }
353
354
355 DWORD STDCALL
356 GetCompressedFileSizeA(LPCSTR lpFileName,
357 LPDWORD lpFileSizeHigh)
358 {
359 UNICODE_STRING FileNameU;
360 ANSI_STRING FileName;
361 DWORD Size;
362
363 RtlInitAnsiString(&FileName,
364 (LPSTR)lpFileName);
365
366 /* convert ansi (or oem) string to unicode */
367 if (bIsFileApiAnsi)
368 RtlAnsiStringToUnicodeString(&FileNameU,
369 &FileName,
370 TRUE);
371 else
372 RtlOemStringToUnicodeString(&FileNameU,
373 &FileName,
374 TRUE);
375
376 Size = GetCompressedFileSizeW(FileNameU.Buffer,
377 lpFileSizeHigh);
378
379 RtlFreeUnicodeString (&FileNameU);
380
381 return Size;
382 }
383
384
385 DWORD STDCALL
386 GetCompressedFileSizeW(LPCWSTR lpFileName,
387 LPDWORD lpFileSizeHigh)
388 {
389 FILE_COMPRESSION_INFORMATION FileCompression;
390 NTSTATUS errCode;
391 IO_STATUS_BLOCK IoStatusBlock;
392 HANDLE hFile;
393
394 hFile = CreateFileW(lpFileName,
395 GENERIC_READ,
396 FILE_SHARE_READ,
397 NULL,
398 OPEN_EXISTING,
399 FILE_ATTRIBUTE_NORMAL,
400 NULL);
401
402 errCode = NtQueryInformationFile(hFile,
403 &IoStatusBlock,
404 &FileCompression,
405 sizeof(FILE_COMPRESSION_INFORMATION),
406 FileCompressionInformation);
407 if (!NT_SUCCESS(errCode))
408 {
409 CloseHandle(hFile);
410 SetLastErrorByStatus(errCode);
411 return 0;
412 }
413 CloseHandle(hFile);
414 return 0;
415 }
416
417
418 WINBOOL STDCALL
419 GetFileInformationByHandle(HANDLE hFile,
420 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
421 {
422 struct
423 {
424 FILE_FS_VOLUME_INFORMATION FileFsVolume;
425 WCHAR Name[255];
426 }
427 FileFsVolume;
428
429 FILE_BASIC_INFORMATION FileBasic;
430 FILE_INTERNAL_INFORMATION FileInternal;
431 FILE_STANDARD_INFORMATION FileStandard;
432 NTSTATUS errCode;
433 IO_STATUS_BLOCK IoStatusBlock;
434
435 errCode = NtQueryInformationFile(hFile,
436 &IoStatusBlock,
437 &FileBasic,
438 sizeof(FILE_BASIC_INFORMATION),
439 FileBasicInformation);
440 if (!NT_SUCCESS(errCode))
441 {
442 SetLastErrorByStatus(errCode);
443 return FALSE;
444 }
445
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));
450
451 errCode = NtQueryInformationFile(hFile,
452 &IoStatusBlock,
453 &FileInternal,
454 sizeof(FILE_INTERNAL_INFORMATION),
455 FileInternalInformation);
456 if (!NT_SUCCESS(errCode))
457 {
458 SetLastErrorByStatus(errCode);
459 return FALSE;
460 }
461
462 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
463 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
464
465 errCode = NtQueryVolumeInformationFile(hFile,
466 &IoStatusBlock,
467 &FileFsVolume,
468 sizeof(FileFsVolume),
469 FileFsVolumeInformation);
470 if (!NT_SUCCESS(errCode))
471 {
472 SetLastErrorByStatus(errCode);
473 return FALSE;
474 }
475
476 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
477
478 errCode = NtQueryInformationFile(hFile,
479 &IoStatusBlock,
480 &FileStandard,
481 sizeof(FILE_STANDARD_INFORMATION),
482 FileStandardInformation);
483 if (!NT_SUCCESS(errCode))
484 {
485 SetLastErrorByStatus(errCode);
486 return FALSE;
487 }
488
489 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
490 lpFileInformation->nFileSizeHigh = FileStandard.AllocationSize.u.HighPart;
491 lpFileInformation->nFileSizeLow = FileStandard.AllocationSize.u.LowPart;
492
493 return TRUE;
494 }
495
496
497 DWORD STDCALL
498 GetFileAttributesA(LPCSTR lpFileName)
499 {
500 UNICODE_STRING FileNameU;
501 ANSI_STRING FileName;
502 WINBOOL Result;
503
504 RtlInitAnsiString (&FileName,
505 (LPSTR)lpFileName);
506
507 /* convert ansi (or oem) string to unicode */
508 if (bIsFileApiAnsi)
509 RtlAnsiStringToUnicodeString (&FileNameU,
510 &FileName,
511 TRUE);
512 else
513 RtlOemStringToUnicodeString (&FileNameU,
514 &FileName,
515 TRUE);
516
517 Result = GetFileAttributesW (FileNameU.Buffer);
518
519 RtlFreeUnicodeString (&FileNameU);
520
521 return Result;
522 }
523
524
525 DWORD STDCALL
526 GetFileAttributesW(LPCWSTR lpFileName)
527 {
528 IO_STATUS_BLOCK IoStatusBlock;
529 FILE_BASIC_INFORMATION FileBasic;
530 HANDLE hFile;
531 NTSTATUS errCode;
532
533 hFile = CreateFileW(lpFileName,
534 FILE_READ_ATTRIBUTES,
535 FILE_SHARE_READ,
536 NULL,
537 OPEN_EXISTING,
538 FILE_ATTRIBUTE_NORMAL,
539 NULL);
540 if (hFile == INVALID_HANDLE_VALUE)
541 {
542 return 0xFFFFFFFF;
543 }
544
545 errCode = NtQueryInformationFile(hFile,
546 &IoStatusBlock,
547 &FileBasic,
548 sizeof(FILE_BASIC_INFORMATION),
549 FileBasicInformation);
550 if (!NT_SUCCESS(errCode))
551 {
552 CloseHandle(hFile);
553 SetLastErrorByStatus(errCode);
554 return 0xFFFFFFFF;
555 }
556 CloseHandle(hFile);
557 return (DWORD)FileBasic.FileAttributes;
558 }
559
560
561 WINBOOL STDCALL
562 SetFileAttributesA(LPCSTR lpFileName,
563 DWORD dwFileAttributes)
564 {
565 UNICODE_STRING FileNameU;
566 ANSI_STRING FileName;
567 WINBOOL Result;
568
569 RtlInitAnsiString(&FileName,
570 (LPSTR)lpFileName);
571
572 /* convert ansi (or oem) string to unicode */
573 if (bIsFileApiAnsi)
574 RtlAnsiStringToUnicodeString(&FileNameU,
575 &FileName,
576 TRUE);
577 else
578 RtlOemStringToUnicodeString(&FileNameU,
579 &FileName,
580 TRUE);
581
582 Result = SetFileAttributesW(FileNameU.Buffer,
583 dwFileAttributes);
584
585 RtlFreeUnicodeString(&FileNameU);
586
587 return Result;
588 }
589
590
591 WINBOOL STDCALL
592 SetFileAttributesW(LPCWSTR lpFileName,
593 DWORD dwFileAttributes)
594 {
595 IO_STATUS_BLOCK IoStatusBlock;
596 FILE_BASIC_INFORMATION FileBasic;
597 HANDLE hFile;
598 NTSTATUS errCode;
599
600 hFile = CreateFileW(lpFileName,
601 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
602 FILE_SHARE_READ,
603 NULL,
604 OPEN_EXISTING,
605 FILE_ATTRIBUTE_NORMAL,
606 NULL);
607
608 errCode = NtQueryInformationFile(hFile,
609 &IoStatusBlock,
610 &FileBasic,
611 sizeof(FILE_BASIC_INFORMATION),
612 FileBasicInformation);
613 if (!NT_SUCCESS(errCode))
614 {
615 CloseHandle(hFile);
616 SetLastErrorByStatus(errCode);
617 return FALSE;
618 }
619 FileBasic.FileAttributes = dwFileAttributes;
620 errCode = NtSetInformationFile(hFile,
621 &IoStatusBlock,
622 &FileBasic,
623 sizeof(FILE_BASIC_INFORMATION),
624 FileBasicInformation);
625 if (!NT_SUCCESS(errCode))
626 {
627 CloseHandle(hFile);
628 SetLastErrorByStatus(errCode);
629 return FALSE;
630 }
631 CloseHandle(hFile);
632 return TRUE;
633 }
634
635
636 UINT STDCALL
637 GetTempFileNameA(LPCSTR lpPathName,
638 LPCSTR lpPrefixString,
639 UINT uUnique,
640 LPSTR lpTempFileName)
641 {
642 HANDLE hFile;
643 UINT unique = uUnique;
644 UINT len;
645 const char *format = "%.*s\\~%.3s%4.4x.TMP";
646
647 DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
648 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
649 lpPrefixString, uUnique, lpTempFileName);
650
651 if (lpPathName == NULL)
652 return 0;
653
654 len = strlen(lpPathName);
655 if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
656 len--;
657
658 if (uUnique == 0)
659 uUnique = GetCurrentTime();
660
661 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
662
663 if (unique)
664 return uUnique;
665
666 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
667 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
668 0)) == INVALID_HANDLE_VALUE)
669 {
670 if (GetLastError() != ERROR_ALREADY_EXISTS)
671 {
672 return 0;
673 }
674 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
675 }
676 CloseHandle(hFile);
677 return uUnique;
678 }
679
680
681 UINT STDCALL
682 GetTempFileNameW(LPCWSTR lpPathName,
683 LPCWSTR lpPrefixString,
684 UINT uUnique,
685 LPWSTR lpTempFileName)
686 {
687 HANDLE hFile;
688 UINT unique = uUnique;
689 UINT len;
690 const WCHAR *format = L"%.*S\\~%.3S%4.4x.TMP";
691
692 DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
693 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
694 lpPrefixString, uUnique, lpTempFileName);
695
696 if (lpPathName == NULL)
697 return 0;
698
699 len = wcslen(lpPathName);
700 if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
701 len--;
702
703 if (uUnique == 0)
704 uUnique = GetCurrentTime();
705
706 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
707
708 if (unique)
709 return uUnique;
710
711 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
712 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
713 0)) == INVALID_HANDLE_VALUE)
714 {
715 if (GetLastError() != ERROR_ALREADY_EXISTS)
716 {
717 return 0;
718 }
719 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
720 }
721 CloseHandle(hFile);
722 return uUnique;
723 }
724
725
726 WINBOOL STDCALL
727 GetFileTime(HANDLE hFile,
728 LPFILETIME lpCreationTime,
729 LPFILETIME lpLastAccessTime,
730 LPFILETIME lpLastWriteTime)
731 {
732 IO_STATUS_BLOCK IoStatusBlock;
733 FILE_BASIC_INFORMATION FileBasic;
734 NTSTATUS Status;
735
736 Status = NtQueryInformationFile(hFile,
737 &IoStatusBlock,
738 &FileBasic,
739 sizeof(FILE_BASIC_INFORMATION),
740 FileBasicInformation);
741 if (!NT_SUCCESS(Status))
742 {
743 SetLastErrorByStatus(Status);
744 return FALSE;
745 }
746
747 if (lpCreationTime)
748 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
749 if (lpLastAccessTime)
750 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
751 if (lpLastWriteTime)
752 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
753
754 return TRUE;
755 }
756
757
758 WINBOOL STDCALL
759 SetFileTime(HANDLE hFile,
760 CONST FILETIME *lpCreationTime,
761 CONST FILETIME *lpLastAccessTime,
762 CONST FILETIME *lpLastWriteTime)
763 {
764 FILE_BASIC_INFORMATION FileBasic;
765 IO_STATUS_BLOCK IoStatusBlock;
766 NTSTATUS Status;
767
768 Status = NtQueryInformationFile(hFile,
769 &IoStatusBlock,
770 &FileBasic,
771 sizeof(FILE_BASIC_INFORMATION),
772 FileBasicInformation);
773 if (!NT_SUCCESS(Status))
774 {
775 SetLastErrorByStatus(Status);
776 return FALSE;
777 }
778
779 if (lpCreationTime)
780 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
781 if (lpLastAccessTime)
782 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
783 if (lpLastWriteTime)
784 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
785
786 // should i initialize changetime ???
787
788 Status = NtSetInformationFile(hFile,
789 &IoStatusBlock,
790 &FileBasic,
791 sizeof(FILE_BASIC_INFORMATION),
792 FileBasicInformation);
793 if (!NT_SUCCESS(Status))
794 {
795 SetLastErrorByStatus(Status);
796 return FALSE;
797 }
798
799 return TRUE;
800 }
801
802
803 WINBOOL STDCALL
804 SetEndOfFile(HANDLE hFile)
805 {
806 int x = -1;
807 DWORD Num;
808 return WriteFile(hFile,&x,1,&Num,NULL);
809 }
810
811 /* EOF */