Sunc with trunk revision 58971.
[reactos.git] / dll / win32 / kernel32 / client / file / fileinfo.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/file.c
5 * PURPOSE: Directory functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <k32.h>
15 #define NDEBUG
16 #include <debug.h>
17 DEBUG_CHANNEL(kernel32file);
18
19 /* FUNCTIONS ****************************************************************/
20
21 PWCHAR
22 FilenameA2W(LPCSTR NameA, BOOL alloc)
23 {
24 ANSI_STRING str;
25 UNICODE_STRING strW;
26 PUNICODE_STRING pstrW;
27 NTSTATUS Status;
28
29 //ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
30 ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer));
31
32 RtlInitAnsiString(&str, NameA);
33 pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
34
35 if (bIsFileApiAnsi)
36 Status= RtlAnsiStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc );
37 else
38 Status= RtlOemStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc );
39
40 if (NT_SUCCESS(Status))
41 return pstrW->Buffer;
42
43 if (Status== STATUS_BUFFER_OVERFLOW)
44 SetLastError( ERROR_FILENAME_EXCED_RANGE );
45 else
46 BaseSetLastNTError(Status);
47
48 return NULL;
49 }
50
51
52 /*
53 No copy/conversion is done if the dest. buffer is too small.
54
55 Returns:
56 Success: number of TCHARS copied into dest. buffer NOT including nullterm
57 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
58 */
59 DWORD
60 FilenameU2A_FitOrFail(
61 LPSTR DestA,
62 INT destLen, /* buffer size in TCHARS incl. nullchar */
63 PUNICODE_STRING SourceU
64 )
65 {
66 DWORD ret;
67
68 /* destLen should never exceed MAX_PATH */
69 if (destLen > MAX_PATH) destLen = MAX_PATH;
70
71 ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU);
72 /* ret incl. nullchar */
73
74 if (DestA && (INT)ret <= destLen)
75 {
76 ANSI_STRING str;
77
78 str.Buffer = DestA;
79 str.MaximumLength = (USHORT)destLen;
80
81
82 if (bIsFileApiAnsi)
83 RtlUnicodeStringToAnsiString(&str, SourceU, FALSE );
84 else
85 RtlUnicodeStringToOemString(&str, SourceU, FALSE );
86
87 ret = str.Length; /* SUCCESS: length without terminating 0 */
88 }
89
90 return ret;
91 }
92
93
94 /*
95 No copy/conversion is done if the dest. buffer is too small.
96
97 Returns:
98 Success: number of TCHARS copied into dest. buffer NOT including nullterm
99 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
100 */
101 DWORD
102 FilenameW2A_FitOrFail(
103 LPSTR DestA,
104 INT destLen, /* buffer size in TCHARS incl. nullchar */
105 LPCWSTR SourceW,
106 INT sourceLen /* buffer size in TCHARS incl. nullchar */
107 )
108 {
109 UNICODE_STRING strW;
110
111 if (sourceLen < 0) sourceLen = wcslen(SourceW) + 1;
112
113 strW.Buffer = (PWCHAR)SourceW;
114 strW.MaximumLength = sourceLen * sizeof(WCHAR);
115 strW.Length = strW.MaximumLength - sizeof(WCHAR);
116
117 return FilenameU2A_FitOrFail(DestA, destLen, &strW);
118 }
119
120
121 /*
122 Return: num. TCHARS copied into dest including nullterm
123 */
124 DWORD
125 FilenameA2W_N(
126 LPWSTR dest,
127 INT destlen, /* buffer size in TCHARS incl. nullchar */
128 LPCSTR src,
129 INT srclen /* buffer size in TCHARS incl. nullchar */
130 )
131 {
132 DWORD ret;
133
134 if (srclen < 0) srclen = strlen( src ) + 1;
135
136 if (bIsFileApiAnsi)
137 RtlMultiByteToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
138 else
139 RtlOemToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
140
141 if (ret) dest[(ret/sizeof(WCHAR))-1]=0;
142
143 return ret/sizeof(WCHAR);
144 }
145
146 /*
147 Return: num. TCHARS copied into dest including nullterm
148 */
149 DWORD
150 FilenameW2A_N(
151 LPSTR dest,
152 INT destlen, /* buffer size in TCHARS incl. nullchar */
153 LPCWSTR src,
154 INT srclen /* buffer size in TCHARS incl. nullchar */
155 )
156 {
157 DWORD ret;
158
159 if (srclen < 0) srclen = wcslen( src ) + 1;
160
161 if (bIsFileApiAnsi)
162 RtlUnicodeToMultiByteN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR));
163 else
164 RtlUnicodeToOemN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR) );
165
166 if (ret) dest[ret-1]=0;
167
168 return ret;
169 }
170
171 /*
172 * @implemented
173 */
174 BOOL WINAPI
175 FlushFileBuffers(IN HANDLE hFile)
176 {
177 NTSTATUS Status;
178 IO_STATUS_BLOCK IoStatusBlock;
179
180 hFile = TranslateStdHandle(hFile);
181
182 if (IsConsoleHandle(hFile))
183 {
184 return FlushConsoleInputBuffer(hFile);
185 }
186
187 Status = NtFlushBuffersFile(hFile,
188 &IoStatusBlock);
189 if (!NT_SUCCESS(Status))
190 {
191 BaseSetLastNTError(Status);
192 return FALSE;
193 }
194 return TRUE;
195 }
196
197
198 /*
199 * @implemented
200 */
201 DWORD WINAPI
202 SetFilePointer(HANDLE hFile,
203 LONG lDistanceToMove,
204 PLONG lpDistanceToMoveHigh,
205 DWORD dwMoveMethod)
206 {
207 FILE_POSITION_INFORMATION FilePosition;
208 FILE_STANDARD_INFORMATION FileStandard;
209 NTSTATUS errCode;
210 IO_STATUS_BLOCK IoStatusBlock;
211 LARGE_INTEGER Distance;
212
213 TRACE("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
214 hFile,lDistanceToMove,dwMoveMethod);
215
216 if(IsConsoleHandle(hFile))
217 {
218 SetLastError(ERROR_INVALID_HANDLE);
219 return INVALID_SET_FILE_POINTER;
220 }
221
222 if (lpDistanceToMoveHigh)
223 {
224 Distance.u.HighPart = *lpDistanceToMoveHigh;
225 Distance.u.LowPart = lDistanceToMove;
226 }
227 else
228 {
229 Distance.QuadPart = lDistanceToMove;
230 }
231
232 switch(dwMoveMethod)
233 {
234 case FILE_CURRENT:
235 errCode = NtQueryInformationFile(hFile,
236 &IoStatusBlock,
237 &FilePosition,
238 sizeof(FILE_POSITION_INFORMATION),
239 FilePositionInformation);
240 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
241 if (!NT_SUCCESS(errCode))
242 {
243 if (lpDistanceToMoveHigh != NULL)
244 *lpDistanceToMoveHigh = -1;
245 BaseSetLastNTError(errCode);
246 return INVALID_SET_FILE_POINTER;
247 }
248 break;
249 case FILE_END:
250 errCode = NtQueryInformationFile(hFile,
251 &IoStatusBlock,
252 &FileStandard,
253 sizeof(FILE_STANDARD_INFORMATION),
254 FileStandardInformation);
255 FilePosition.CurrentByteOffset.QuadPart =
256 FileStandard.EndOfFile.QuadPart + Distance.QuadPart;
257 if (!NT_SUCCESS(errCode))
258 {
259 if (lpDistanceToMoveHigh != NULL)
260 *lpDistanceToMoveHigh = -1;
261 BaseSetLastNTError(errCode);
262 return INVALID_SET_FILE_POINTER;
263 }
264 break;
265 case FILE_BEGIN:
266 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
267 break;
268 default:
269 SetLastError(ERROR_INVALID_PARAMETER);
270 return INVALID_SET_FILE_POINTER;
271 }
272
273 if(FilePosition.CurrentByteOffset.QuadPart < 0)
274 {
275 SetLastError(ERROR_NEGATIVE_SEEK);
276 return INVALID_SET_FILE_POINTER;
277 }
278
279 if (lpDistanceToMoveHigh == NULL && FilePosition.CurrentByteOffset.HighPart != 0)
280 {
281 /* If we're moving the pointer outside of the 32 bit boundaries but
282 the application only passed a 32 bit value we need to bail out! */
283 SetLastError(ERROR_INVALID_PARAMETER);
284 return INVALID_SET_FILE_POINTER;
285 }
286
287 errCode = NtSetInformationFile(hFile,
288 &IoStatusBlock,
289 &FilePosition,
290 sizeof(FILE_POSITION_INFORMATION),
291 FilePositionInformation);
292 if (!NT_SUCCESS(errCode))
293 {
294 if (lpDistanceToMoveHigh != NULL)
295 *lpDistanceToMoveHigh = -1;
296
297 BaseSetLastNTError(errCode);
298 return INVALID_SET_FILE_POINTER;
299 }
300
301 if (lpDistanceToMoveHigh != NULL)
302 {
303 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
304 }
305
306 if (FilePosition.CurrentByteOffset.u.LowPart == MAXDWORD)
307 {
308 /* The value of -1 is valid here, especially when the new
309 file position is greater than 4 GB. Since NtSetInformationFile
310 succeeded we never set an error code and we explicitly need
311 to clear a previously set error code in this case, which
312 an application will check if INVALID_SET_FILE_POINTER is returned! */
313 SetLastError(ERROR_SUCCESS);
314 }
315
316 return FilePosition.CurrentByteOffset.u.LowPart;
317 }
318
319
320 /*
321 * @implemented
322 */
323 BOOL
324 WINAPI
325 SetFilePointerEx(HANDLE hFile,
326 LARGE_INTEGER liDistanceToMove,
327 PLARGE_INTEGER lpNewFilePointer,
328 DWORD dwMoveMethod)
329 {
330 FILE_POSITION_INFORMATION FilePosition;
331 FILE_STANDARD_INFORMATION FileStandard;
332 NTSTATUS errCode;
333 IO_STATUS_BLOCK IoStatusBlock;
334
335 if(IsConsoleHandle(hFile))
336 {
337 SetLastError(ERROR_INVALID_HANDLE);
338 return FALSE;
339 }
340
341 switch(dwMoveMethod)
342 {
343 case FILE_CURRENT:
344 NtQueryInformationFile(hFile,
345 &IoStatusBlock,
346 &FilePosition,
347 sizeof(FILE_POSITION_INFORMATION),
348 FilePositionInformation);
349 FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart;
350 break;
351 case FILE_END:
352 NtQueryInformationFile(hFile,
353 &IoStatusBlock,
354 &FileStandard,
355 sizeof(FILE_STANDARD_INFORMATION),
356 FileStandardInformation);
357 FilePosition.CurrentByteOffset.QuadPart =
358 FileStandard.EndOfFile.QuadPart + liDistanceToMove.QuadPart;
359 break;
360 case FILE_BEGIN:
361 FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart;
362 break;
363 default:
364 SetLastError(ERROR_INVALID_PARAMETER);
365 return FALSE;
366 }
367
368 if(FilePosition.CurrentByteOffset.QuadPart < 0)
369 {
370 SetLastError(ERROR_NEGATIVE_SEEK);
371 return FALSE;
372 }
373
374 errCode = NtSetInformationFile(hFile,
375 &IoStatusBlock,
376 &FilePosition,
377 sizeof(FILE_POSITION_INFORMATION),
378 FilePositionInformation);
379 if (!NT_SUCCESS(errCode))
380 {
381 BaseSetLastNTError(errCode);
382 return FALSE;
383 }
384
385 if (lpNewFilePointer)
386 {
387 *lpNewFilePointer = FilePosition.CurrentByteOffset;
388 }
389 return TRUE;
390 }
391
392
393 /*
394 * @implemented
395 */
396 DWORD WINAPI
397 GetFileType(HANDLE hFile)
398 {
399 FILE_FS_DEVICE_INFORMATION DeviceInfo;
400 IO_STATUS_BLOCK StatusBlock;
401 NTSTATUS Status;
402
403 /* Get real handle */
404 hFile = TranslateStdHandle(hFile);
405
406 /* Check for console handle */
407 if (IsConsoleHandle(hFile))
408 {
409 if (VerifyConsoleIoHandle(hFile))
410 return FILE_TYPE_CHAR;
411 }
412
413 Status = NtQueryVolumeInformationFile(hFile,
414 &StatusBlock,
415 &DeviceInfo,
416 sizeof(FILE_FS_DEVICE_INFORMATION),
417 FileFsDeviceInformation);
418 if (!NT_SUCCESS(Status))
419 {
420 BaseSetLastNTError(Status);
421 return FILE_TYPE_UNKNOWN;
422 }
423
424 switch (DeviceInfo.DeviceType)
425 {
426 case FILE_DEVICE_CD_ROM:
427 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
428 case FILE_DEVICE_CONTROLLER:
429 case FILE_DEVICE_DATALINK:
430 case FILE_DEVICE_DFS:
431 case FILE_DEVICE_DISK:
432 case FILE_DEVICE_DISK_FILE_SYSTEM:
433 case FILE_DEVICE_VIRTUAL_DISK:
434 return FILE_TYPE_DISK;
435
436 case FILE_DEVICE_KEYBOARD:
437 case FILE_DEVICE_MOUSE:
438 case FILE_DEVICE_NULL:
439 case FILE_DEVICE_PARALLEL_PORT:
440 case FILE_DEVICE_PRINTER:
441 case FILE_DEVICE_SERIAL_PORT:
442 case FILE_DEVICE_SCREEN:
443 case FILE_DEVICE_SOUND:
444 case FILE_DEVICE_MODEM:
445 return FILE_TYPE_CHAR;
446
447 case FILE_DEVICE_NAMED_PIPE:
448 return FILE_TYPE_PIPE;
449 }
450
451 return FILE_TYPE_UNKNOWN;
452 }
453
454
455 /*
456 * @implemented
457 */
458 DWORD WINAPI
459 GetFileSize(HANDLE hFile,
460 LPDWORD lpFileSizeHigh)
461 {
462 NTSTATUS errCode;
463 FILE_STANDARD_INFORMATION FileStandard;
464 IO_STATUS_BLOCK IoStatusBlock;
465
466 errCode = NtQueryInformationFile(hFile,
467 &IoStatusBlock,
468 &FileStandard,
469 sizeof(FILE_STANDARD_INFORMATION),
470 FileStandardInformation);
471 if (!NT_SUCCESS(errCode))
472 {
473 BaseSetLastNTError(errCode);
474 if ( lpFileSizeHigh == NULL )
475 {
476 return -1;
477 }
478 else
479 {
480 return 0;
481 }
482 }
483 if ( lpFileSizeHigh != NULL )
484 *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
485
486 return FileStandard.EndOfFile.u.LowPart;
487 }
488
489
490 /*
491 * @implemented
492 */
493 BOOL
494 WINAPI
495 GetFileSizeEx(
496 HANDLE hFile,
497 PLARGE_INTEGER lpFileSize
498 )
499 {
500 NTSTATUS errCode;
501 FILE_STANDARD_INFORMATION FileStandard;
502 IO_STATUS_BLOCK IoStatusBlock;
503
504 errCode = NtQueryInformationFile(hFile,
505 &IoStatusBlock,
506 &FileStandard,
507 sizeof(FILE_STANDARD_INFORMATION),
508 FileStandardInformation);
509 if (!NT_SUCCESS(errCode))
510 {
511 BaseSetLastNTError(errCode);
512 return FALSE;
513 }
514 if (lpFileSize)
515 *lpFileSize = FileStandard.EndOfFile;
516
517 return TRUE;
518 }
519
520
521 /*
522 * @implemented
523 */
524 DWORD WINAPI
525 GetCompressedFileSizeA(LPCSTR lpFileName,
526 LPDWORD lpFileSizeHigh)
527 {
528 PWCHAR FileNameW;
529
530 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
531 return INVALID_FILE_SIZE;
532
533 return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
534 }
535
536
537 /*
538 * @implemented
539 */
540 DWORD WINAPI
541 GetCompressedFileSizeW(LPCWSTR lpFileName,
542 LPDWORD lpFileSizeHigh)
543 {
544 FILE_COMPRESSION_INFORMATION FileCompression;
545 NTSTATUS errCode;
546 IO_STATUS_BLOCK IoStatusBlock;
547 HANDLE hFile;
548
549 hFile = CreateFileW(lpFileName,
550 GENERIC_READ,
551 FILE_SHARE_READ,
552 NULL,
553 OPEN_EXISTING,
554 FILE_ATTRIBUTE_NORMAL,
555 NULL);
556
557 if (hFile == INVALID_HANDLE_VALUE)
558 return INVALID_FILE_SIZE;
559
560 errCode = NtQueryInformationFile(hFile,
561 &IoStatusBlock,
562 &FileCompression,
563 sizeof(FILE_COMPRESSION_INFORMATION),
564 FileCompressionInformation);
565
566 CloseHandle(hFile);
567
568 if (!NT_SUCCESS(errCode))
569 {
570 BaseSetLastNTError(errCode);
571 return INVALID_FILE_SIZE;
572 }
573
574 if(lpFileSizeHigh)
575 *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
576
577 SetLastError(NO_ERROR);
578 return FileCompression.CompressedFileSize.u.LowPart;
579 }
580
581
582 /*
583 * @implemented
584 */
585 BOOL WINAPI
586 GetFileInformationByHandle(HANDLE hFile,
587 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
588 {
589 struct
590 {
591 FILE_FS_VOLUME_INFORMATION FileFsVolume;
592 WCHAR Name[255];
593 }
594 FileFsVolume;
595
596 FILE_BASIC_INFORMATION FileBasic;
597 FILE_INTERNAL_INFORMATION FileInternal;
598 FILE_STANDARD_INFORMATION FileStandard;
599 NTSTATUS errCode;
600 IO_STATUS_BLOCK IoStatusBlock;
601
602 if(IsConsoleHandle(hFile))
603 {
604 SetLastError(ERROR_INVALID_HANDLE);
605 return FALSE;
606 }
607
608 errCode = NtQueryInformationFile(hFile,
609 &IoStatusBlock,
610 &FileBasic,
611 sizeof(FILE_BASIC_INFORMATION),
612 FileBasicInformation);
613 if (!NT_SUCCESS(errCode))
614 {
615 BaseSetLastNTError(errCode);
616 return FALSE;
617 }
618
619 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
620
621 lpFileInformation->ftCreationTime.dwHighDateTime = FileBasic.CreationTime.u.HighPart;
622 lpFileInformation->ftCreationTime.dwLowDateTime = FileBasic.CreationTime.u.LowPart;
623
624 lpFileInformation->ftLastAccessTime.dwHighDateTime = FileBasic.LastAccessTime.u.HighPart;
625 lpFileInformation->ftLastAccessTime.dwLowDateTime = FileBasic.LastAccessTime.u.LowPart;
626
627 lpFileInformation->ftLastWriteTime.dwHighDateTime = FileBasic.LastWriteTime.u.HighPart;
628 lpFileInformation->ftLastWriteTime.dwLowDateTime = FileBasic.LastWriteTime.u.LowPart;
629
630 errCode = NtQueryInformationFile(hFile,
631 &IoStatusBlock,
632 &FileInternal,
633 sizeof(FILE_INTERNAL_INFORMATION),
634 FileInternalInformation);
635 if (!NT_SUCCESS(errCode))
636 {
637 BaseSetLastNTError(errCode);
638 return FALSE;
639 }
640
641 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
642 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
643
644 errCode = NtQueryVolumeInformationFile(hFile,
645 &IoStatusBlock,
646 &FileFsVolume,
647 sizeof(FileFsVolume),
648 FileFsVolumeInformation);
649 if (!NT_SUCCESS(errCode))
650 {
651 BaseSetLastNTError(errCode);
652 return FALSE;
653 }
654
655 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
656
657 errCode = NtQueryInformationFile(hFile,
658 &IoStatusBlock,
659 &FileStandard,
660 sizeof(FILE_STANDARD_INFORMATION),
661 FileStandardInformation);
662 if (!NT_SUCCESS(errCode))
663 {
664 BaseSetLastNTError(errCode);
665 return FALSE;
666 }
667
668 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
669 lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
670 lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
671
672 return TRUE;
673 }
674
675
676 /*
677 * @implemented
678 */
679 BOOL WINAPI
680 GetFileAttributesExW(LPCWSTR lpFileName,
681 GET_FILEEX_INFO_LEVELS fInfoLevelId,
682 LPVOID lpFileInformation)
683 {
684 FILE_NETWORK_OPEN_INFORMATION FileInformation;
685 OBJECT_ATTRIBUTES ObjectAttributes;
686 UNICODE_STRING FileName;
687 NTSTATUS Status;
688 WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
689
690 TRACE("GetFileAttributesExW(%S) called\n", lpFileName);
691
692
693 if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
694 {
695 SetLastError(ERROR_INVALID_PARAMETER);
696 return FALSE;
697 }
698
699 /* Validate and translate the filename */
700 if (!RtlDosPathNameToNtPathName_U (lpFileName,
701 &FileName,
702 NULL,
703 NULL))
704 {
705 WARN ("Invalid path '%S'\n", lpFileName);
706 SetLastError (ERROR_BAD_PATHNAME);
707 return FALSE;
708 }
709
710 /* build the object attributes */
711 InitializeObjectAttributes (&ObjectAttributes,
712 &FileName,
713 OBJ_CASE_INSENSITIVE,
714 NULL,
715 NULL);
716
717 /* Get file attributes */
718 Status = NtQueryFullAttributesFile(&ObjectAttributes,
719 &FileInformation);
720
721 RtlFreeUnicodeString (&FileName);
722 if (!NT_SUCCESS (Status))
723 {
724 WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status);
725 BaseSetLastNTError (Status);
726 return FALSE;
727 }
728
729 FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation;
730 FileAttributeData->dwFileAttributes = FileInformation.FileAttributes;
731 FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart;
732 FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart;
733 FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart;
734 FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart;
735 FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart;
736 FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart;
737 FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart;
738 FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart;
739
740 return TRUE;
741 }
742
743 /*
744 * @implemented
745 */
746 BOOL WINAPI
747 GetFileAttributesExA(LPCSTR lpFileName,
748 GET_FILEEX_INFO_LEVELS fInfoLevelId,
749 LPVOID lpFileInformation)
750 {
751 PWCHAR FileNameW;
752
753 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
754 return FALSE;
755
756 return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
757 }
758
759
760 /*
761 * @implemented
762 */
763 DWORD WINAPI
764 GetFileAttributesA(LPCSTR lpFileName)
765 {
766 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
767 PWSTR FileNameW;
768 BOOL ret;
769
770 if (!lpFileName || !(FileNameW = FilenameA2W(lpFileName, FALSE)))
771 return INVALID_FILE_ATTRIBUTES;
772
773 ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
774
775 return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
776 }
777
778
779 /*
780 * @implemented
781 */
782 DWORD WINAPI
783 GetFileAttributesW(LPCWSTR lpFileName)
784 {
785 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
786 BOOL Result;
787
788 TRACE ("GetFileAttributeW(%S) called\n", lpFileName);
789
790 Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
791
792 return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
793 }
794
795
796 /*
797 * @implemented
798 */
799 BOOL WINAPI
800 GetFileAttributesByHandle(IN HANDLE hFile,
801 OUT LPDWORD dwFileAttributes,
802 IN DWORD dwFlags)
803 {
804 FILE_BASIC_INFORMATION FileBasic;
805 IO_STATUS_BLOCK IoStatusBlock;
806 NTSTATUS Status;
807
808 UNREFERENCED_PARAMETER(dwFlags);
809
810 if (IsConsoleHandle(hFile))
811 {
812 SetLastError(ERROR_INVALID_HANDLE);
813 return FALSE;
814 }
815
816 Status = NtQueryInformationFile(hFile,
817 &IoStatusBlock,
818 &FileBasic,
819 sizeof(FileBasic),
820 FileBasicInformation);
821 if (NT_SUCCESS(Status))
822 {
823 *dwFileAttributes = FileBasic.FileAttributes;
824 return TRUE;
825 }
826
827 BaseSetLastNTError(Status);
828 return FALSE;
829 }
830
831
832 /*
833 * @implemented
834 */
835 BOOL WINAPI
836 SetFileAttributesByHandle(IN HANDLE hFile,
837 IN DWORD dwFileAttributes,
838 IN DWORD dwFlags)
839 {
840 FILE_BASIC_INFORMATION FileBasic;
841 IO_STATUS_BLOCK IoStatusBlock;
842 NTSTATUS Status;
843
844 UNREFERENCED_PARAMETER(dwFlags);
845
846 if (IsConsoleHandle(hFile))
847 {
848 SetLastError(ERROR_INVALID_HANDLE);
849 return FALSE;
850 }
851
852 Status = NtQueryInformationFile(hFile,
853 &IoStatusBlock,
854 &FileBasic,
855 sizeof(FileBasic),
856 FileBasicInformation);
857 if (NT_SUCCESS(Status))
858 {
859 FileBasic.FileAttributes = dwFileAttributes;
860
861 Status = NtSetInformationFile(hFile,
862 &IoStatusBlock,
863 &FileBasic,
864 sizeof(FileBasic),
865 FileBasicInformation);
866 }
867
868 if (!NT_SUCCESS(Status))
869 {
870 BaseSetLastNTError(Status);
871 return FALSE;
872 }
873
874 return TRUE;
875 }
876
877
878 /*
879 * @implemented
880 */
881 BOOL WINAPI
882 SetFileAttributesA(
883 LPCSTR lpFileName,
884 DWORD dwFileAttributes)
885 {
886 PWCHAR FileNameW;
887
888 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
889 return FALSE;
890
891 return SetFileAttributesW(FileNameW, dwFileAttributes);
892 }
893
894
895 /*
896 * @implemented
897 */
898 BOOL WINAPI
899 SetFileAttributesW(LPCWSTR lpFileName,
900 DWORD dwFileAttributes)
901 {
902 FILE_BASIC_INFORMATION FileInformation;
903 OBJECT_ATTRIBUTES ObjectAttributes;
904 IO_STATUS_BLOCK IoStatusBlock;
905 UNICODE_STRING FileName;
906 HANDLE FileHandle;
907 NTSTATUS Status;
908
909 TRACE ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
910
911 /* Validate and translate the filename */
912 if (!RtlDosPathNameToNtPathName_U (lpFileName,
913 &FileName,
914 NULL,
915 NULL))
916 {
917 WARN ("Invalid path\n");
918 SetLastError (ERROR_BAD_PATHNAME);
919 return FALSE;
920 }
921 TRACE ("FileName: \'%wZ\'\n", &FileName);
922
923 /* build the object attributes */
924 InitializeObjectAttributes (&ObjectAttributes,
925 &FileName,
926 OBJ_CASE_INSENSITIVE,
927 NULL,
928 NULL);
929
930 /* Open the file */
931 Status = NtOpenFile (&FileHandle,
932 SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
933 &ObjectAttributes,
934 &IoStatusBlock,
935 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
936 FILE_SYNCHRONOUS_IO_NONALERT);
937 RtlFreeUnicodeString (&FileName);
938 if (!NT_SUCCESS (Status))
939 {
940 WARN ("NtOpenFile() failed (Status %lx)\n", Status);
941 BaseSetLastNTError (Status);
942 return FALSE;
943 }
944
945 Status = NtQueryInformationFile(FileHandle,
946 &IoStatusBlock,
947 &FileInformation,
948 sizeof(FILE_BASIC_INFORMATION),
949 FileBasicInformation);
950 if (!NT_SUCCESS(Status))
951 {
952 WARN ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
953 NtClose (FileHandle);
954 BaseSetLastNTError (Status);
955 return FALSE;
956 }
957
958 FileInformation.FileAttributes = dwFileAttributes;
959 Status = NtSetInformationFile(FileHandle,
960 &IoStatusBlock,
961 &FileInformation,
962 sizeof(FILE_BASIC_INFORMATION),
963 FileBasicInformation);
964 NtClose (FileHandle);
965 if (!NT_SUCCESS(Status))
966 {
967 WARN ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
968 BaseSetLastNTError (Status);
969 return FALSE;
970 }
971
972 return TRUE;
973 }
974
975 /*
976 * @implemented
977 */
978 BOOL WINAPI
979 GetFileTime(IN HANDLE hFile,
980 OUT LPFILETIME lpCreationTime OPTIONAL,
981 OUT LPFILETIME lpLastAccessTime OPTIONAL,
982 OUT LPFILETIME lpLastWriteTime OPTIONAL)
983 {
984 NTSTATUS Status;
985 IO_STATUS_BLOCK IoStatusBlock;
986 FILE_BASIC_INFORMATION FileBasic;
987
988 if(IsConsoleHandle(hFile))
989 {
990 BaseSetLastNTError(STATUS_INVALID_HANDLE);
991 return FALSE;
992 }
993
994 Status = NtQueryInformationFile(hFile,
995 &IoStatusBlock,
996 &FileBasic,
997 sizeof(FILE_BASIC_INFORMATION),
998 FileBasicInformation);
999 if (!NT_SUCCESS(Status))
1000 {
1001 BaseSetLastNTError(Status);
1002 return FALSE;
1003 }
1004
1005 if (lpCreationTime)
1006 {
1007 lpCreationTime->dwLowDateTime = FileBasic.CreationTime.LowPart;
1008 lpCreationTime->dwHighDateTime = FileBasic.CreationTime.HighPart;
1009 }
1010
1011 if (lpLastAccessTime)
1012 {
1013 lpLastAccessTime->dwLowDateTime = FileBasic.LastAccessTime.LowPart;
1014 lpLastAccessTime->dwHighDateTime = FileBasic.LastAccessTime.HighPart;
1015 }
1016
1017 if (lpLastWriteTime)
1018 {
1019 lpLastWriteTime->dwLowDateTime = FileBasic.LastWriteTime.LowPart;
1020 lpLastWriteTime->dwHighDateTime = FileBasic.LastWriteTime.HighPart;
1021 }
1022
1023 return TRUE;
1024 }
1025
1026
1027 /*
1028 * @implemented
1029 */
1030 BOOL WINAPI
1031 SetFileTime(IN HANDLE hFile,
1032 CONST FILETIME *lpCreationTime OPTIONAL,
1033 CONST FILETIME *lpLastAccessTime OPTIONAL,
1034 CONST FILETIME *lpLastWriteTime OPTIONAL)
1035 {
1036 NTSTATUS Status;
1037 IO_STATUS_BLOCK IoStatusBlock;
1038 FILE_BASIC_INFORMATION FileBasic;
1039
1040 if(IsConsoleHandle(hFile))
1041 {
1042 BaseSetLastNTError(STATUS_INVALID_HANDLE);
1043 return FALSE;
1044 }
1045
1046 memset(&FileBasic, 0, sizeof(FILE_BASIC_INFORMATION));
1047
1048 if (lpCreationTime)
1049 {
1050 FileBasic.CreationTime.LowPart = lpCreationTime->dwLowDateTime;
1051 FileBasic.CreationTime.HighPart = lpCreationTime->dwHighDateTime;
1052 }
1053
1054 if (lpLastAccessTime)
1055 {
1056 FileBasic.LastAccessTime.LowPart = lpLastAccessTime->dwLowDateTime;
1057 FileBasic.LastAccessTime.HighPart = lpLastAccessTime->dwHighDateTime;
1058 }
1059
1060 if (lpLastWriteTime)
1061 {
1062 FileBasic.LastWriteTime.LowPart = lpLastWriteTime->dwLowDateTime;
1063 FileBasic.LastWriteTime.HighPart = lpLastWriteTime->dwHighDateTime;
1064 }
1065
1066 Status = NtSetInformationFile(hFile,
1067 &IoStatusBlock,
1068 &FileBasic,
1069 sizeof(FILE_BASIC_INFORMATION),
1070 FileBasicInformation);
1071 if (!NT_SUCCESS(Status))
1072 {
1073 BaseSetLastNTError(Status);
1074 return FALSE;
1075 }
1076
1077 return TRUE;
1078 }
1079
1080
1081 /*
1082 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1083 *
1084 * @implemented
1085 */
1086 BOOL WINAPI
1087 SetEndOfFile(HANDLE hFile)
1088 {
1089 IO_STATUS_BLOCK IoStatusBlock;
1090 FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
1091 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
1092 FILE_POSITION_INFORMATION FilePosInfo;
1093 NTSTATUS Status;
1094
1095 if(IsConsoleHandle(hFile))
1096 {
1097 SetLastError(ERROR_INVALID_HANDLE);
1098 return FALSE;
1099 }
1100
1101 //get current position
1102 Status = NtQueryInformationFile(
1103 hFile,
1104 &IoStatusBlock,
1105 &FilePosInfo,
1106 sizeof(FILE_POSITION_INFORMATION),
1107 FilePositionInformation
1108 );
1109
1110 if (!NT_SUCCESS(Status)){
1111 BaseSetLastNTError(Status);
1112 return FALSE;
1113 }
1114
1115 EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1116
1117 /*
1118 NOTE:
1119 This call is not supposed to free up any space after the eof marker
1120 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1121 But...most file systems dispatch both FileEndOfFileInformation
1122 and FileAllocationInformation as they were the same command.
1123
1124 */
1125 Status = NtSetInformationFile(
1126 hFile,
1127 &IoStatusBlock, //out
1128 &EndOfFileInfo,
1129 sizeof(FILE_END_OF_FILE_INFORMATION),
1130 FileEndOfFileInformation
1131 );
1132
1133 if (!NT_SUCCESS(Status)){
1134 BaseSetLastNTError(Status);
1135 return FALSE;
1136 }
1137
1138 FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1139
1140
1141 Status = NtSetInformationFile(
1142 hFile,
1143 &IoStatusBlock, //out
1144 &FileAllocationInfo,
1145 sizeof(FILE_ALLOCATION_INFORMATION),
1146 FileAllocationInformation
1147 );
1148
1149 if (!NT_SUCCESS(Status)){
1150 BaseSetLastNTError(Status);
1151 return FALSE;
1152 }
1153
1154 return TRUE;
1155
1156 }
1157
1158
1159 /*
1160 * @implemented
1161 */
1162 BOOL
1163 WINAPI
1164 SetFileValidData(
1165 HANDLE hFile,
1166 LONGLONG ValidDataLength
1167 )
1168 {
1169 IO_STATUS_BLOCK IoStatusBlock;
1170 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
1171 NTSTATUS Status;
1172
1173 ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
1174
1175 Status = NtSetInformationFile(
1176 hFile,
1177 &IoStatusBlock, //out
1178 &ValidDataLengthInformation,
1179 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
1180 FileValidDataLengthInformation
1181 );
1182
1183 if (!NT_SUCCESS(Status)){
1184 BaseSetLastNTError(Status);
1185 return FALSE;
1186 }
1187
1188 return TRUE;
1189 }
1190
1191 /* EOF */