94d527b36ab0dcf42fbccc4ff9fa2b8d6017a636
[reactos.git] / reactos / lib / kernel32 / file / file.c
1 /* $Id: file.c,v 1.30 2002/04/01 22:06:51 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
640 if (lpPathName == NULL)
641 return 0;
642
643 if (uUnique == 0)
644 uUnique = GetCurrentTime();
645 /*
646 * sprintf(lpTempFileName,"%s\\%c%.3s%4.4x%s",
647 * lpPathName,'~',lpPrefixString,uUnique,".tmp");
648 */
649 if (unique)
650 return uUnique;
651
652 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
653 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
654 0)) == INVALID_HANDLE_VALUE)
655 {
656 // wsprintfA(lpTempFileName,"%s\\%c%.3s%4.4x%s",
657 // lpPathName,'~',lpPrefixString,++uUnique,".tmp");
658 }
659
660 CloseHandle((HANDLE)hFile);
661 return uUnique;
662 }
663
664
665 UINT STDCALL
666 GetTempFileNameW(LPCWSTR lpPathName,
667 LPCWSTR lpPrefixString,
668 UINT uUnique,
669 LPWSTR lpTempFileName)
670 {
671 HANDLE hFile;
672 UINT unique = uUnique;
673
674 if (lpPathName == NULL)
675 return 0;
676
677 if (uUnique == 0)
678 uUnique = GetCurrentTime();
679
680 // swprintf(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
681 // lpPathName,'~',lpPrefixString,uUnique,L".tmp");
682
683 if (unique)
684 return uUnique;
685
686 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
687 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
688 0)) == INVALID_HANDLE_VALUE)
689 {
690 // wsprintfW(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
691 // lpPathName,'~',lpPrefixString,++uUnique,L".tmp");
692 }
693
694 CloseHandle((HANDLE)hFile);
695 return uUnique;
696 }
697
698
699 WINBOOL STDCALL
700 GetFileTime(HANDLE hFile,
701 LPFILETIME lpCreationTime,
702 LPFILETIME lpLastAccessTime,
703 LPFILETIME lpLastWriteTime)
704 {
705 IO_STATUS_BLOCK IoStatusBlock;
706 FILE_BASIC_INFORMATION FileBasic;
707 NTSTATUS Status;
708
709 Status = NtQueryInformationFile(hFile,
710 &IoStatusBlock,
711 &FileBasic,
712 sizeof(FILE_BASIC_INFORMATION),
713 FileBasicInformation);
714 if (!NT_SUCCESS(Status))
715 {
716 SetLastErrorByStatus(Status);
717 return FALSE;
718 }
719
720 if (lpCreationTime)
721 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
722 if (lpLastAccessTime)
723 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
724 if (lpLastWriteTime)
725 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
726
727 return TRUE;
728 }
729
730
731 WINBOOL STDCALL
732 SetFileTime(HANDLE hFile,
733 CONST FILETIME *lpCreationTime,
734 CONST FILETIME *lpLastAccessTime,
735 CONST FILETIME *lpLastWriteTime)
736 {
737 FILE_BASIC_INFORMATION FileBasic;
738 IO_STATUS_BLOCK IoStatusBlock;
739 NTSTATUS Status;
740
741 Status = NtQueryInformationFile(hFile,
742 &IoStatusBlock,
743 &FileBasic,
744 sizeof(FILE_BASIC_INFORMATION),
745 FileBasicInformation);
746 if (!NT_SUCCESS(Status))
747 {
748 SetLastErrorByStatus(Status);
749 return FALSE;
750 }
751
752 if (lpCreationTime)
753 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
754 if (lpLastAccessTime)
755 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
756 if (lpLastWriteTime)
757 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
758
759 // should i initialize changetime ???
760
761 Status = NtSetInformationFile(hFile,
762 &IoStatusBlock,
763 &FileBasic,
764 sizeof(FILE_BASIC_INFORMATION),
765 FileBasicInformation);
766 if (!NT_SUCCESS(Status))
767 {
768 SetLastErrorByStatus(Status);
769 return FALSE;
770 }
771
772 return TRUE;
773 }
774
775
776 WINBOOL STDCALL
777 SetEndOfFile(HANDLE hFile)
778 {
779 int x = -1;
780 DWORD Num;
781 return WriteFile(hFile,&x,1,&Num,NULL);
782 }
783
784 /* EOF */