Made GetTempFileNameA/W workable.
[reactos.git] / reactos / lib / kernel32 / file / file.c
1 /* $Id: file.c,v 1.31 2002/04/27 19:15:00 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 errCode = NtFlushBuffersFile(hFile,
164 &IoStatusBlock);
165 if (!NT_SUCCESS(errCode))
166 {
167 SetLastErrorByStatus(errCode);
168 return(FALSE);
169 }
170 return(TRUE);
171 }
172
173
174 DWORD STDCALL
175 SetFilePointer(HANDLE hFile,
176 LONG lDistanceToMove,
177 PLONG lpDistanceToMoveHigh,
178 DWORD dwMoveMethod)
179 {
180 FILE_POSITION_INFORMATION FilePosition;
181 FILE_STANDARD_INFORMATION FileStandart;
182 NTSTATUS errCode;
183 IO_STATUS_BLOCK IoStatusBlock;
184 LARGE_INTEGER Distance;
185
186 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
187 hFile,lDistanceToMove,dwMoveMethod);
188
189 Distance.u.LowPart = lDistanceToMove;
190 if (lpDistanceToMoveHigh)
191 {
192 Distance.u.HighPart = *lpDistanceToMoveHigh;
193 }
194 else if (lDistanceToMove >= 0)
195 {
196 Distance.u.HighPart = 0;
197 }
198 else
199 {
200 Distance.u.HighPart = -1;
201 }
202
203 if (dwMoveMethod == FILE_CURRENT)
204 {
205 NtQueryInformationFile(hFile,
206 &IoStatusBlock,
207 &FilePosition,
208 sizeof(FILE_POSITION_INFORMATION),
209 FilePositionInformation);
210 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
211 }
212 else if (dwMoveMethod == FILE_END)
213 {
214 NtQueryInformationFile(hFile,
215 &IoStatusBlock,
216 &FileStandart,
217 sizeof(FILE_STANDARD_INFORMATION),
218 FileStandardInformation);
219 FilePosition.CurrentByteOffset.QuadPart =
220 FileStandart.EndOfFile.QuadPart + Distance.QuadPart;
221 }
222 else if ( dwMoveMethod == FILE_BEGIN )
223 {
224 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
225 }
226
227 errCode = NtSetInformationFile(hFile,
228 &IoStatusBlock,
229 &FilePosition,
230 sizeof(FILE_POSITION_INFORMATION),
231 FilePositionInformation);
232 if (!NT_SUCCESS(errCode))
233 {
234 SetLastErrorByStatus(errCode);
235 return -1;
236 }
237
238 if (lpDistanceToMoveHigh != NULL)
239 {
240 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
241 }
242 return FilePosition.CurrentByteOffset.u.LowPart;
243 }
244
245
246 DWORD STDCALL
247 GetFileType(HANDLE hFile)
248 {
249 FILE_FS_DEVICE_INFORMATION DeviceInfo;
250 IO_STATUS_BLOCK StatusBlock;
251 NTSTATUS Status;
252
253 /* get real handle */
254 switch ((ULONG)hFile)
255 {
256 case STD_INPUT_HANDLE:
257 hFile = NtCurrentPeb()->ProcessParameters->InputHandle;
258 break;
259
260 case STD_OUTPUT_HANDLE:
261 hFile = NtCurrentPeb()->ProcessParameters->OutputHandle;
262 break;
263
264 case STD_ERROR_HANDLE:
265 hFile = NtCurrentPeb()->ProcessParameters->ErrorHandle;
266 break;
267 }
268
269 /* check console handles */
270 if (((ULONG)hFile & 3) == 3)
271 {
272 // if (VerifyConsoleHandle(hFile))
273 return FILE_TYPE_CHAR;
274 }
275
276 Status = NtQueryVolumeInformationFile(hFile,
277 &StatusBlock,
278 &DeviceInfo,
279 sizeof(FILE_FS_DEVICE_INFORMATION),
280 FileFsDeviceInformation);
281 if (!NT_SUCCESS(Status))
282 {
283 SetLastErrorByStatus(Status);
284 return FILE_TYPE_UNKNOWN;
285 }
286
287 switch (DeviceInfo.DeviceType)
288 {
289 case FILE_DEVICE_CD_ROM:
290 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
291 case FILE_DEVICE_CONTROLLER:
292 case FILE_DEVICE_DATALINK:
293 case FILE_DEVICE_DFS:
294 case FILE_DEVICE_DISK:
295 case FILE_DEVICE_DISK_FILE_SYSTEM:
296 case FILE_DEVICE_VIRTUAL_DISK:
297 return FILE_TYPE_DISK;
298
299 case FILE_DEVICE_KEYBOARD:
300 case FILE_DEVICE_MOUSE:
301 case FILE_DEVICE_NULL:
302 case FILE_DEVICE_PARALLEL_PORT:
303 case FILE_DEVICE_PRINTER:
304 case FILE_DEVICE_SERIAL_PORT:
305 case FILE_DEVICE_SCREEN:
306 case FILE_DEVICE_SOUND:
307 case FILE_DEVICE_MODEM:
308 return FILE_TYPE_CHAR;
309
310 case FILE_DEVICE_NAMED_PIPE:
311 return FILE_TYPE_PIPE;
312 }
313
314 return FILE_TYPE_UNKNOWN;
315 }
316
317
318 DWORD STDCALL
319 GetFileSize(HANDLE hFile,
320 LPDWORD lpFileSizeHigh)
321 {
322 NTSTATUS errCode;
323 FILE_STANDARD_INFORMATION FileStandard;
324 IO_STATUS_BLOCK IoStatusBlock;
325
326 errCode = NtQueryInformationFile(hFile,
327 &IoStatusBlock,
328 &FileStandard,
329 sizeof(FILE_STANDARD_INFORMATION),
330 FileStandardInformation);
331 if (!NT_SUCCESS(errCode))
332 {
333 SetLastErrorByStatus(errCode);
334 if ( lpFileSizeHigh == NULL )
335 {
336 return -1;
337 }
338 else
339 {
340 return 0;
341 }
342 }
343 if ( lpFileSizeHigh != NULL )
344 *lpFileSizeHigh = FileStandard.AllocationSize.u.HighPart;
345
346 return FileStandard.AllocationSize.u.LowPart;
347 }
348
349
350 DWORD STDCALL
351 GetCompressedFileSizeA(LPCSTR lpFileName,
352 LPDWORD lpFileSizeHigh)
353 {
354 UNICODE_STRING FileNameU;
355 ANSI_STRING FileName;
356 DWORD Size;
357
358 RtlInitAnsiString(&FileName,
359 (LPSTR)lpFileName);
360
361 /* convert ansi (or oem) string to unicode */
362 if (bIsFileApiAnsi)
363 RtlAnsiStringToUnicodeString(&FileNameU,
364 &FileName,
365 TRUE);
366 else
367 RtlOemStringToUnicodeString(&FileNameU,
368 &FileName,
369 TRUE);
370
371 Size = GetCompressedFileSizeW(FileNameU.Buffer,
372 lpFileSizeHigh);
373
374 RtlFreeUnicodeString (&FileNameU);
375
376 return Size;
377 }
378
379
380 DWORD STDCALL
381 GetCompressedFileSizeW(LPCWSTR lpFileName,
382 LPDWORD lpFileSizeHigh)
383 {
384 FILE_COMPRESSION_INFORMATION FileCompression;
385 NTSTATUS errCode;
386 IO_STATUS_BLOCK IoStatusBlock;
387 HANDLE hFile;
388
389 hFile = CreateFileW(lpFileName,
390 GENERIC_READ,
391 FILE_SHARE_READ,
392 NULL,
393 OPEN_EXISTING,
394 FILE_ATTRIBUTE_NORMAL,
395 NULL);
396
397 errCode = NtQueryInformationFile(hFile,
398 &IoStatusBlock,
399 &FileCompression,
400 sizeof(FILE_COMPRESSION_INFORMATION),
401 FileCompressionInformation);
402 if (!NT_SUCCESS(errCode))
403 {
404 CloseHandle(hFile);
405 SetLastErrorByStatus(errCode);
406 return 0;
407 }
408 CloseHandle(hFile);
409 return 0;
410 }
411
412
413 WINBOOL STDCALL
414 GetFileInformationByHandle(HANDLE hFile,
415 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
416 {
417 struct
418 {
419 FILE_FS_VOLUME_INFORMATION FileFsVolume;
420 WCHAR Name[255];
421 }
422 FileFsVolume;
423
424 FILE_BASIC_INFORMATION FileBasic;
425 FILE_INTERNAL_INFORMATION FileInternal;
426 FILE_STANDARD_INFORMATION FileStandard;
427 NTSTATUS errCode;
428 IO_STATUS_BLOCK IoStatusBlock;
429
430 errCode = NtQueryInformationFile(hFile,
431 &IoStatusBlock,
432 &FileBasic,
433 sizeof(FILE_BASIC_INFORMATION),
434 FileBasicInformation);
435 if (!NT_SUCCESS(errCode))
436 {
437 SetLastErrorByStatus(errCode);
438 return FALSE;
439 }
440
441 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
442 memcpy(&lpFileInformation->ftCreationTime,&FileBasic.CreationTime,sizeof(LARGE_INTEGER));
443 memcpy(&lpFileInformation->ftLastAccessTime,&FileBasic.LastAccessTime,sizeof(LARGE_INTEGER));
444 memcpy(&lpFileInformation->ftLastWriteTime, &FileBasic.LastWriteTime,sizeof(LARGE_INTEGER));
445
446 errCode = NtQueryInformationFile(hFile,
447 &IoStatusBlock,
448 &FileInternal,
449 sizeof(FILE_INTERNAL_INFORMATION),
450 FileInternalInformation);
451 if (!NT_SUCCESS(errCode))
452 {
453 SetLastErrorByStatus(errCode);
454 return FALSE;
455 }
456
457 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
458 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
459
460 errCode = NtQueryVolumeInformationFile(hFile,
461 &IoStatusBlock,
462 &FileFsVolume,
463 sizeof(FileFsVolume),
464 FileFsVolumeInformation);
465 if (!NT_SUCCESS(errCode))
466 {
467 SetLastErrorByStatus(errCode);
468 return FALSE;
469 }
470
471 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
472
473 errCode = NtQueryInformationFile(hFile,
474 &IoStatusBlock,
475 &FileStandard,
476 sizeof(FILE_STANDARD_INFORMATION),
477 FileStandardInformation);
478 if (!NT_SUCCESS(errCode))
479 {
480 SetLastErrorByStatus(errCode);
481 return FALSE;
482 }
483
484 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
485 lpFileInformation->nFileSizeHigh = FileStandard.AllocationSize.u.HighPart;
486 lpFileInformation->nFileSizeLow = FileStandard.AllocationSize.u.LowPart;
487
488 return TRUE;
489 }
490
491
492 DWORD STDCALL
493 GetFileAttributesA(LPCSTR lpFileName)
494 {
495 UNICODE_STRING FileNameU;
496 ANSI_STRING FileName;
497 WINBOOL Result;
498
499 RtlInitAnsiString (&FileName,
500 (LPSTR)lpFileName);
501
502 /* convert ansi (or oem) string to unicode */
503 if (bIsFileApiAnsi)
504 RtlAnsiStringToUnicodeString (&FileNameU,
505 &FileName,
506 TRUE);
507 else
508 RtlOemStringToUnicodeString (&FileNameU,
509 &FileName,
510 TRUE);
511
512 Result = GetFileAttributesW (FileNameU.Buffer);
513
514 RtlFreeUnicodeString (&FileNameU);
515
516 return Result;
517 }
518
519
520 DWORD STDCALL
521 GetFileAttributesW(LPCWSTR lpFileName)
522 {
523 IO_STATUS_BLOCK IoStatusBlock;
524 FILE_BASIC_INFORMATION FileBasic;
525 HANDLE hFile;
526 NTSTATUS errCode;
527
528 hFile = CreateFileW(lpFileName,
529 FILE_READ_ATTRIBUTES,
530 FILE_SHARE_READ,
531 NULL,
532 OPEN_EXISTING,
533 FILE_ATTRIBUTE_NORMAL,
534 NULL);
535 if (hFile == INVALID_HANDLE_VALUE)
536 {
537 return 0xFFFFFFFF;
538 }
539
540 errCode = NtQueryInformationFile(hFile,
541 &IoStatusBlock,
542 &FileBasic,
543 sizeof(FILE_BASIC_INFORMATION),
544 FileBasicInformation);
545 if (!NT_SUCCESS(errCode))
546 {
547 CloseHandle(hFile);
548 SetLastErrorByStatus(errCode);
549 return 0xFFFFFFFF;
550 }
551 CloseHandle(hFile);
552 return (DWORD)FileBasic.FileAttributes;
553 }
554
555
556 WINBOOL STDCALL
557 SetFileAttributesA(LPCSTR lpFileName,
558 DWORD dwFileAttributes)
559 {
560 UNICODE_STRING FileNameU;
561 ANSI_STRING FileName;
562 WINBOOL Result;
563
564 RtlInitAnsiString(&FileName,
565 (LPSTR)lpFileName);
566
567 /* convert ansi (or oem) string to unicode */
568 if (bIsFileApiAnsi)
569 RtlAnsiStringToUnicodeString(&FileNameU,
570 &FileName,
571 TRUE);
572 else
573 RtlOemStringToUnicodeString(&FileNameU,
574 &FileName,
575 TRUE);
576
577 Result = SetFileAttributesW(FileNameU.Buffer,
578 dwFileAttributes);
579
580 RtlFreeUnicodeString(&FileNameU);
581
582 return Result;
583 }
584
585
586 WINBOOL STDCALL
587 SetFileAttributesW(LPCWSTR lpFileName,
588 DWORD dwFileAttributes)
589 {
590 IO_STATUS_BLOCK IoStatusBlock;
591 FILE_BASIC_INFORMATION FileBasic;
592 HANDLE hFile;
593 NTSTATUS errCode;
594
595 hFile = CreateFileW(lpFileName,
596 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
597 FILE_SHARE_READ,
598 NULL,
599 OPEN_EXISTING,
600 FILE_ATTRIBUTE_NORMAL,
601 NULL);
602
603 errCode = NtQueryInformationFile(hFile,
604 &IoStatusBlock,
605 &FileBasic,
606 sizeof(FILE_BASIC_INFORMATION),
607 FileBasicInformation);
608 if (!NT_SUCCESS(errCode))
609 {
610 CloseHandle(hFile);
611 SetLastErrorByStatus(errCode);
612 return FALSE;
613 }
614 FileBasic.FileAttributes = dwFileAttributes;
615 errCode = NtSetInformationFile(hFile,
616 &IoStatusBlock,
617 &FileBasic,
618 sizeof(FILE_BASIC_INFORMATION),
619 FileBasicInformation);
620 if (!NT_SUCCESS(errCode))
621 {
622 CloseHandle(hFile);
623 SetLastErrorByStatus(errCode);
624 return FALSE;
625 }
626 CloseHandle(hFile);
627 return TRUE;
628 }
629
630
631 UINT STDCALL
632 GetTempFileNameA(LPCSTR lpPathName,
633 LPCSTR lpPrefixString,
634 UINT uUnique,
635 LPSTR lpTempFileName)
636 {
637 HANDLE hFile;
638 UINT unique = uUnique;
639 UINT len;
640 const char *format = "%.*s\\~%.3s%4.4x.TMP";
641
642 DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
643 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
644 lpPrefixString, uUnique, lpTempFileName);
645
646 if (lpPathName == NULL)
647 return 0;
648
649 len = strlen(lpPathName);
650 if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
651 len--;
652
653 if (uUnique == 0)
654 uUnique = GetCurrentTime();
655
656 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
657
658 if (unique)
659 return uUnique;
660
661 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
662 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
663 0)) == INVALID_HANDLE_VALUE)
664 {
665 if (GetLastError() != ERROR_ALREADY_EXISTS)
666 {
667 return 0;
668 }
669 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
670 }
671 CloseHandle(hFile);
672 return uUnique;
673 }
674
675
676 UINT STDCALL
677 GetTempFileNameW(LPCWSTR lpPathName,
678 LPCWSTR lpPrefixString,
679 UINT uUnique,
680 LPWSTR lpTempFileName)
681 {
682 HANDLE hFile;
683 UINT unique = uUnique;
684 UINT len;
685 const WCHAR *format = L"%.*S\\~%.3S%4.4x.TMP";
686
687 DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
688 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
689 lpPrefixString, uUnique, lpTempFileName);
690
691 if (lpPathName == NULL)
692 return 0;
693
694 len = wcslen(lpPathName);
695 if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
696 len--;
697
698 if (uUnique == 0)
699 uUnique = GetCurrentTime();
700
701 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
702
703 if (unique)
704 return uUnique;
705
706 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
707 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
708 0)) == INVALID_HANDLE_VALUE)
709 {
710 if (GetLastError() != ERROR_ALREADY_EXISTS)
711 {
712 return 0;
713 }
714 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
715 }
716 CloseHandle(hFile);
717 return uUnique;
718 }
719
720
721 WINBOOL STDCALL
722 GetFileTime(HANDLE hFile,
723 LPFILETIME lpCreationTime,
724 LPFILETIME lpLastAccessTime,
725 LPFILETIME lpLastWriteTime)
726 {
727 IO_STATUS_BLOCK IoStatusBlock;
728 FILE_BASIC_INFORMATION FileBasic;
729 NTSTATUS Status;
730
731 Status = NtQueryInformationFile(hFile,
732 &IoStatusBlock,
733 &FileBasic,
734 sizeof(FILE_BASIC_INFORMATION),
735 FileBasicInformation);
736 if (!NT_SUCCESS(Status))
737 {
738 SetLastErrorByStatus(Status);
739 return FALSE;
740 }
741
742 if (lpCreationTime)
743 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
744 if (lpLastAccessTime)
745 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
746 if (lpLastWriteTime)
747 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
748
749 return TRUE;
750 }
751
752
753 WINBOOL STDCALL
754 SetFileTime(HANDLE hFile,
755 CONST FILETIME *lpCreationTime,
756 CONST FILETIME *lpLastAccessTime,
757 CONST FILETIME *lpLastWriteTime)
758 {
759 FILE_BASIC_INFORMATION FileBasic;
760 IO_STATUS_BLOCK IoStatusBlock;
761 NTSTATUS Status;
762
763 Status = NtQueryInformationFile(hFile,
764 &IoStatusBlock,
765 &FileBasic,
766 sizeof(FILE_BASIC_INFORMATION),
767 FileBasicInformation);
768 if (!NT_SUCCESS(Status))
769 {
770 SetLastErrorByStatus(Status);
771 return FALSE;
772 }
773
774 if (lpCreationTime)
775 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
776 if (lpLastAccessTime)
777 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
778 if (lpLastWriteTime)
779 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
780
781 // should i initialize changetime ???
782
783 Status = NtSetInformationFile(hFile,
784 &IoStatusBlock,
785 &FileBasic,
786 sizeof(FILE_BASIC_INFORMATION),
787 FileBasicInformation);
788 if (!NT_SUCCESS(Status))
789 {
790 SetLastErrorByStatus(Status);
791 return FALSE;
792 }
793
794 return TRUE;
795 }
796
797
798 WINBOOL STDCALL
799 SetEndOfFile(HANDLE hFile)
800 {
801 int x = -1;
802 DWORD Num;
803 return WriteFile(hFile,&x,1,&Num,NULL);
804 }
805
806 /* EOF */