update for HEAD-2002110701
[reactos.git] / lib / kernel32 / file / file.c
1 /* $Id$
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->hStdInput;
263
264           break;
265
266         case STD_OUTPUT_HANDLE:
267           hFile = NtCurrentPeb()->ProcessParameters->hStdOutput;
268
269           break;
270
271         case STD_ERROR_HANDLE:
272           hFile = NtCurrentPeb()->ProcessParameters->hStdError;
273
274           break;
275      }
276
277    /* check console handles */
278    if (IsConsoleHandle(hFile))
279      {
280 //      if (VerifyConsoleHandle(hFile))
281           return FILE_TYPE_CHAR;
282      }
283
284    Status = NtQueryVolumeInformationFile(hFile,
285                                          &StatusBlock,
286                                          &DeviceInfo,
287                                          sizeof(FILE_FS_DEVICE_INFORMATION),
288                                          FileFsDeviceInformation);
289    if (!NT_SUCCESS(Status))
290      {
291         SetLastErrorByStatus(Status);
292         return FILE_TYPE_UNKNOWN;
293      }
294
295    switch (DeviceInfo.DeviceType)
296      {
297         case FILE_DEVICE_CD_ROM:
298         case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
299         case FILE_DEVICE_CONTROLLER:
300         case FILE_DEVICE_DATALINK:
301         case FILE_DEVICE_DFS:
302         case FILE_DEVICE_DISK:
303         case FILE_DEVICE_DISK_FILE_SYSTEM:
304         case FILE_DEVICE_VIRTUAL_DISK:
305           return FILE_TYPE_DISK;
306
307         case FILE_DEVICE_KEYBOARD:
308         case FILE_DEVICE_MOUSE:
309         case FILE_DEVICE_NULL:
310         case FILE_DEVICE_PARALLEL_PORT:
311         case FILE_DEVICE_PRINTER:
312         case FILE_DEVICE_SERIAL_PORT:
313         case FILE_DEVICE_SCREEN:
314         case FILE_DEVICE_SOUND:
315         case FILE_DEVICE_MODEM:
316           return FILE_TYPE_CHAR;
317
318         case FILE_DEVICE_NAMED_PIPE:
319           return FILE_TYPE_PIPE;
320      }
321
322    return FILE_TYPE_UNKNOWN;
323 }
324
325
326 DWORD STDCALL
327 GetFileSize(HANDLE hFile,
328             LPDWORD lpFileSizeHigh)
329 {
330    NTSTATUS errCode;
331    FILE_STANDARD_INFORMATION FileStandard;
332    IO_STATUS_BLOCK IoStatusBlock;
333
334    errCode = NtQueryInformationFile(hFile,
335                                     &IoStatusBlock,
336                                     &FileStandard,
337                                     sizeof(FILE_STANDARD_INFORMATION),
338                                     FileStandardInformation);
339    if (!NT_SUCCESS(errCode))
340      {
341         SetLastErrorByStatus(errCode);
342         if ( lpFileSizeHigh == NULL )
343           {
344              return -1;
345           }
346         else
347           {
348              return 0;
349           }
350      }
351    if ( lpFileSizeHigh != NULL )
352      *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
353
354    return FileStandard.EndOfFile.u.LowPart;
355 }
356
357
358 DWORD STDCALL
359 GetCompressedFileSizeA(LPCSTR lpFileName,
360                        LPDWORD lpFileSizeHigh)
361 {
362    UNICODE_STRING FileNameU;
363    ANSI_STRING FileName;
364    DWORD Size;
365
366    RtlInitAnsiString(&FileName,
367                      (LPSTR)lpFileName);
368
369    /* convert ansi (or oem) string to unicode */
370    if (bIsFileApiAnsi)
371      RtlAnsiStringToUnicodeString(&FileNameU,
372                                   &FileName,
373                                   TRUE);
374    else
375      RtlOemStringToUnicodeString(&FileNameU,
376                                  &FileName,
377                                  TRUE);
378
379    Size = GetCompressedFileSizeW(FileNameU.Buffer,
380                                  lpFileSizeHigh);
381
382    RtlFreeUnicodeString (&FileNameU);
383
384    return Size;
385 }
386
387
388 DWORD STDCALL
389 GetCompressedFileSizeW(LPCWSTR lpFileName,
390                        LPDWORD lpFileSizeHigh)
391 {
392    FILE_COMPRESSION_INFORMATION FileCompression;
393    NTSTATUS errCode;
394    IO_STATUS_BLOCK IoStatusBlock;
395    HANDLE hFile;
396    
397    hFile = CreateFileW(lpFileName,
398                        GENERIC_READ,
399                        FILE_SHARE_READ,
400                        NULL,
401                        OPEN_EXISTING,
402                        FILE_ATTRIBUTE_NORMAL,
403                        NULL);
404
405    errCode = NtQueryInformationFile(hFile,
406                                     &IoStatusBlock,
407                                     &FileCompression,
408                                     sizeof(FILE_COMPRESSION_INFORMATION),
409                                     FileCompressionInformation);
410    if (!NT_SUCCESS(errCode))
411      {
412         CloseHandle(hFile);
413         SetLastErrorByStatus(errCode);
414         return 0;
415      }
416    CloseHandle(hFile);
417    return 0;
418 }
419
420
421 WINBOOL STDCALL
422 GetFileInformationByHandle(HANDLE hFile,
423                            LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
424 {
425    struct
426    {
427         FILE_FS_VOLUME_INFORMATION FileFsVolume;
428         WCHAR Name[255];
429    }
430    FileFsVolume;
431
432    FILE_BASIC_INFORMATION FileBasic;
433    FILE_INTERNAL_INFORMATION FileInternal;
434    FILE_STANDARD_INFORMATION FileStandard;
435    NTSTATUS errCode;
436    IO_STATUS_BLOCK IoStatusBlock;
437
438    errCode = NtQueryInformationFile(hFile,
439                                     &IoStatusBlock,
440                                     &FileBasic,
441                                     sizeof(FILE_BASIC_INFORMATION),
442                                     FileBasicInformation);
443    if (!NT_SUCCESS(errCode))
444      {
445         SetLastErrorByStatus(errCode);
446         return FALSE;
447      }
448
449    lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
450    memcpy(&lpFileInformation->ftCreationTime,&FileBasic.CreationTime,sizeof(LARGE_INTEGER));
451    memcpy(&lpFileInformation->ftLastAccessTime,&FileBasic.LastAccessTime,sizeof(LARGE_INTEGER));
452    memcpy(&lpFileInformation->ftLastWriteTime, &FileBasic.LastWriteTime,sizeof(LARGE_INTEGER));
453
454    errCode = NtQueryInformationFile(hFile,
455                                     &IoStatusBlock,
456                                     &FileInternal,
457                                     sizeof(FILE_INTERNAL_INFORMATION),
458                                     FileInternalInformation);
459    if (!NT_SUCCESS(errCode))
460      {
461         SetLastErrorByStatus(errCode);
462         return FALSE;
463      }
464
465    lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
466    lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
467
468    errCode = NtQueryVolumeInformationFile(hFile,
469                                           &IoStatusBlock,
470                                           &FileFsVolume,
471                                           sizeof(FileFsVolume),
472                                           FileFsVolumeInformation);
473    if (!NT_SUCCESS(errCode))
474      {
475         SetLastErrorByStatus(errCode);
476         return FALSE;
477      }
478
479    lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
480
481    errCode = NtQueryInformationFile(hFile,
482                                     &IoStatusBlock,
483                                     &FileStandard,
484                                     sizeof(FILE_STANDARD_INFORMATION),
485                                     FileStandardInformation);
486    if (!NT_SUCCESS(errCode))
487      {
488         SetLastErrorByStatus(errCode);
489         return FALSE;
490      }
491
492    lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
493    lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
494    lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
495
496    return TRUE;
497 }
498
499
500 DWORD STDCALL
501 GetFileAttributesA(LPCSTR lpFileName)
502 {
503         UNICODE_STRING FileNameU;
504         ANSI_STRING FileName;
505         WINBOOL Result;
506
507         RtlInitAnsiString (&FileName,
508                            (LPSTR)lpFileName);
509
510         /* convert ansi (or oem) string to unicode */
511         if (bIsFileApiAnsi)
512                 RtlAnsiStringToUnicodeString (&FileNameU,
513                                               &FileName,
514                                               TRUE);
515         else
516                 RtlOemStringToUnicodeString (&FileNameU,
517                                              &FileName,
518                                              TRUE);
519
520         Result = GetFileAttributesW (FileNameU.Buffer);
521
522         RtlFreeUnicodeString (&FileNameU);
523
524         return Result;
525 }
526
527
528 DWORD STDCALL
529 GetFileAttributesW(LPCWSTR lpFileName)
530 {
531    IO_STATUS_BLOCK IoStatusBlock;
532    FILE_BASIC_INFORMATION FileBasic;
533    HANDLE hFile;
534    NTSTATUS errCode;
535
536    hFile = CreateFileW(lpFileName,
537                        FILE_READ_ATTRIBUTES,
538                        FILE_SHARE_READ,
539                        NULL,
540                        OPEN_EXISTING,
541                        FILE_ATTRIBUTE_NORMAL,
542                        NULL);
543    if (hFile == INVALID_HANDLE_VALUE)
544      {
545         return 0xFFFFFFFF;
546      }
547
548    errCode = NtQueryInformationFile(hFile,
549                                     &IoStatusBlock,
550                                     &FileBasic,
551                                     sizeof(FILE_BASIC_INFORMATION),
552                                     FileBasicInformation);
553    if (!NT_SUCCESS(errCode))
554      {
555         CloseHandle(hFile);
556         SetLastErrorByStatus(errCode);
557         return 0xFFFFFFFF;
558      }
559    CloseHandle(hFile);
560    return (DWORD)FileBasic.FileAttributes;
561 }
562
563
564 WINBOOL STDCALL
565 SetFileAttributesA(LPCSTR lpFileName,
566                    DWORD dwFileAttributes)
567 {
568    UNICODE_STRING FileNameU;
569    ANSI_STRING FileName;
570    WINBOOL Result;
571
572    RtlInitAnsiString(&FileName,
573                      (LPSTR)lpFileName);
574
575    /* convert ansi (or oem) string to unicode */
576    if (bIsFileApiAnsi)
577      RtlAnsiStringToUnicodeString(&FileNameU,
578                                   &FileName,
579                                   TRUE);
580    else
581      RtlOemStringToUnicodeString(&FileNameU,
582                                  &FileName,
583                                  TRUE);
584
585    Result = SetFileAttributesW(FileNameU.Buffer,
586                                dwFileAttributes);
587
588    RtlFreeUnicodeString(&FileNameU);
589
590    return Result;
591 }
592
593
594 WINBOOL STDCALL
595 SetFileAttributesW(LPCWSTR lpFileName,
596                    DWORD dwFileAttributes)
597 {
598    IO_STATUS_BLOCK IoStatusBlock;
599    FILE_BASIC_INFORMATION FileBasic;
600    HANDLE hFile;
601    NTSTATUS errCode;
602    
603    hFile = CreateFileW(lpFileName,
604                        FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
605                        FILE_SHARE_READ,
606                        NULL,
607                        OPEN_EXISTING,
608                        FILE_ATTRIBUTE_NORMAL,
609                        NULL);
610
611    errCode = NtQueryInformationFile(hFile,
612                                     &IoStatusBlock,
613                                     &FileBasic,
614                                     sizeof(FILE_BASIC_INFORMATION),
615                                     FileBasicInformation);
616    if (!NT_SUCCESS(errCode))
617      {
618         CloseHandle(hFile);
619         SetLastErrorByStatus(errCode);
620         return FALSE;
621      }
622    FileBasic.FileAttributes = dwFileAttributes;
623    errCode = NtSetInformationFile(hFile,
624                                   &IoStatusBlock,
625                                   &FileBasic,
626                                   sizeof(FILE_BASIC_INFORMATION),
627                                   FileBasicInformation);
628    if (!NT_SUCCESS(errCode))
629      {
630         CloseHandle(hFile);
631         SetLastErrorByStatus(errCode);
632         return FALSE;
633      }
634    CloseHandle(hFile);
635    return TRUE;
636 }
637
638
639 UINT STDCALL
640 GetTempFileNameA(LPCSTR lpPathName,
641                  LPCSTR lpPrefixString,
642                  UINT uUnique,
643                  LPSTR lpTempFileName)
644 {
645    HANDLE hFile;
646    UINT unique = uUnique;
647    UINT len;
648    const char *format = "%.*s\\~%.3s%4.4x.TMP";
649
650    DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
651           "uUnique %x, lpTempFileName %x)\n", lpPathName, 4, 
652           lpPrefixString, uUnique, lpTempFileName);
653   
654    if (lpPathName == NULL)
655      return 0;
656
657    len = strlen(lpPathName);
658    if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
659      len--;
660
661    if (uUnique == 0)
662      uUnique = GetCurrentTime();
663    
664    sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
665    
666    if (unique)
667      return uUnique;
668    
669    while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
670                                CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
671                                0)) == INVALID_HANDLE_VALUE)
672    {
673       if (GetLastError() != ERROR_ALREADY_EXISTS)
674       {
675          return 0;
676       }
677       sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
678    }
679    CloseHandle(hFile);
680    return uUnique;
681 }
682
683
684 UINT STDCALL
685 GetTempFileNameW(LPCWSTR lpPathName,
686                  LPCWSTR lpPrefixString,
687                  UINT uUnique,
688                  LPWSTR lpTempFileName)
689 {
690    HANDLE hFile;
691    UINT unique = uUnique;
692    UINT len;
693    const WCHAR *format = L"%.*S\\~%.3S%4.4x.TMP";
694    
695    DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
696           "uUnique %x, lpTempFileName %x)\n", lpPathName, 4, 
697           lpPrefixString, uUnique, lpTempFileName);
698
699    if (lpPathName == NULL)
700      return 0;
701
702    len = wcslen(lpPathName);
703    if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
704      len--;
705    
706    if (uUnique == 0)
707      uUnique = GetCurrentTime();
708    
709    swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
710    
711    if (unique)
712      return uUnique;
713   
714    while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
715                                CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
716                                0)) == INVALID_HANDLE_VALUE)
717    {
718       if (GetLastError() != ERROR_ALREADY_EXISTS)
719       {
720          return 0;
721       }
722       swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
723    }
724    CloseHandle(hFile);
725    return uUnique;
726 }
727
728
729 WINBOOL STDCALL
730 GetFileTime(HANDLE hFile,
731             LPFILETIME lpCreationTime,
732             LPFILETIME lpLastAccessTime,
733             LPFILETIME lpLastWriteTime)
734 {
735    IO_STATUS_BLOCK IoStatusBlock;
736    FILE_BASIC_INFORMATION FileBasic;
737    NTSTATUS Status;
738
739    Status = NtQueryInformationFile(hFile,
740                                    &IoStatusBlock,
741                                    &FileBasic,
742                                    sizeof(FILE_BASIC_INFORMATION),
743                                    FileBasicInformation);
744    if (!NT_SUCCESS(Status))
745      {
746         SetLastErrorByStatus(Status);
747         return FALSE;
748      }
749
750    if (lpCreationTime)
751      memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
752    if (lpLastAccessTime)
753      memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
754    if (lpLastWriteTime)
755      memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
756
757    return TRUE;
758 }
759
760
761 WINBOOL STDCALL
762 SetFileTime(HANDLE hFile,
763             CONST FILETIME *lpCreationTime,
764             CONST FILETIME *lpLastAccessTime,
765             CONST FILETIME *lpLastWriteTime)
766 {
767    FILE_BASIC_INFORMATION FileBasic;
768    IO_STATUS_BLOCK IoStatusBlock;
769    NTSTATUS Status;
770
771    Status = NtQueryInformationFile(hFile,
772                                    &IoStatusBlock,
773                                    &FileBasic,
774                                    sizeof(FILE_BASIC_INFORMATION),
775                                    FileBasicInformation);
776    if (!NT_SUCCESS(Status))
777      {
778         SetLastErrorByStatus(Status);
779         return FALSE;
780      }
781
782    if (lpCreationTime)
783      memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
784    if (lpLastAccessTime)
785      memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
786    if (lpLastWriteTime)
787      memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
788
789    // should i initialize changetime ???
790
791    Status = NtSetInformationFile(hFile,
792                                  &IoStatusBlock,
793                                  &FileBasic,
794                                  sizeof(FILE_BASIC_INFORMATION),
795                                  FileBasicInformation);
796    if (!NT_SUCCESS(Status))
797      {
798         SetLastErrorByStatus(Status);
799         return FALSE;
800      }
801    
802    return TRUE;
803 }
804
805
806 /*
807 The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
808 */
809 WINBOOL STDCALL
810 SetEndOfFile(HANDLE hFile)
811 {
812         IO_STATUS_BLOCK  IoStatusBlock;
813         FILE_END_OF_FILE_INFORMATION    EndOfFileInfo;
814         FILE_ALLOCATION_INFORMATION             FileAllocationInfo;
815         FILE_POSITION_INFORMATION                FilePosInfo;
816         NTSTATUS Status;
817
818         //get current position
819         Status = NtQueryInformationFile(
820                                         hFile,
821                                         &IoStatusBlock,
822                                         &FilePosInfo,
823                                         sizeof(FILE_POSITION_INFORMATION),
824                                         FilePositionInformation
825                                         );
826
827         if (!NT_SUCCESS(Status)){
828                 SetLastErrorByStatus(Status);
829                 return FALSE;
830         }
831
832         EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
833
834         /*
835         NOTE: 
836         This call is not supposed to free up any space after the eof marker
837         if the file gets truncated. We have to deallocate the space explicitly afterwards.
838         But...most file systems dispatch both FileEndOfFileInformation 
839         and FileAllocationInformation as they were the same     command.
840
841         */
842         Status = NtSetInformationFile(
843                                                 hFile,
844                                                 &IoStatusBlock,  //out
845                                                 &EndOfFileInfo,
846                                                 sizeof(FILE_END_OF_FILE_INFORMATION),
847                                                 FileEndOfFileInformation
848                                                 );
849
850         if (!NT_SUCCESS(Status)){
851                 SetLastErrorByStatus(Status);
852                 return FALSE;
853         }
854
855         FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
856
857
858         Status = NtSetInformationFile(
859                                                 hFile,
860                                                 &IoStatusBlock,  //out
861                                                 &FileAllocationInfo,
862                                                 sizeof(FILE_ALLOCATION_INFORMATION),
863                                                 FileAllocationInformation
864                                                 );
865
866         if (!NT_SUCCESS(Status)){
867                 SetLastErrorByStatus(Status);
868                 return FALSE;
869         }
870         
871         return TRUE;
872
873 }
874
875 /* EOF */