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