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