Fixed negativ positions in SetFilePointer().
[reactos.git] / reactos / lib / kernel32 / file / file.c
1 /* $Id: file.c,v 1.29 2002/03/25 21:07:17 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 if (lpReOpenBuff == NULL)
72 {
73 return FALSE;
74 }
75
76 RtlInitAnsiString (&FileName,
77 (LPSTR)lpFileName);
78
79 /* convert ansi (or oem) string to unicode */
80 if (bIsFileApiAnsi)
81 RtlAnsiStringToUnicodeString (&FileNameU,
82 &FileName,
83 TRUE);
84 else
85 RtlOemStringToUnicodeString (&FileNameU,
86 &FileName,
87 TRUE);
88
89 Len = SearchPathW (NULL,
90 FileNameU.Buffer,
91 NULL,
92 MAX_PATH,
93 PathNameW,
94 &FilePart);
95
96 RtlFreeHeap (RtlGetProcessHeap (),
97 0,
98 FileNameU.Buffer);
99
100 if (Len == 0)
101 return (HFILE)NULL;
102
103 if (Len > MAX_PATH)
104 return (HFILE)NULL;
105
106 FileNameString.Length = lstrlenW(PathNameW) * sizeof(WCHAR);
107 FileNameString.Buffer = PathNameW;
108 FileNameString.MaximumLength = FileNameString.Length + sizeof(WCHAR);
109
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;
116
117 // FILE_SHARE_READ
118 // FILE_NO_INTERMEDIATE_BUFFERING
119
120 if ((uStyle & OF_PARSE) == OF_PARSE)
121 return (HFILE)NULL;
122
123 errCode = NtOpenFile (&FileHandle,
124 GENERIC_READ|SYNCHRONIZE,
125 &ObjectAttributes,
126 &IoStatusBlock,
127 FILE_SHARE_READ,
128 FILE_NON_DIRECTORY_FILE);
129
130 lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
131
132 if (!NT_SUCCESS(errCode))
133 {
134 SetLastErrorByStatus (errCode);
135 return (HFILE)INVALID_HANDLE_VALUE;
136 }
137
138 return (HFILE)FileHandle;
139 }
140
141
142 WINBOOL STDCALL
143 FlushFileBuffers(HANDLE hFile)
144 {
145 NTSTATUS errCode;
146 IO_STATUS_BLOCK IoStatusBlock;
147
148 errCode = NtFlushBuffersFile(hFile,
149 &IoStatusBlock);
150 if (!NT_SUCCESS(errCode))
151 {
152 SetLastErrorByStatus(errCode);
153 return(FALSE);
154 }
155 return(TRUE);
156 }
157
158
159 DWORD STDCALL
160 SetFilePointer(HANDLE hFile,
161 LONG lDistanceToMove,
162 PLONG lpDistanceToMoveHigh,
163 DWORD dwMoveMethod)
164 {
165 FILE_POSITION_INFORMATION FilePosition;
166 FILE_STANDARD_INFORMATION FileStandart;
167 NTSTATUS errCode;
168 IO_STATUS_BLOCK IoStatusBlock;
169 LARGE_INTEGER Distance;
170
171 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
172 hFile,lDistanceToMove,dwMoveMethod);
173
174 Distance.u.LowPart = lDistanceToMove;
175 if (lpDistanceToMoveHigh)
176 {
177 Distance.u.HighPart = *lpDistanceToMoveHigh;
178 }
179 else if (lDistanceToMove >= 0)
180 {
181 Distance.u.HighPart = 0;
182 }
183 else
184 {
185 Distance.u.HighPart = -1;
186 }
187
188 if (dwMoveMethod == FILE_CURRENT)
189 {
190 NtQueryInformationFile(hFile,
191 &IoStatusBlock,
192 &FilePosition,
193 sizeof(FILE_POSITION_INFORMATION),
194 FilePositionInformation);
195 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
196 }
197 else if (dwMoveMethod == FILE_END)
198 {
199 NtQueryInformationFile(hFile,
200 &IoStatusBlock,
201 &FileStandart,
202 sizeof(FILE_STANDARD_INFORMATION),
203 FileStandardInformation);
204 FilePosition.CurrentByteOffset.QuadPart =
205 FileStandart.EndOfFile.QuadPart + Distance.QuadPart;
206 }
207 else if ( dwMoveMethod == FILE_BEGIN )
208 {
209 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
210 }
211
212 errCode = NtSetInformationFile(hFile,
213 &IoStatusBlock,
214 &FilePosition,
215 sizeof(FILE_POSITION_INFORMATION),
216 FilePositionInformation);
217 if (!NT_SUCCESS(errCode))
218 {
219 SetLastErrorByStatus(errCode);
220 return -1;
221 }
222
223 if (lpDistanceToMoveHigh != NULL)
224 {
225 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
226 }
227 return FilePosition.CurrentByteOffset.u.LowPart;
228 }
229
230
231 DWORD STDCALL
232 GetFileType(HANDLE hFile)
233 {
234 FILE_FS_DEVICE_INFORMATION DeviceInfo;
235 IO_STATUS_BLOCK StatusBlock;
236 NTSTATUS Status;
237
238 /* get real handle */
239 switch ((ULONG)hFile)
240 {
241 case STD_INPUT_HANDLE:
242 hFile = NtCurrentPeb()->ProcessParameters->InputHandle;
243 break;
244
245 case STD_OUTPUT_HANDLE:
246 hFile = NtCurrentPeb()->ProcessParameters->OutputHandle;
247 break;
248
249 case STD_ERROR_HANDLE:
250 hFile = NtCurrentPeb()->ProcessParameters->ErrorHandle;
251 break;
252 }
253
254 /* check console handles */
255 if (((ULONG)hFile & 3) == 3)
256 {
257 // if (VerifyConsoleHandle(hFile))
258 return FILE_TYPE_CHAR;
259 }
260
261 Status = NtQueryVolumeInformationFile(hFile,
262 &StatusBlock,
263 &DeviceInfo,
264 sizeof(FILE_FS_DEVICE_INFORMATION),
265 FileFsDeviceInformation);
266 if (!NT_SUCCESS(Status))
267 {
268 SetLastErrorByStatus(Status);
269 return FILE_TYPE_UNKNOWN;
270 }
271
272 switch (DeviceInfo.DeviceType)
273 {
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;
283
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;
294
295 case FILE_DEVICE_NAMED_PIPE:
296 return FILE_TYPE_PIPE;
297 }
298
299 return FILE_TYPE_UNKNOWN;
300 }
301
302
303 DWORD STDCALL
304 GetFileSize(HANDLE hFile,
305 LPDWORD lpFileSizeHigh)
306 {
307 NTSTATUS errCode;
308 FILE_STANDARD_INFORMATION FileStandard;
309 IO_STATUS_BLOCK IoStatusBlock;
310
311 errCode = NtQueryInformationFile(hFile,
312 &IoStatusBlock,
313 &FileStandard,
314 sizeof(FILE_STANDARD_INFORMATION),
315 FileStandardInformation);
316 if (!NT_SUCCESS(errCode))
317 {
318 SetLastErrorByStatus(errCode);
319 if ( lpFileSizeHigh == NULL )
320 {
321 return -1;
322 }
323 else
324 {
325 return 0;
326 }
327 }
328 if ( lpFileSizeHigh != NULL )
329 *lpFileSizeHigh = FileStandard.AllocationSize.u.HighPart;
330
331 return FileStandard.AllocationSize.u.LowPart;
332 }
333
334
335 DWORD STDCALL
336 GetCompressedFileSizeA(LPCSTR lpFileName,
337 LPDWORD lpFileSizeHigh)
338 {
339 UNICODE_STRING FileNameU;
340 ANSI_STRING FileName;
341 DWORD Size;
342
343 RtlInitAnsiString(&FileName,
344 (LPSTR)lpFileName);
345
346 /* convert ansi (or oem) string to unicode */
347 if (bIsFileApiAnsi)
348 RtlAnsiStringToUnicodeString(&FileNameU,
349 &FileName,
350 TRUE);
351 else
352 RtlOemStringToUnicodeString(&FileNameU,
353 &FileName,
354 TRUE);
355
356 Size = GetCompressedFileSizeW(FileNameU.Buffer,
357 lpFileSizeHigh);
358
359 RtlFreeUnicodeString (&FileNameU);
360
361 return Size;
362 }
363
364
365 DWORD STDCALL
366 GetCompressedFileSizeW(LPCWSTR lpFileName,
367 LPDWORD lpFileSizeHigh)
368 {
369 FILE_COMPRESSION_INFORMATION FileCompression;
370 NTSTATUS errCode;
371 IO_STATUS_BLOCK IoStatusBlock;
372 HANDLE hFile;
373
374 hFile = CreateFileW(lpFileName,
375 GENERIC_READ,
376 FILE_SHARE_READ,
377 NULL,
378 OPEN_EXISTING,
379 FILE_ATTRIBUTE_NORMAL,
380 NULL);
381
382 errCode = NtQueryInformationFile(hFile,
383 &IoStatusBlock,
384 &FileCompression,
385 sizeof(FILE_COMPRESSION_INFORMATION),
386 FileCompressionInformation);
387 if (!NT_SUCCESS(errCode))
388 {
389 CloseHandle(hFile);
390 SetLastErrorByStatus(errCode);
391 return 0;
392 }
393 CloseHandle(hFile);
394 return 0;
395 }
396
397
398 WINBOOL STDCALL
399 GetFileInformationByHandle(HANDLE hFile,
400 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
401 {
402 struct
403 {
404 FILE_FS_VOLUME_INFORMATION FileFsVolume;
405 WCHAR Name[255];
406 }
407 FileFsVolume;
408
409 FILE_BASIC_INFORMATION FileBasic;
410 FILE_INTERNAL_INFORMATION FileInternal;
411 FILE_STANDARD_INFORMATION FileStandard;
412 NTSTATUS errCode;
413 IO_STATUS_BLOCK IoStatusBlock;
414
415 errCode = NtQueryInformationFile(hFile,
416 &IoStatusBlock,
417 &FileBasic,
418 sizeof(FILE_BASIC_INFORMATION),
419 FileBasicInformation);
420 if (!NT_SUCCESS(errCode))
421 {
422 SetLastErrorByStatus(errCode);
423 return FALSE;
424 }
425
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));
430
431 errCode = NtQueryInformationFile(hFile,
432 &IoStatusBlock,
433 &FileInternal,
434 sizeof(FILE_INTERNAL_INFORMATION),
435 FileInternalInformation);
436 if (!NT_SUCCESS(errCode))
437 {
438 SetLastErrorByStatus(errCode);
439 return FALSE;
440 }
441
442 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
443 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
444
445 errCode = NtQueryVolumeInformationFile(hFile,
446 &IoStatusBlock,
447 &FileFsVolume,
448 sizeof(FileFsVolume),
449 FileFsVolumeInformation);
450 if (!NT_SUCCESS(errCode))
451 {
452 SetLastErrorByStatus(errCode);
453 return FALSE;
454 }
455
456 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
457
458 errCode = NtQueryInformationFile(hFile,
459 &IoStatusBlock,
460 &FileStandard,
461 sizeof(FILE_STANDARD_INFORMATION),
462 FileStandardInformation);
463 if (!NT_SUCCESS(errCode))
464 {
465 SetLastErrorByStatus(errCode);
466 return FALSE;
467 }
468
469 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
470 lpFileInformation->nFileSizeHigh = FileStandard.AllocationSize.u.HighPart;
471 lpFileInformation->nFileSizeLow = FileStandard.AllocationSize.u.LowPart;
472
473 return TRUE;
474 }
475
476
477 DWORD STDCALL
478 GetFileAttributesA(LPCSTR lpFileName)
479 {
480 UNICODE_STRING FileNameU;
481 ANSI_STRING FileName;
482 WINBOOL Result;
483
484 RtlInitAnsiString (&FileName,
485 (LPSTR)lpFileName);
486
487 /* convert ansi (or oem) string to unicode */
488 if (bIsFileApiAnsi)
489 RtlAnsiStringToUnicodeString (&FileNameU,
490 &FileName,
491 TRUE);
492 else
493 RtlOemStringToUnicodeString (&FileNameU,
494 &FileName,
495 TRUE);
496
497 Result = GetFileAttributesW (FileNameU.Buffer);
498
499 RtlFreeUnicodeString (&FileNameU);
500
501 return Result;
502 }
503
504
505 DWORD STDCALL
506 GetFileAttributesW(LPCWSTR lpFileName)
507 {
508 IO_STATUS_BLOCK IoStatusBlock;
509 FILE_BASIC_INFORMATION FileBasic;
510 HANDLE hFile;
511 NTSTATUS errCode;
512
513 hFile = CreateFileW(lpFileName,
514 FILE_READ_ATTRIBUTES,
515 FILE_SHARE_READ,
516 NULL,
517 OPEN_EXISTING,
518 FILE_ATTRIBUTE_NORMAL,
519 NULL);
520 if (hFile == INVALID_HANDLE_VALUE)
521 {
522 return 0xFFFFFFFF;
523 }
524
525 errCode = NtQueryInformationFile(hFile,
526 &IoStatusBlock,
527 &FileBasic,
528 sizeof(FILE_BASIC_INFORMATION),
529 FileBasicInformation);
530 if (!NT_SUCCESS(errCode))
531 {
532 CloseHandle(hFile);
533 SetLastErrorByStatus(errCode);
534 return 0xFFFFFFFF;
535 }
536 CloseHandle(hFile);
537 return (DWORD)FileBasic.FileAttributes;
538 }
539
540
541 WINBOOL STDCALL
542 SetFileAttributesA(LPCSTR lpFileName,
543 DWORD dwFileAttributes)
544 {
545 UNICODE_STRING FileNameU;
546 ANSI_STRING FileName;
547 WINBOOL Result;
548
549 RtlInitAnsiString(&FileName,
550 (LPSTR)lpFileName);
551
552 /* convert ansi (or oem) string to unicode */
553 if (bIsFileApiAnsi)
554 RtlAnsiStringToUnicodeString(&FileNameU,
555 &FileName,
556 TRUE);
557 else
558 RtlOemStringToUnicodeString(&FileNameU,
559 &FileName,
560 TRUE);
561
562 Result = SetFileAttributesW(FileNameU.Buffer,
563 dwFileAttributes);
564
565 RtlFreeUnicodeString(&FileNameU);
566
567 return Result;
568 }
569
570
571 WINBOOL STDCALL
572 SetFileAttributesW(LPCWSTR lpFileName,
573 DWORD dwFileAttributes)
574 {
575 IO_STATUS_BLOCK IoStatusBlock;
576 FILE_BASIC_INFORMATION FileBasic;
577 HANDLE hFile;
578 NTSTATUS errCode;
579
580 hFile = CreateFileW(lpFileName,
581 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
582 FILE_SHARE_READ,
583 NULL,
584 OPEN_EXISTING,
585 FILE_ATTRIBUTE_NORMAL,
586 NULL);
587
588 errCode = NtQueryInformationFile(hFile,
589 &IoStatusBlock,
590 &FileBasic,
591 sizeof(FILE_BASIC_INFORMATION),
592 FileBasicInformation);
593 if (!NT_SUCCESS(errCode))
594 {
595 CloseHandle(hFile);
596 SetLastErrorByStatus(errCode);
597 return FALSE;
598 }
599 FileBasic.FileAttributes = dwFileAttributes;
600 errCode = NtSetInformationFile(hFile,
601 &IoStatusBlock,
602 &FileBasic,
603 sizeof(FILE_BASIC_INFORMATION),
604 FileBasicInformation);
605 if (!NT_SUCCESS(errCode))
606 {
607 CloseHandle(hFile);
608 SetLastErrorByStatus(errCode);
609 return FALSE;
610 }
611 CloseHandle(hFile);
612 return TRUE;
613 }
614
615
616 UINT STDCALL
617 GetTempFileNameA(LPCSTR lpPathName,
618 LPCSTR lpPrefixString,
619 UINT uUnique,
620 LPSTR lpTempFileName)
621 {
622 HANDLE hFile;
623 UINT unique = uUnique;
624
625 if (lpPathName == NULL)
626 return 0;
627
628 if (uUnique == 0)
629 uUnique = GetCurrentTime();
630 /*
631 * sprintf(lpTempFileName,"%s\\%c%.3s%4.4x%s",
632 * lpPathName,'~',lpPrefixString,uUnique,".tmp");
633 */
634 if (unique)
635 return uUnique;
636
637 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
638 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
639 0)) == INVALID_HANDLE_VALUE)
640 {
641 // wsprintfA(lpTempFileName,"%s\\%c%.3s%4.4x%s",
642 // lpPathName,'~',lpPrefixString,++uUnique,".tmp");
643 }
644
645 CloseHandle((HANDLE)hFile);
646 return uUnique;
647 }
648
649
650 UINT STDCALL
651 GetTempFileNameW(LPCWSTR lpPathName,
652 LPCWSTR lpPrefixString,
653 UINT uUnique,
654 LPWSTR lpTempFileName)
655 {
656 HANDLE hFile;
657 UINT unique = uUnique;
658
659 if (lpPathName == NULL)
660 return 0;
661
662 if (uUnique == 0)
663 uUnique = GetCurrentTime();
664
665 // swprintf(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
666 // lpPathName,'~',lpPrefixString,uUnique,L".tmp");
667
668 if (unique)
669 return uUnique;
670
671 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
672 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
673 0)) == INVALID_HANDLE_VALUE)
674 {
675 // wsprintfW(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
676 // lpPathName,'~',lpPrefixString,++uUnique,L".tmp");
677 }
678
679 CloseHandle((HANDLE)hFile);
680 return uUnique;
681 }
682
683
684 WINBOOL STDCALL
685 GetFileTime(HANDLE hFile,
686 LPFILETIME lpCreationTime,
687 LPFILETIME lpLastAccessTime,
688 LPFILETIME lpLastWriteTime)
689 {
690 IO_STATUS_BLOCK IoStatusBlock;
691 FILE_BASIC_INFORMATION FileBasic;
692 NTSTATUS Status;
693
694 Status = NtQueryInformationFile(hFile,
695 &IoStatusBlock,
696 &FileBasic,
697 sizeof(FILE_BASIC_INFORMATION),
698 FileBasicInformation);
699 if (!NT_SUCCESS(Status))
700 {
701 SetLastErrorByStatus(Status);
702 return FALSE;
703 }
704
705 if (lpCreationTime)
706 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
707 if (lpLastAccessTime)
708 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
709 if (lpLastWriteTime)
710 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
711
712 return TRUE;
713 }
714
715
716 WINBOOL STDCALL
717 SetFileTime(HANDLE hFile,
718 CONST FILETIME *lpCreationTime,
719 CONST FILETIME *lpLastAccessTime,
720 CONST FILETIME *lpLastWriteTime)
721 {
722 FILE_BASIC_INFORMATION FileBasic;
723 IO_STATUS_BLOCK IoStatusBlock;
724 NTSTATUS Status;
725
726 Status = NtQueryInformationFile(hFile,
727 &IoStatusBlock,
728 &FileBasic,
729 sizeof(FILE_BASIC_INFORMATION),
730 FileBasicInformation);
731 if (!NT_SUCCESS(Status))
732 {
733 SetLastErrorByStatus(Status);
734 return FALSE;
735 }
736
737 if (lpCreationTime)
738 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
739 if (lpLastAccessTime)
740 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
741 if (lpLastWriteTime)
742 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
743
744 // should i initialize changetime ???
745
746 Status = NtSetInformationFile(hFile,
747 &IoStatusBlock,
748 &FileBasic,
749 sizeof(FILE_BASIC_INFORMATION),
750 FileBasicInformation);
751 if (!NT_SUCCESS(Status))
752 {
753 SetLastErrorByStatus(Status);
754 return FALSE;
755 }
756
757 return TRUE;
758 }
759
760
761 WINBOOL STDCALL
762 SetEndOfFile(HANDLE hFile)
763 {
764 int x = -1;
765 DWORD Num;
766 return WriteFile(hFile,&x,1,&Num,NULL);
767 }
768
769 /* EOF */