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