implemented SetFileShortName()
[reactos.git] / reactos / lib / kernel32 / file / file.c
1 /* $Id: file.c,v 1.53 2004/03/18 18:29:18 weiden 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 <k32.h>
16 #include <ddk/ntifs.h>
17
18 #define NDEBUG
19 #include "../include/debug.h"
20
21
22 /* GLOBALS ******************************************************************/
23
24 BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
25
26
27 /* FUNCTIONS ****************************************************************/
28
29 /*
30 * @implemented
31 */
32 VOID STDCALL
33 SetFileApisToOEM(VOID)
34 {
35 bIsFileApiAnsi = FALSE;
36 }
37
38
39 /*
40 * @implemented
41 */
42 VOID STDCALL
43 SetFileApisToANSI(VOID)
44 {
45 bIsFileApiAnsi = TRUE;
46 }
47
48
49 /*
50 * @implemented
51 */
52 BOOL STDCALL
53 AreFileApisANSI(VOID)
54 {
55 return bIsFileApiAnsi;
56 }
57
58
59 /*
60 * @implemented
61 */
62 HFILE STDCALL
63 OpenFile(LPCSTR lpFileName,
64 LPOFSTRUCT lpReOpenBuff,
65 UINT uStyle)
66 {
67 OBJECT_ATTRIBUTES ObjectAttributes;
68 IO_STATUS_BLOCK IoStatusBlock;
69 UNICODE_STRING FileNameString;
70 UNICODE_STRING FileNameU;
71 ANSI_STRING FileName;
72 WCHAR PathNameW[MAX_PATH];
73 HANDLE FileHandle = NULL;
74 NTSTATUS errCode;
75 PWCHAR FilePart;
76 ULONG Len;
77
78 DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
79
80 if (lpReOpenBuff == NULL)
81 {
82 return FALSE;
83 }
84
85 RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
86
87 /* convert ansi (or oem) string to unicode */
88 if (bIsFileApiAnsi)
89 RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
90 else
91 RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
92
93 Len = SearchPathW (NULL,
94 FileNameU.Buffer,
95 NULL,
96 OFS_MAXPATHNAME,
97 PathNameW,
98 &FilePart);
99
100 RtlFreeUnicodeString(&FileNameU);
101
102 if (Len == 0 || Len > OFS_MAXPATHNAME)
103 {
104 return (HFILE)INVALID_HANDLE_VALUE;
105 }
106
107 FileName.Buffer = lpReOpenBuff->szPathName;
108 FileName.Length = 0;
109 FileName.MaximumLength = OFS_MAXPATHNAME;
110
111 RtlInitUnicodeString(&FileNameU, PathNameW);
112
113 /* convert unicode string to ansi (or oem) */
114 if (bIsFileApiAnsi)
115 RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
116 else
117 RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
118
119 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)PathNameW,
120 &FileNameString,
121 NULL,
122 NULL))
123 {
124 return (HFILE)INVALID_HANDLE_VALUE;
125 }
126
127 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
128 ObjectAttributes.RootDirectory = NULL;
129 ObjectAttributes.ObjectName = &FileNameString;
130 ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
131 ObjectAttributes.SecurityDescriptor = NULL;
132 ObjectAttributes.SecurityQualityOfService = NULL;
133
134 // FILE_SHARE_READ
135 // FILE_NO_INTERMEDIATE_BUFFERING
136
137 if ((uStyle & OF_PARSE) == OF_PARSE)
138 {
139 RtlFreeUnicodeString(&FileNameString);
140 return (HFILE)NULL;
141 }
142
143 errCode = NtOpenFile (&FileHandle,
144 GENERIC_READ|SYNCHRONIZE,
145 &ObjectAttributes,
146 &IoStatusBlock,
147 FILE_SHARE_READ,
148 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
149
150 RtlFreeUnicodeString(&FileNameString);
151
152 lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
153
154 if (!NT_SUCCESS(errCode))
155 {
156 SetLastErrorByStatus (errCode);
157 return (HFILE)INVALID_HANDLE_VALUE;
158 }
159
160 return (HFILE)FileHandle;
161 }
162
163
164 /*
165 * @implemented
166 */
167 BOOL STDCALL
168 FlushFileBuffers(HANDLE hFile)
169 {
170 NTSTATUS errCode;
171 IO_STATUS_BLOCK IoStatusBlock;
172
173 if (IsConsoleHandle(hFile))
174 {
175 return FALSE;
176 }
177
178 errCode = NtFlushBuffersFile(hFile,
179 &IoStatusBlock);
180 if (!NT_SUCCESS(errCode))
181 {
182 SetLastErrorByStatus(errCode);
183 return(FALSE);
184 }
185 return(TRUE);
186 }
187
188
189 /*
190 * @implemented
191 */
192 DWORD STDCALL
193 SetFilePointer(HANDLE hFile,
194 LONG lDistanceToMove,
195 PLONG lpDistanceToMoveHigh,
196 DWORD dwMoveMethod)
197 {
198 FILE_POSITION_INFORMATION FilePosition;
199 FILE_STANDARD_INFORMATION FileStandart;
200 NTSTATUS errCode;
201 IO_STATUS_BLOCK IoStatusBlock;
202 LARGE_INTEGER Distance;
203
204 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
205 hFile,lDistanceToMove,dwMoveMethod);
206
207 /* FIXME - should fail if hFile is a console handle */
208
209 Distance.u.LowPart = lDistanceToMove;
210 if (lpDistanceToMoveHigh)
211 {
212 Distance.u.HighPart = *lpDistanceToMoveHigh;
213 }
214 else if (lDistanceToMove >= 0)
215 {
216 Distance.u.HighPart = 0;
217 }
218 else
219 {
220 Distance.u.HighPart = -1;
221 }
222
223 switch(dwMoveMethod)
224 {
225 case FILE_CURRENT:
226 NtQueryInformationFile(hFile,
227 &IoStatusBlock,
228 &FilePosition,
229 sizeof(FILE_POSITION_INFORMATION),
230 FilePositionInformation);
231 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
232 break;
233 case FILE_END:
234 NtQueryInformationFile(hFile,
235 &IoStatusBlock,
236 &FileStandart,
237 sizeof(FILE_STANDARD_INFORMATION),
238 FileStandardInformation);
239 FilePosition.CurrentByteOffset.QuadPart =
240 FileStandart.EndOfFile.QuadPart + Distance.QuadPart;
241 break;
242 case FILE_BEGIN:
243 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
244 break;
245 }
246
247 if(FilePosition.CurrentByteOffset.QuadPart < 0)
248 {
249 SetLastError(ERROR_NEGATIVE_SEEK);
250 return -1;
251 }
252
253 errCode = NtSetInformationFile(hFile,
254 &IoStatusBlock,
255 &FilePosition,
256 sizeof(FILE_POSITION_INFORMATION),
257 FilePositionInformation);
258 if (!NT_SUCCESS(errCode))
259 {
260 SetLastErrorByStatus(errCode);
261 return -1;
262 }
263
264 if (lpDistanceToMoveHigh != NULL)
265 {
266 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
267 }
268 return FilePosition.CurrentByteOffset.u.LowPart;
269 }
270
271
272 /*
273 * @implemented
274 */
275 BOOL
276 STDCALL
277 SetFilePointerEx(HANDLE hFile,
278 LARGE_INTEGER liDistanceToMove,
279 PLARGE_INTEGER lpNewFilePointer,
280 DWORD dwMoveMethod)
281 {
282 FILE_POSITION_INFORMATION FilePosition;
283 FILE_STANDARD_INFORMATION FileStandart;
284 NTSTATUS errCode;
285 IO_STATUS_BLOCK IoStatusBlock;
286
287 /* FIXME - should fail if hFile is a console handle */
288
289 switch(dwMoveMethod)
290 {
291 case FILE_CURRENT:
292 NtQueryInformationFile(hFile,
293 &IoStatusBlock,
294 &FilePosition,
295 sizeof(FILE_POSITION_INFORMATION),
296 FilePositionInformation);
297 FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart;
298 break;
299 case FILE_END:
300 NtQueryInformationFile(hFile,
301 &IoStatusBlock,
302 &FileStandart,
303 sizeof(FILE_STANDARD_INFORMATION),
304 FileStandardInformation);
305 FilePosition.CurrentByteOffset.QuadPart =
306 FileStandart.EndOfFile.QuadPart + liDistanceToMove.QuadPart;
307 break;
308 case FILE_BEGIN:
309 FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart;
310 break;
311 }
312
313 if(FilePosition.CurrentByteOffset.QuadPart < 0)
314 {
315 SetLastError(ERROR_NEGATIVE_SEEK);
316 return FALSE;
317 }
318
319 errCode = NtSetInformationFile(hFile,
320 &IoStatusBlock,
321 &FilePosition,
322 sizeof(FILE_POSITION_INFORMATION),
323 FilePositionInformation);
324 if (!NT_SUCCESS(errCode))
325 {
326 SetLastErrorByStatus(errCode);
327 return FALSE;
328 }
329
330 if (lpNewFilePointer)
331 {
332 *lpNewFilePointer = FilePosition.CurrentByteOffset;
333 }
334 return TRUE;
335 }
336
337
338 /*
339 * @implemented
340 */
341 DWORD STDCALL
342 GetFileType(HANDLE hFile)
343 {
344 FILE_FS_DEVICE_INFORMATION DeviceInfo;
345 IO_STATUS_BLOCK StatusBlock;
346 NTSTATUS Status;
347
348 /* Get real handle */
349 switch ((ULONG)hFile)
350 {
351 case STD_INPUT_HANDLE:
352 hFile = NtCurrentPeb()->ProcessParameters->hStdInput;
353 break;
354
355 case STD_OUTPUT_HANDLE:
356 hFile = NtCurrentPeb()->ProcessParameters->hStdOutput;
357 break;
358
359 case STD_ERROR_HANDLE:
360 hFile = NtCurrentPeb()->ProcessParameters->hStdError;
361 break;
362 }
363
364 /* Check for console handle */
365 if (IsConsoleHandle(hFile))
366 {
367 if (VerifyConsoleIoHandle(hFile))
368 return FILE_TYPE_CHAR;
369 }
370
371 Status = NtQueryVolumeInformationFile(hFile,
372 &StatusBlock,
373 &DeviceInfo,
374 sizeof(FILE_FS_DEVICE_INFORMATION),
375 FileFsDeviceInformation);
376 if (!NT_SUCCESS(Status))
377 {
378 SetLastErrorByStatus(Status);
379 return FILE_TYPE_UNKNOWN;
380 }
381
382 switch (DeviceInfo.DeviceType)
383 {
384 case FILE_DEVICE_CD_ROM:
385 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
386 case FILE_DEVICE_CONTROLLER:
387 case FILE_DEVICE_DATALINK:
388 case FILE_DEVICE_DFS:
389 case FILE_DEVICE_DISK:
390 case FILE_DEVICE_DISK_FILE_SYSTEM:
391 case FILE_DEVICE_VIRTUAL_DISK:
392 return FILE_TYPE_DISK;
393
394 case FILE_DEVICE_KEYBOARD:
395 case FILE_DEVICE_MOUSE:
396 case FILE_DEVICE_NULL:
397 case FILE_DEVICE_PARALLEL_PORT:
398 case FILE_DEVICE_PRINTER:
399 case FILE_DEVICE_SERIAL_PORT:
400 case FILE_DEVICE_SCREEN:
401 case FILE_DEVICE_SOUND:
402 case FILE_DEVICE_MODEM:
403 return FILE_TYPE_CHAR;
404
405 case FILE_DEVICE_NAMED_PIPE:
406 return FILE_TYPE_PIPE;
407 }
408
409 return FILE_TYPE_UNKNOWN;
410 }
411
412
413 /*
414 * @implemented
415 */
416 DWORD STDCALL
417 GetFileSize(HANDLE hFile,
418 LPDWORD lpFileSizeHigh)
419 {
420 NTSTATUS errCode;
421 FILE_STANDARD_INFORMATION FileStandard;
422 IO_STATUS_BLOCK IoStatusBlock;
423
424 errCode = NtQueryInformationFile(hFile,
425 &IoStatusBlock,
426 &FileStandard,
427 sizeof(FILE_STANDARD_INFORMATION),
428 FileStandardInformation);
429 if (!NT_SUCCESS(errCode))
430 {
431 SetLastErrorByStatus(errCode);
432 if ( lpFileSizeHigh == NULL )
433 {
434 return -1;
435 }
436 else
437 {
438 return 0;
439 }
440 }
441 if ( lpFileSizeHigh != NULL )
442 *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
443
444 return FileStandard.EndOfFile.u.LowPart;
445 }
446
447
448 /*
449 * @implemented
450 */
451 BOOL
452 STDCALL
453 GetFileSizeEx(
454 HANDLE hFile,
455 PLARGE_INTEGER lpFileSize
456 )
457 {
458 NTSTATUS errCode;
459 FILE_STANDARD_INFORMATION FileStandard;
460 IO_STATUS_BLOCK IoStatusBlock;
461
462 errCode = NtQueryInformationFile(hFile,
463 &IoStatusBlock,
464 &FileStandard,
465 sizeof(FILE_STANDARD_INFORMATION),
466 FileStandardInformation);
467 if (!NT_SUCCESS(errCode))
468 {
469 SetLastErrorByStatus(errCode);
470 return FALSE;
471 }
472 if (lpFileSize)
473 *lpFileSize = FileStandard.EndOfFile;
474
475 return TRUE;
476 }
477
478
479 /*
480 * @implemented
481 */
482 DWORD STDCALL
483 GetCompressedFileSizeA(LPCSTR lpFileName,
484 LPDWORD lpFileSizeHigh)
485 {
486 UNICODE_STRING FileNameU;
487 ANSI_STRING FileName;
488 DWORD Size;
489
490 RtlInitAnsiString(&FileName,
491 (LPSTR)lpFileName);
492
493 /* convert ansi (or oem) string to unicode */
494 if (bIsFileApiAnsi)
495 RtlAnsiStringToUnicodeString(&FileNameU,
496 &FileName,
497 TRUE);
498 else
499 RtlOemStringToUnicodeString(&FileNameU,
500 &FileName,
501 TRUE);
502
503 Size = GetCompressedFileSizeW(FileNameU.Buffer,
504 lpFileSizeHigh);
505
506 RtlFreeUnicodeString (&FileNameU);
507
508 return Size;
509 }
510
511
512 /*
513 * @implemented
514 */
515 DWORD STDCALL
516 GetCompressedFileSizeW(LPCWSTR lpFileName,
517 LPDWORD lpFileSizeHigh)
518 {
519 FILE_COMPRESSION_INFORMATION FileCompression;
520 NTSTATUS errCode;
521 IO_STATUS_BLOCK IoStatusBlock;
522 HANDLE hFile;
523
524 hFile = CreateFileW(lpFileName,
525 GENERIC_READ,
526 FILE_SHARE_READ,
527 NULL,
528 OPEN_EXISTING,
529 FILE_ATTRIBUTE_NORMAL,
530 NULL);
531
532 errCode = NtQueryInformationFile(hFile,
533 &IoStatusBlock,
534 &FileCompression,
535 sizeof(FILE_COMPRESSION_INFORMATION),
536 FileCompressionInformation);
537 if (!NT_SUCCESS(errCode))
538 {
539 CloseHandle(hFile);
540 SetLastErrorByStatus(errCode);
541 return INVALID_FILE_SIZE;
542 }
543 CloseHandle(hFile);
544
545 if(lpFileSizeHigh)
546 *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
547
548 return FileCompression.CompressedFileSize.u.LowPart;
549 }
550
551
552 /*
553 * @implemented
554 */
555 BOOL STDCALL
556 GetFileInformationByHandle(HANDLE hFile,
557 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
558 {
559 struct
560 {
561 FILE_FS_VOLUME_INFORMATION FileFsVolume;
562 WCHAR Name[255];
563 }
564 FileFsVolume;
565
566 FILE_BASIC_INFORMATION FileBasic;
567 FILE_INTERNAL_INFORMATION FileInternal;
568 FILE_STANDARD_INFORMATION FileStandard;
569 NTSTATUS errCode;
570 IO_STATUS_BLOCK IoStatusBlock;
571
572 errCode = NtQueryInformationFile(hFile,
573 &IoStatusBlock,
574 &FileBasic,
575 sizeof(FILE_BASIC_INFORMATION),
576 FileBasicInformation);
577 if (!NT_SUCCESS(errCode))
578 {
579 SetLastErrorByStatus(errCode);
580 return FALSE;
581 }
582
583 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
584 memcpy(&lpFileInformation->ftCreationTime,&FileBasic.CreationTime,sizeof(LARGE_INTEGER));
585 memcpy(&lpFileInformation->ftLastAccessTime,&FileBasic.LastAccessTime,sizeof(LARGE_INTEGER));
586 memcpy(&lpFileInformation->ftLastWriteTime, &FileBasic.LastWriteTime,sizeof(LARGE_INTEGER));
587
588 errCode = NtQueryInformationFile(hFile,
589 &IoStatusBlock,
590 &FileInternal,
591 sizeof(FILE_INTERNAL_INFORMATION),
592 FileInternalInformation);
593 if (!NT_SUCCESS(errCode))
594 {
595 SetLastErrorByStatus(errCode);
596 return FALSE;
597 }
598
599 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
600 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
601
602 errCode = NtQueryVolumeInformationFile(hFile,
603 &IoStatusBlock,
604 &FileFsVolume,
605 sizeof(FileFsVolume),
606 FileFsVolumeInformation);
607 if (!NT_SUCCESS(errCode))
608 {
609 SetLastErrorByStatus(errCode);
610 return FALSE;
611 }
612
613 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
614
615 errCode = NtQueryInformationFile(hFile,
616 &IoStatusBlock,
617 &FileStandard,
618 sizeof(FILE_STANDARD_INFORMATION),
619 FileStandardInformation);
620 if (!NT_SUCCESS(errCode))
621 {
622 SetLastErrorByStatus(errCode);
623 return FALSE;
624 }
625
626 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
627 lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
628 lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
629
630 return TRUE;
631 }
632
633
634 /*
635 * @implemented
636 */
637 BOOL STDCALL
638 GetFileAttributesExW(LPCWSTR lpFileName,
639 GET_FILEEX_INFO_LEVELS fInfoLevelId,
640 LPVOID lpFileInformation)
641 {
642 FILE_NETWORK_OPEN_INFORMATION FileInformation;
643 OBJECT_ATTRIBUTES ObjectAttributes;
644 IO_STATUS_BLOCK IoStatusBlock;
645 UNICODE_STRING FileName;
646 HANDLE FileHandle;
647 NTSTATUS Status;
648 WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
649
650 DPRINT ("GetFileAttributesExW(%S) called\n", lpFileName);
651
652
653 if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
654 {
655 SetLastError(ERROR_INVALID_PARAMETER);
656 return FALSE;
657 }
658
659 /* Validate and translate the filename */
660 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
661 &FileName,
662 NULL,
663 NULL))
664 {
665 DPRINT ("Invalid path\n");
666 SetLastError (ERROR_BAD_PATHNAME);
667 return FALSE;
668 }
669
670 /* build the object attributes */
671 InitializeObjectAttributes (&ObjectAttributes,
672 &FileName,
673 OBJ_CASE_INSENSITIVE,
674 NULL,
675 NULL);
676
677 /* Open the file */
678 Status = NtOpenFile (&FileHandle,
679 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
680 &ObjectAttributes,
681 &IoStatusBlock,
682 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
683 FILE_SYNCHRONOUS_IO_NONALERT);
684 RtlFreeUnicodeString (&FileName);
685 if (!NT_SUCCESS (Status))
686 {
687 DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
688 SetLastErrorByStatus (Status);
689 return FALSE;
690 }
691
692 /* Get file attributes */
693 Status = NtQueryInformationFile (FileHandle,
694 &IoStatusBlock,
695 &FileInformation,
696 sizeof(FILE_NETWORK_OPEN_INFORMATION),
697 FileNetworkOpenInformation);
698 NtClose (FileHandle);
699
700 if (!NT_SUCCESS (Status))
701 {
702 DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
703 SetLastErrorByStatus (Status);
704 return FALSE;
705 }
706
707 FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation;
708 FileAttributeData->dwFileAttributes = FileInformation.FileAttributes;
709 FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart;
710 FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart;
711 FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart;
712 FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart;
713 FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart;
714 FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart;
715 FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart;
716 FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart;
717
718 return TRUE;
719 }
720
721 /*
722 * @implemented
723 */
724 BOOL STDCALL
725 GetFileAttributesExA(LPCSTR lpFileName,
726 GET_FILEEX_INFO_LEVELS fInfoLevelId,
727 LPVOID lpFileInformation)
728 {
729 UNICODE_STRING FileNameU;
730 ANSI_STRING FileName;
731 BOOL Result;
732 RtlInitAnsiString (&FileName,
733 (LPSTR)lpFileName);
734
735 /* convert ansi (or oem) string to unicode */
736 if (bIsFileApiAnsi)
737 RtlAnsiStringToUnicodeString (&FileNameU,
738 &FileName,
739 TRUE);
740 else
741 RtlOemStringToUnicodeString (&FileNameU,
742 &FileName,
743 TRUE);
744
745 Result = GetFileAttributesExW(FileNameU.Buffer, fInfoLevelId, lpFileInformation);
746
747 RtlFreeUnicodeString (&FileNameU);
748
749 return Result;
750 }
751
752
753 /*
754 * @implemented
755 */
756 DWORD STDCALL
757 GetFileAttributesA(LPCSTR lpFileName)
758 {
759 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
760 UNICODE_STRING FileNameU;
761 ANSI_STRING FileName;
762 BOOL Result;
763
764 RtlInitAnsiString (&FileName,
765 (LPSTR)lpFileName);
766
767 /* convert ansi (or oem) string to unicode */
768 if (bIsFileApiAnsi)
769 RtlAnsiStringToUnicodeString (&FileNameU,
770 &FileName,
771 TRUE);
772 else
773 RtlOemStringToUnicodeString (&FileNameU,
774 &FileName,
775 TRUE);
776
777 Result = GetFileAttributesExW(FileNameU.Buffer, GetFileExInfoStandard, &FileAttributeData);
778
779 RtlFreeUnicodeString (&FileNameU);
780
781 return Result ? FileAttributeData.dwFileAttributes : 0xffffffff;
782 }
783
784
785 /*
786 * @implemented
787 */
788 DWORD STDCALL
789 GetFileAttributesW(LPCWSTR lpFileName)
790 {
791 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
792 BOOL Result;
793
794 DPRINT ("GetFileAttributeW(%S) called\n", lpFileName);
795
796 Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
797
798 return Result ? FileAttributeData.dwFileAttributes : 0xffffffff;
799 }
800
801 BOOL STDCALL
802 SetFileAttributesA(LPCSTR lpFileName,
803 DWORD dwFileAttributes)
804 {
805 UNICODE_STRING FileNameU;
806 ANSI_STRING FileName;
807 BOOL Result;
808
809 RtlInitAnsiString (&FileName,
810 (LPSTR)lpFileName);
811
812 /* convert ansi (or oem) string to unicode */
813 if (bIsFileApiAnsi)
814 RtlAnsiStringToUnicodeString (&FileNameU,
815 &FileName,
816 TRUE);
817 else
818 RtlOemStringToUnicodeString (&FileNameU,
819 &FileName,
820 TRUE);
821
822 Result = SetFileAttributesW (FileNameU.Buffer,
823 dwFileAttributes);
824
825 RtlFreeUnicodeString (&FileNameU);
826
827 return Result;
828 }
829
830
831 /*
832 * @implemented
833 */
834 BOOL STDCALL
835 SetFileAttributesW(LPCWSTR lpFileName,
836 DWORD dwFileAttributes)
837 {
838 FILE_BASIC_INFORMATION FileInformation;
839 OBJECT_ATTRIBUTES ObjectAttributes;
840 IO_STATUS_BLOCK IoStatusBlock;
841 UNICODE_STRING FileName;
842 HANDLE FileHandle;
843 NTSTATUS Status;
844
845 DPRINT ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
846
847 /* Validate and translate the filename */
848 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
849 &FileName,
850 NULL,
851 NULL))
852 {
853 DPRINT ("Invalid path\n");
854 SetLastError (ERROR_BAD_PATHNAME);
855 return FALSE;
856 }
857 DPRINT ("FileName: \'%wZ\'\n", &FileName);
858
859 /* build the object attributes */
860 InitializeObjectAttributes (&ObjectAttributes,
861 &FileName,
862 OBJ_CASE_INSENSITIVE,
863 NULL,
864 NULL);
865
866 /* Open the file */
867 Status = NtOpenFile (&FileHandle,
868 SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
869 &ObjectAttributes,
870 &IoStatusBlock,
871 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
872 FILE_SYNCHRONOUS_IO_NONALERT);
873 RtlFreeUnicodeString (&FileName);
874 if (!NT_SUCCESS (Status))
875 {
876 DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
877 SetLastErrorByStatus (Status);
878 return FALSE;
879 }
880
881 Status = NtQueryInformationFile(FileHandle,
882 &IoStatusBlock,
883 &FileInformation,
884 sizeof(FILE_BASIC_INFORMATION),
885 FileBasicInformation);
886 if (!NT_SUCCESS(Status))
887 {
888 DPRINT ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
889 NtClose (FileHandle);
890 SetLastErrorByStatus (Status);
891 return FALSE;
892 }
893
894 FileInformation.FileAttributes = dwFileAttributes;
895 Status = NtSetInformationFile(FileHandle,
896 &IoStatusBlock,
897 &FileInformation,
898 sizeof(FILE_BASIC_INFORMATION),
899 FileBasicInformation);
900 NtClose (FileHandle);
901 if (!NT_SUCCESS(Status))
902 {
903 DPRINT ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
904 SetLastErrorByStatus (Status);
905 return FALSE;
906 }
907
908 return TRUE;
909 }
910
911
912 /*
913 * @implemented
914 */
915 UINT STDCALL
916 GetTempFileNameA(LPCSTR lpPathName,
917 LPCSTR lpPrefixString,
918 UINT uUnique,
919 LPSTR lpTempFileName)
920 {
921 HANDLE hFile;
922 UINT unique = uUnique;
923 UINT len;
924 const char *format = "%.*s\\~%.3s%4.4x.TMP";
925
926 DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
927 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
928 lpPrefixString, uUnique, lpTempFileName);
929
930 if (lpPathName == NULL)
931 return 0;
932
933 len = strlen(lpPathName);
934 if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
935 len--;
936
937 if (uUnique == 0)
938 uUnique = GetCurrentTime();
939
940 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
941
942 if (unique)
943 return uUnique;
944
945 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
946 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
947 0)) == INVALID_HANDLE_VALUE)
948 {
949 if (GetLastError() != ERROR_ALREADY_EXISTS)
950 {
951 return 0;
952 }
953 sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
954 }
955 CloseHandle(hFile);
956 return uUnique;
957 }
958
959
960 /*
961 * @implemented
962 */
963 UINT STDCALL
964 GetTempFileNameW(LPCWSTR lpPathName,
965 LPCWSTR lpPrefixString,
966 UINT uUnique,
967 LPWSTR lpTempFileName)
968 {
969 HANDLE hFile;
970 UINT unique = uUnique;
971 UINT len;
972 const WCHAR *format = L"%.*s\\~%.3s%4.4x.TMP";
973
974 DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
975 "uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
976 lpPrefixString, uUnique, lpTempFileName);
977
978 if (lpPathName == NULL)
979 return 0;
980
981 len = wcslen(lpPathName);
982 if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
983 len--;
984
985 if (uUnique == 0)
986 uUnique = GetCurrentTime();
987
988 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
989
990 if (unique)
991 return uUnique;
992
993 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
994 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
995 0)) == INVALID_HANDLE_VALUE)
996 {
997 if (GetLastError() != ERROR_ALREADY_EXISTS)
998 {
999 return 0;
1000 }
1001 swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
1002 }
1003 CloseHandle(hFile);
1004 return uUnique;
1005 }
1006
1007
1008 /*
1009 * @implemented
1010 */
1011 BOOL STDCALL
1012 GetFileTime(HANDLE hFile,
1013 LPFILETIME lpCreationTime,
1014 LPFILETIME lpLastAccessTime,
1015 LPFILETIME lpLastWriteTime)
1016 {
1017 IO_STATUS_BLOCK IoStatusBlock;
1018 FILE_BASIC_INFORMATION FileBasic;
1019 NTSTATUS Status;
1020
1021 Status = NtQueryInformationFile(hFile,
1022 &IoStatusBlock,
1023 &FileBasic,
1024 sizeof(FILE_BASIC_INFORMATION),
1025 FileBasicInformation);
1026 if (!NT_SUCCESS(Status))
1027 {
1028 SetLastErrorByStatus(Status);
1029 return FALSE;
1030 }
1031
1032 if (lpCreationTime)
1033 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
1034 if (lpLastAccessTime)
1035 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
1036 if (lpLastWriteTime)
1037 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
1038
1039 return TRUE;
1040 }
1041
1042
1043 /*
1044 * @implemented
1045 */
1046 BOOL STDCALL
1047 SetFileTime(HANDLE hFile,
1048 CONST FILETIME *lpCreationTime,
1049 CONST FILETIME *lpLastAccessTime,
1050 CONST FILETIME *lpLastWriteTime)
1051 {
1052 FILE_BASIC_INFORMATION FileBasic;
1053 IO_STATUS_BLOCK IoStatusBlock;
1054 NTSTATUS Status;
1055
1056 Status = NtQueryInformationFile(hFile,
1057 &IoStatusBlock,
1058 &FileBasic,
1059 sizeof(FILE_BASIC_INFORMATION),
1060 FileBasicInformation);
1061 if (!NT_SUCCESS(Status))
1062 {
1063 SetLastErrorByStatus(Status);
1064 return FALSE;
1065 }
1066
1067 if (lpCreationTime)
1068 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
1069 if (lpLastAccessTime)
1070 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
1071 if (lpLastWriteTime)
1072 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
1073
1074 // should i initialize changetime ???
1075
1076 Status = NtSetInformationFile(hFile,
1077 &IoStatusBlock,
1078 &FileBasic,
1079 sizeof(FILE_BASIC_INFORMATION),
1080 FileBasicInformation);
1081 if (!NT_SUCCESS(Status))
1082 {
1083 SetLastErrorByStatus(Status);
1084 return FALSE;
1085 }
1086
1087 return TRUE;
1088 }
1089
1090
1091 /*
1092 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1093 *
1094 * @implemented
1095 */
1096 BOOL STDCALL
1097 SetEndOfFile(HANDLE hFile)
1098 {
1099 IO_STATUS_BLOCK IoStatusBlock;
1100 FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
1101 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
1102 FILE_POSITION_INFORMATION FilePosInfo;
1103 NTSTATUS Status;
1104
1105 //get current position
1106 Status = NtQueryInformationFile(
1107 hFile,
1108 &IoStatusBlock,
1109 &FilePosInfo,
1110 sizeof(FILE_POSITION_INFORMATION),
1111 FilePositionInformation
1112 );
1113
1114 if (!NT_SUCCESS(Status)){
1115 SetLastErrorByStatus(Status);
1116 return FALSE;
1117 }
1118
1119 EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1120
1121 /*
1122 NOTE:
1123 This call is not supposed to free up any space after the eof marker
1124 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1125 But...most file systems dispatch both FileEndOfFileInformation
1126 and FileAllocationInformation as they were the same command.
1127
1128 */
1129 Status = NtSetInformationFile(
1130 hFile,
1131 &IoStatusBlock, //out
1132 &EndOfFileInfo,
1133 sizeof(FILE_END_OF_FILE_INFORMATION),
1134 FileEndOfFileInformation
1135 );
1136
1137 if (!NT_SUCCESS(Status)){
1138 SetLastErrorByStatus(Status);
1139 return FALSE;
1140 }
1141
1142 FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1143
1144
1145 Status = NtSetInformationFile(
1146 hFile,
1147 &IoStatusBlock, //out
1148 &FileAllocationInfo,
1149 sizeof(FILE_ALLOCATION_INFORMATION),
1150 FileAllocationInformation
1151 );
1152
1153 if (!NT_SUCCESS(Status)){
1154 SetLastErrorByStatus(Status);
1155 return FALSE;
1156 }
1157
1158 return TRUE;
1159
1160 }
1161
1162
1163 /*
1164 * @implemented
1165 */
1166 BOOL
1167 STDCALL
1168 SetFileValidData(
1169 HANDLE hFile,
1170 LONGLONG ValidDataLength
1171 )
1172 {
1173 IO_STATUS_BLOCK IoStatusBlock;
1174 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
1175 NTSTATUS Status;
1176
1177 ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
1178
1179 Status = NtSetInformationFile(
1180 hFile,
1181 &IoStatusBlock, //out
1182 &ValidDataLengthInformation,
1183 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
1184 FileValidDataLengthInformation
1185 );
1186
1187 if (!NT_SUCCESS(Status)){
1188 SetLastErrorByStatus(Status);
1189 return FALSE;
1190 }
1191
1192 return TRUE;
1193 }
1194
1195
1196 /*
1197 * @implemented
1198 */
1199 BOOL
1200 STDCALL
1201 SetFileShortNameW(
1202 HANDLE hFile,
1203 LPCWSTR lpShortName)
1204 {
1205 NTSTATUS Status;
1206 ULONG NeededSize;
1207 UNICODE_STRING ShortName;
1208 IO_STATUS_BLOCK IoStatusBlock;
1209 PFILE_NAME_INFORMATION FileNameInformation;
1210
1211 if(!lpShortName)
1212 {
1213 SetLastError(ERROR_INVALID_PARAMETER);
1214 return FALSE;
1215 }
1216
1217 RtlInitUnicodeString(&ShortName, lpShortName);
1218
1219 NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR);
1220 if(!(FileNameInformation = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize)))
1221 {
1222 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1223 return FALSE;
1224 }
1225
1226 FileNameInformation->FileNameLength = ShortName.Length;
1227 RtlCopyMemory(FileNameInformation->FileName, ShortName.Buffer, ShortName.Length);
1228
1229 Status = NtSetInformationFile(hFile,
1230 &IoStatusBlock, //out
1231 FileNameInformation,
1232 NeededSize,
1233 FileShortNameInformation);
1234
1235 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInformation);
1236 if(!NT_SUCCESS(Status))
1237 {
1238
1239 SetLastErrorByStatus(Status);
1240 }
1241
1242 return NT_SUCCESS(Status);
1243 }
1244
1245
1246 /*
1247 * @implemented
1248 */
1249 BOOL
1250 STDCALL
1251 SetFileShortNameA(
1252 HANDLE hFile,
1253 LPCSTR lpShortName
1254 )
1255 {
1256 NTSTATUS Status;
1257 BOOL Ret;
1258 ANSI_STRING ShortNameA;
1259 UNICODE_STRING ShortName;
1260
1261 if(!lpShortName)
1262 {
1263 SetLastError(ERROR_INVALID_PARAMETER);
1264 return FALSE;
1265 }
1266
1267 RtlInitAnsiString(&ShortNameA, (LPSTR)lpShortName);
1268
1269 if(bIsFileApiAnsi)
1270 Status = RtlAnsiStringToUnicodeString(&ShortName, &ShortNameA, TRUE);
1271 else
1272 Status = RtlOemStringToUnicodeString(&ShortName, &ShortNameA, TRUE);
1273 if(!NT_SUCCESS(Status))
1274 {
1275 SetLastErrorByStatus(Status);
1276 return FALSE;
1277 }
1278
1279 Ret = SetFileShortNameW(hFile, ShortName.Buffer);
1280
1281 RtlFreeUnicodeString(&ShortName);
1282 return Ret;
1283 }
1284
1285 /* EOF */