move from branch
[reactos.git] / reactos / dll / win32 / 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 <k32.h>
16
17 #define NDEBUG
18 #include "../include/debug.h"
19
20
21 /* GLOBALS ******************************************************************/
22
23 BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
24
25 /* FUNCTIONS ****************************************************************/
26
27
28
29 PWCHAR
30 FilenameA2W(LPCSTR NameA, BOOL alloc)
31 {
32 ANSI_STRING str;
33 UNICODE_STRING strW;
34 PUNICODE_STRING pstrW;
35 NTSTATUS Status;
36
37 //ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
38 ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer));
39
40 RtlInitAnsiString(&str, NameA);
41 pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
42
43 if (bIsFileApiAnsi)
44 Status= RtlAnsiStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc );
45 else
46 Status= RtlOemStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc );
47
48 if (NT_SUCCESS(Status))
49 return pstrW->Buffer;
50
51 if (Status== STATUS_BUFFER_OVERFLOW)
52 SetLastError( ERROR_FILENAME_EXCED_RANGE );
53 else
54 SetLastErrorByStatus(Status);
55
56 return NULL;
57 }
58
59
60 /*
61 No copy/conversion is done if the dest. buffer is too small.
62
63 Returns:
64 Success: number of TCHARS copied into dest. buffer NOT including nullterm
65 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
66 */
67 DWORD
68 FilenameU2A_FitOrFail(
69 LPSTR DestA,
70 INT destLen, /* buffer size in TCHARS incl. nullchar */
71 PUNICODE_STRING SourceU
72 )
73 {
74 DWORD ret;
75
76 ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU);
77 /* ret incl. nullchar */
78
79 if (DestA && (INT)ret <= destLen)
80 {
81 ANSI_STRING str;
82
83 str.Buffer = DestA;
84 str.MaximumLength = (USHORT)destLen;
85
86
87 if (bIsFileApiAnsi)
88 RtlUnicodeStringToAnsiString(&str, SourceU, FALSE );
89 else
90 RtlUnicodeStringToOemString(&str, SourceU, FALSE );
91
92 ret = str.Length; /* SUCCESS: length without terminating 0 */
93 }
94
95 return ret;
96 }
97
98
99 /*
100 No copy/conversion is done if the dest. buffer is too small.
101
102 Returns:
103 Success: number of TCHARS copied into dest. buffer NOT including nullterm
104 Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
105 */
106 DWORD
107 FilenameW2A_FitOrFail(
108 LPSTR DestA,
109 INT destLen, /* buffer size in TCHARS incl. nullchar */
110 LPCWSTR SourceW,
111 INT sourceLen /* buffer size in TCHARS incl. nullchar */
112 )
113 {
114 UNICODE_STRING strW;
115
116 if (sourceLen < 0) sourceLen = wcslen(SourceW) + 1;
117
118 strW.Buffer = (PWCHAR)SourceW;
119 strW.MaximumLength = sourceLen * sizeof(WCHAR);
120 strW.Length = strW.MaximumLength - sizeof(WCHAR);
121
122 return FilenameU2A_FitOrFail(DestA, destLen, &strW);
123 }
124
125
126 /*
127 Return: num. TCHARS copied into dest including nullterm
128 */
129 DWORD
130 FilenameA2W_N(
131 LPWSTR dest,
132 INT destlen, /* buffer size in TCHARS incl. nullchar */
133 LPCSTR src,
134 INT srclen /* buffer size in TCHARS incl. nullchar */
135 )
136 {
137 DWORD ret;
138
139 if (srclen < 0) srclen = strlen( src ) + 1;
140
141 if (bIsFileApiAnsi)
142 RtlMultiByteToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
143 else
144 RtlOemToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
145
146 if (ret) dest[(ret/sizeof(WCHAR))-1]=0;
147
148 return ret/sizeof(WCHAR);
149 }
150
151 /*
152 Return: num. TCHARS copied into dest including nullterm
153 */
154 DWORD
155 FilenameW2A_N(
156 LPSTR dest,
157 INT destlen, /* buffer size in TCHARS incl. nullchar */
158 LPCWSTR src,
159 INT srclen /* buffer size in TCHARS incl. nullchar */
160 )
161 {
162 DWORD ret;
163
164 if (srclen < 0) srclen = wcslen( src ) + 1;
165
166 if (bIsFileApiAnsi)
167 RtlUnicodeToMultiByteN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR));
168 else
169 RtlUnicodeToOemN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR) );
170
171 if (ret) dest[ret-1]=0;
172
173 return ret;
174 }
175
176
177 /*
178 * @implemented
179 */
180 VOID
181 STDCALL
182 SetFileApisToOEM(VOID)
183 {
184 /* Set the correct Base Api */
185 Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString;
186
187 /* FIXME: Old, deprecated way */
188 bIsFileApiAnsi = FALSE;
189 }
190
191
192 /*
193 * @implemented
194 */
195 VOID
196 STDCALL
197 SetFileApisToANSI(VOID)
198 {
199 /* Set the correct Base Api */
200 Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
201
202 /* FIXME: Old, deprecated way */
203 bIsFileApiAnsi = TRUE;
204 }
205
206
207 /*
208 * @implemented
209 */
210 BOOL STDCALL
211 AreFileApisANSI(VOID)
212 {
213 return bIsFileApiAnsi;
214 }
215
216
217 /*
218 * @implemented
219 */
220 HFILE STDCALL
221 OpenFile(LPCSTR lpFileName,
222 LPOFSTRUCT lpReOpenBuff,
223 UINT uStyle)
224 {
225 OBJECT_ATTRIBUTES ObjectAttributes;
226 IO_STATUS_BLOCK IoStatusBlock;
227 UNICODE_STRING FileNameString;
228 UNICODE_STRING FileNameU;
229 ANSI_STRING FileName;
230 WCHAR PathNameW[MAX_PATH];
231 HANDLE FileHandle = NULL;
232 NTSTATUS errCode;
233 PWCHAR FilePart;
234 ULONG Len;
235
236 DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
237
238 if (lpReOpenBuff == NULL)
239 {
240 return FALSE;
241 }
242
243 if ((uStyle & OF_CREATE) == OF_CREATE)
244 {
245 DWORD Sharing;
246 switch (uStyle & 0x70)
247 {
248 case OF_SHARE_EXCLUSIVE: Sharing = 0; break;
249 case OF_SHARE_DENY_WRITE: Sharing = FILE_SHARE_READ; break;
250 case OF_SHARE_DENY_READ: Sharing = FILE_SHARE_WRITE; break;
251 case OF_SHARE_DENY_NONE:
252 case OF_SHARE_COMPAT:
253 default:
254 Sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
255 }
256 return (HFILE) CreateFileA (lpFileName,
257 GENERIC_READ | GENERIC_WRITE,
258 Sharing,
259 NULL,
260 CREATE_ALWAYS,
261 FILE_ATTRIBUTE_NORMAL,
262 0);
263 }
264
265 RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
266
267 /* convert ansi (or oem) string to unicode */
268 if (bIsFileApiAnsi)
269 RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
270 else
271 RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
272
273 Len = SearchPathW (NULL,
274 FileNameU.Buffer,
275 NULL,
276 OFS_MAXPATHNAME,
277 PathNameW,
278 &FilePart);
279
280 RtlFreeUnicodeString(&FileNameU);
281
282 if (Len == 0 || Len > OFS_MAXPATHNAME)
283 {
284 return (HFILE)INVALID_HANDLE_VALUE;
285 }
286
287 FileName.Buffer = lpReOpenBuff->szPathName;
288 FileName.Length = 0;
289 FileName.MaximumLength = OFS_MAXPATHNAME;
290
291 RtlInitUnicodeString(&FileNameU, PathNameW);
292
293 /* convert unicode string to ansi (or oem) */
294 if (bIsFileApiAnsi)
295 RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
296 else
297 RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
298
299 if (!RtlDosPathNameToNtPathName_U (PathNameW,
300 &FileNameString,
301 NULL,
302 NULL))
303 {
304 return (HFILE)INVALID_HANDLE_VALUE;
305 }
306
307 // FILE_SHARE_READ
308 // FILE_NO_INTERMEDIATE_BUFFERING
309
310 if ((uStyle & OF_PARSE) == OF_PARSE)
311 {
312 RtlFreeHeap(RtlGetProcessHeap(),
313 0,
314 FileNameString.Buffer);
315 return (HFILE)NULL;
316 }
317
318 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
319 ObjectAttributes.RootDirectory = NULL;
320 ObjectAttributes.ObjectName = &FileNameString;
321 ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
322 ObjectAttributes.SecurityDescriptor = NULL;
323 ObjectAttributes.SecurityQualityOfService = NULL;
324
325 errCode = NtOpenFile (&FileHandle,
326 GENERIC_READ|SYNCHRONIZE,
327 &ObjectAttributes,
328 &IoStatusBlock,
329 FILE_SHARE_READ,
330 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
331
332 RtlFreeHeap(RtlGetProcessHeap(),
333 0,
334 FileNameString.Buffer);
335
336 lpReOpenBuff->nErrCode = (WORD)RtlNtStatusToDosError(errCode);
337
338 if (!NT_SUCCESS(errCode))
339 {
340 SetLastErrorByStatus (errCode);
341 return (HFILE)INVALID_HANDLE_VALUE;
342 }
343
344 return (HFILE)FileHandle;
345 }
346
347
348 /*
349 * @implemented
350 */
351 BOOL STDCALL
352 FlushFileBuffers(HANDLE hFile)
353 {
354 NTSTATUS errCode;
355 IO_STATUS_BLOCK IoStatusBlock;
356
357 if (IsConsoleHandle(hFile))
358 {
359 return FALSE;
360 }
361
362 errCode = NtFlushBuffersFile(hFile,
363 &IoStatusBlock);
364 if (!NT_SUCCESS(errCode))
365 {
366 SetLastErrorByStatus(errCode);
367 return(FALSE);
368 }
369 return(TRUE);
370 }
371
372
373 /*
374 * @implemented
375 */
376 DWORD STDCALL
377 SetFilePointer(HANDLE hFile,
378 LONG lDistanceToMove,
379 PLONG lpDistanceToMoveHigh,
380 DWORD dwMoveMethod)
381 {
382 FILE_POSITION_INFORMATION FilePosition;
383 FILE_STANDARD_INFORMATION FileStandard;
384 NTSTATUS errCode;
385 IO_STATUS_BLOCK IoStatusBlock;
386 LARGE_INTEGER Distance;
387
388 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
389 hFile,lDistanceToMove,dwMoveMethod);
390
391 if(IsConsoleHandle(hFile))
392 {
393 SetLastError(ERROR_INVALID_HANDLE);
394 return -1;
395 }
396
397 Distance.u.LowPart = lDistanceToMove;
398 if (lpDistanceToMoveHigh)
399 {
400 Distance.u.HighPart = *lpDistanceToMoveHigh;
401 }
402 else if (lDistanceToMove >= 0)
403 {
404 Distance.u.HighPart = 0;
405 }
406 else
407 {
408 Distance.u.HighPart = -1;
409 }
410
411 switch(dwMoveMethod)
412 {
413 case FILE_CURRENT:
414 NtQueryInformationFile(hFile,
415 &IoStatusBlock,
416 &FilePosition,
417 sizeof(FILE_POSITION_INFORMATION),
418 FilePositionInformation);
419 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
420 break;
421 case FILE_END:
422 NtQueryInformationFile(hFile,
423 &IoStatusBlock,
424 &FileStandard,
425 sizeof(FILE_STANDARD_INFORMATION),
426 FileStandardInformation);
427 FilePosition.CurrentByteOffset.QuadPart =
428 FileStandard.EndOfFile.QuadPart + Distance.QuadPart;
429 break;
430 case FILE_BEGIN:
431 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
432 break;
433 default:
434 SetLastError(ERROR_INVALID_PARAMETER);
435 return -1;
436 }
437
438 if(FilePosition.CurrentByteOffset.QuadPart < 0)
439 {
440 SetLastError(ERROR_NEGATIVE_SEEK);
441 return -1;
442 }
443
444 errCode = NtSetInformationFile(hFile,
445 &IoStatusBlock,
446 &FilePosition,
447 sizeof(FILE_POSITION_INFORMATION),
448 FilePositionInformation);
449 if (!NT_SUCCESS(errCode))
450 {
451 SetLastErrorByStatus(errCode);
452 return -1;
453 }
454
455 if (lpDistanceToMoveHigh != NULL)
456 {
457 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
458 }
459 return FilePosition.CurrentByteOffset.u.LowPart;
460 }
461
462
463 /*
464 * @implemented
465 */
466 BOOL
467 STDCALL
468 SetFilePointerEx(HANDLE hFile,
469 LARGE_INTEGER liDistanceToMove,
470 PLARGE_INTEGER lpNewFilePointer,
471 DWORD dwMoveMethod)
472 {
473 FILE_POSITION_INFORMATION FilePosition;
474 FILE_STANDARD_INFORMATION FileStandard;
475 NTSTATUS errCode;
476 IO_STATUS_BLOCK IoStatusBlock;
477
478 if(IsConsoleHandle(hFile))
479 {
480 SetLastError(ERROR_INVALID_HANDLE);
481 return FALSE;
482 }
483
484 switch(dwMoveMethod)
485 {
486 case FILE_CURRENT:
487 NtQueryInformationFile(hFile,
488 &IoStatusBlock,
489 &FilePosition,
490 sizeof(FILE_POSITION_INFORMATION),
491 FilePositionInformation);
492 FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart;
493 break;
494 case FILE_END:
495 NtQueryInformationFile(hFile,
496 &IoStatusBlock,
497 &FileStandard,
498 sizeof(FILE_STANDARD_INFORMATION),
499 FileStandardInformation);
500 FilePosition.CurrentByteOffset.QuadPart =
501 FileStandard.EndOfFile.QuadPart + liDistanceToMove.QuadPart;
502 break;
503 case FILE_BEGIN:
504 FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart;
505 break;
506 default:
507 SetLastError(ERROR_INVALID_PARAMETER);
508 return FALSE;
509 }
510
511 if(FilePosition.CurrentByteOffset.QuadPart < 0)
512 {
513 SetLastError(ERROR_NEGATIVE_SEEK);
514 return FALSE;
515 }
516
517 errCode = NtSetInformationFile(hFile,
518 &IoStatusBlock,
519 &FilePosition,
520 sizeof(FILE_POSITION_INFORMATION),
521 FilePositionInformation);
522 if (!NT_SUCCESS(errCode))
523 {
524 SetLastErrorByStatus(errCode);
525 return FALSE;
526 }
527
528 if (lpNewFilePointer)
529 {
530 *lpNewFilePointer = FilePosition.CurrentByteOffset;
531 }
532 return TRUE;
533 }
534
535
536 /*
537 * @implemented
538 */
539 DWORD STDCALL
540 GetFileType(HANDLE hFile)
541 {
542 FILE_FS_DEVICE_INFORMATION DeviceInfo;
543 IO_STATUS_BLOCK StatusBlock;
544 NTSTATUS Status;
545
546 /* Get real handle */
547 switch ((ULONG)hFile)
548 {
549 case STD_INPUT_HANDLE:
550 hFile = NtCurrentPeb()->ProcessParameters->StandardInput;
551 break;
552
553 case STD_OUTPUT_HANDLE:
554 hFile = NtCurrentPeb()->ProcessParameters->StandardOutput;
555 break;
556
557 case STD_ERROR_HANDLE:
558 hFile = NtCurrentPeb()->ProcessParameters->StandardError;
559 break;
560 }
561
562 /* Check for console handle */
563 if (IsConsoleHandle(hFile))
564 {
565 if (VerifyConsoleIoHandle(hFile))
566 return FILE_TYPE_CHAR;
567 }
568
569 Status = NtQueryVolumeInformationFile(hFile,
570 &StatusBlock,
571 &DeviceInfo,
572 sizeof(FILE_FS_DEVICE_INFORMATION),
573 FileFsDeviceInformation);
574 if (!NT_SUCCESS(Status))
575 {
576 SetLastErrorByStatus(Status);
577 return FILE_TYPE_UNKNOWN;
578 }
579
580 switch (DeviceInfo.DeviceType)
581 {
582 case FILE_DEVICE_CD_ROM:
583 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
584 case FILE_DEVICE_CONTROLLER:
585 case FILE_DEVICE_DATALINK:
586 case FILE_DEVICE_DFS:
587 case FILE_DEVICE_DISK:
588 case FILE_DEVICE_DISK_FILE_SYSTEM:
589 case FILE_DEVICE_VIRTUAL_DISK:
590 return FILE_TYPE_DISK;
591
592 case FILE_DEVICE_KEYBOARD:
593 case FILE_DEVICE_MOUSE:
594 case FILE_DEVICE_NULL:
595 case FILE_DEVICE_PARALLEL_PORT:
596 case FILE_DEVICE_PRINTER:
597 case FILE_DEVICE_SERIAL_PORT:
598 case FILE_DEVICE_SCREEN:
599 case FILE_DEVICE_SOUND:
600 case FILE_DEVICE_MODEM:
601 return FILE_TYPE_CHAR;
602
603 case FILE_DEVICE_NAMED_PIPE:
604 return FILE_TYPE_PIPE;
605 }
606
607 return FILE_TYPE_UNKNOWN;
608 }
609
610
611 /*
612 * @implemented
613 */
614 DWORD STDCALL
615 GetFileSize(HANDLE hFile,
616 LPDWORD lpFileSizeHigh)
617 {
618 NTSTATUS errCode;
619 FILE_STANDARD_INFORMATION FileStandard;
620 IO_STATUS_BLOCK IoStatusBlock;
621
622 errCode = NtQueryInformationFile(hFile,
623 &IoStatusBlock,
624 &FileStandard,
625 sizeof(FILE_STANDARD_INFORMATION),
626 FileStandardInformation);
627 if (!NT_SUCCESS(errCode))
628 {
629 SetLastErrorByStatus(errCode);
630 if ( lpFileSizeHigh == NULL )
631 {
632 return -1;
633 }
634 else
635 {
636 return 0;
637 }
638 }
639 if ( lpFileSizeHigh != NULL )
640 *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
641
642 return FileStandard.EndOfFile.u.LowPart;
643 }
644
645
646 /*
647 * @implemented
648 */
649 BOOL
650 STDCALL
651 GetFileSizeEx(
652 HANDLE hFile,
653 PLARGE_INTEGER lpFileSize
654 )
655 {
656 NTSTATUS errCode;
657 FILE_STANDARD_INFORMATION FileStandard;
658 IO_STATUS_BLOCK IoStatusBlock;
659
660 errCode = NtQueryInformationFile(hFile,
661 &IoStatusBlock,
662 &FileStandard,
663 sizeof(FILE_STANDARD_INFORMATION),
664 FileStandardInformation);
665 if (!NT_SUCCESS(errCode))
666 {
667 SetLastErrorByStatus(errCode);
668 return FALSE;
669 }
670 if (lpFileSize)
671 *lpFileSize = FileStandard.EndOfFile;
672
673 return TRUE;
674 }
675
676
677 /*
678 * @implemented
679 */
680 DWORD STDCALL
681 GetCompressedFileSizeA(LPCSTR lpFileName,
682 LPDWORD lpFileSizeHigh)
683 {
684 PWCHAR FileNameW;
685
686 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
687 return INVALID_FILE_SIZE;
688
689 return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
690 }
691
692
693 /*
694 * @implemented
695 */
696 DWORD STDCALL
697 GetCompressedFileSizeW(LPCWSTR lpFileName,
698 LPDWORD lpFileSizeHigh)
699 {
700 FILE_COMPRESSION_INFORMATION FileCompression;
701 NTSTATUS errCode;
702 IO_STATUS_BLOCK IoStatusBlock;
703 HANDLE hFile;
704
705 hFile = CreateFileW(lpFileName,
706 GENERIC_READ,
707 FILE_SHARE_READ,
708 NULL,
709 OPEN_EXISTING,
710 FILE_ATTRIBUTE_NORMAL,
711 NULL);
712
713 if (hFile == INVALID_HANDLE_VALUE)
714 return INVALID_FILE_SIZE;
715
716 errCode = NtQueryInformationFile(hFile,
717 &IoStatusBlock,
718 &FileCompression,
719 sizeof(FILE_COMPRESSION_INFORMATION),
720 FileCompressionInformation);
721
722 CloseHandle(hFile);
723
724 if (!NT_SUCCESS(errCode))
725 {
726 SetLastErrorByStatus(errCode);
727 return INVALID_FILE_SIZE;
728 }
729
730 if(lpFileSizeHigh)
731 *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
732
733 SetLastError(NO_ERROR);
734 return FileCompression.CompressedFileSize.u.LowPart;
735 }
736
737
738 /*
739 * @implemented
740 */
741 BOOL STDCALL
742 GetFileInformationByHandle(HANDLE hFile,
743 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
744 {
745 struct
746 {
747 FILE_FS_VOLUME_INFORMATION FileFsVolume;
748 WCHAR Name[255];
749 }
750 FileFsVolume;
751
752 FILE_BASIC_INFORMATION FileBasic;
753 FILE_INTERNAL_INFORMATION FileInternal;
754 FILE_STANDARD_INFORMATION FileStandard;
755 NTSTATUS errCode;
756 IO_STATUS_BLOCK IoStatusBlock;
757
758 if(IsConsoleHandle(hFile))
759 {
760 SetLastError(ERROR_INVALID_HANDLE);
761 return FALSE;
762 }
763
764 errCode = NtQueryInformationFile(hFile,
765 &IoStatusBlock,
766 &FileBasic,
767 sizeof(FILE_BASIC_INFORMATION),
768 FileBasicInformation);
769 if (!NT_SUCCESS(errCode))
770 {
771 SetLastErrorByStatus(errCode);
772 return FALSE;
773 }
774
775 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
776
777 lpFileInformation->ftCreationTime.dwHighDateTime = FileBasic.CreationTime.u.HighPart;
778 lpFileInformation->ftCreationTime.dwLowDateTime = FileBasic.CreationTime.u.LowPart;
779
780 lpFileInformation->ftLastAccessTime.dwHighDateTime = FileBasic.LastAccessTime.u.HighPart;
781 lpFileInformation->ftLastAccessTime.dwLowDateTime = FileBasic.LastAccessTime.u.LowPart;
782
783 lpFileInformation->ftLastWriteTime.dwHighDateTime = FileBasic.LastWriteTime.u.HighPart;
784 lpFileInformation->ftLastWriteTime.dwLowDateTime = FileBasic.LastWriteTime.u.LowPart;
785
786 errCode = NtQueryInformationFile(hFile,
787 &IoStatusBlock,
788 &FileInternal,
789 sizeof(FILE_INTERNAL_INFORMATION),
790 FileInternalInformation);
791 if (!NT_SUCCESS(errCode))
792 {
793 SetLastErrorByStatus(errCode);
794 return FALSE;
795 }
796
797 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
798 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
799
800 errCode = NtQueryVolumeInformationFile(hFile,
801 &IoStatusBlock,
802 &FileFsVolume,
803 sizeof(FileFsVolume),
804 FileFsVolumeInformation);
805 if (!NT_SUCCESS(errCode))
806 {
807 SetLastErrorByStatus(errCode);
808 return FALSE;
809 }
810
811 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
812
813 errCode = NtQueryInformationFile(hFile,
814 &IoStatusBlock,
815 &FileStandard,
816 sizeof(FILE_STANDARD_INFORMATION),
817 FileStandardInformation);
818 if (!NT_SUCCESS(errCode))
819 {
820 SetLastErrorByStatus(errCode);
821 return FALSE;
822 }
823
824 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
825 lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
826 lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
827
828 return TRUE;
829 }
830
831
832 /*
833 * @implemented
834 */
835 BOOL STDCALL
836 GetFileAttributesExW(LPCWSTR lpFileName,
837 GET_FILEEX_INFO_LEVELS fInfoLevelId,
838 LPVOID lpFileInformation)
839 {
840 FILE_NETWORK_OPEN_INFORMATION FileInformation;
841 OBJECT_ATTRIBUTES ObjectAttributes;
842 UNICODE_STRING FileName;
843 NTSTATUS Status;
844 WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
845
846 DPRINT("GetFileAttributesExW(%S) called\n", lpFileName);
847
848
849 if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
850 {
851 SetLastError(ERROR_INVALID_PARAMETER);
852 return FALSE;
853 }
854
855 /* Validate and translate the filename */
856 if (!RtlDosPathNameToNtPathName_U (lpFileName,
857 &FileName,
858 NULL,
859 NULL))
860 {
861 DPRINT1 ("Invalid path\n");
862 SetLastError (ERROR_BAD_PATHNAME);
863 return FALSE;
864 }
865
866 /* build the object attributes */
867 InitializeObjectAttributes (&ObjectAttributes,
868 &FileName,
869 OBJ_CASE_INSENSITIVE,
870 NULL,
871 NULL);
872
873 /* Get file attributes */
874 Status = NtQueryFullAttributesFile(&ObjectAttributes,
875 &FileInformation);
876
877 RtlFreeUnicodeString (&FileName);
878 if (!NT_SUCCESS (Status))
879 {
880 DPRINT ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status);
881 SetLastErrorByStatus (Status);
882 return FALSE;
883 }
884
885 FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation;
886 FileAttributeData->dwFileAttributes = FileInformation.FileAttributes;
887 FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart;
888 FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart;
889 FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart;
890 FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart;
891 FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart;
892 FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart;
893 FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart;
894 FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart;
895
896 return TRUE;
897 }
898
899 /*
900 * @implemented
901 */
902 BOOL STDCALL
903 GetFileAttributesExA(LPCSTR lpFileName,
904 GET_FILEEX_INFO_LEVELS fInfoLevelId,
905 LPVOID lpFileInformation)
906 {
907 PWCHAR FileNameW;
908
909 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
910 return FALSE;
911
912 return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
913 }
914
915
916 /*
917 * @implemented
918 */
919 DWORD STDCALL
920 GetFileAttributesA(LPCSTR lpFileName)
921 {
922 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
923 PWSTR FileNameW;
924 BOOL ret;
925
926 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
927 return INVALID_FILE_ATTRIBUTES;
928
929 ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
930
931 return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
932 }
933
934
935 /*
936 * @implemented
937 */
938 DWORD STDCALL
939 GetFileAttributesW(LPCWSTR lpFileName)
940 {
941 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
942 BOOL Result;
943
944 DPRINT ("GetFileAttributeW(%S) called\n", lpFileName);
945
946 Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
947
948 return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
949 }
950
951
952 /*
953 * @implemented
954 */
955 BOOL STDCALL
956 GetFileAttributesByHandle(IN HANDLE hFile,
957 OUT LPDWORD dwFileAttributes,
958 IN DWORD dwFlags)
959 {
960 FILE_BASIC_INFORMATION FileBasic;
961 IO_STATUS_BLOCK IoStatusBlock;
962 NTSTATUS Status;
963
964 UNREFERENCED_PARAMETER(dwFlags);
965
966 if (IsConsoleHandle(hFile))
967 {
968 SetLastError(ERROR_INVALID_HANDLE);
969 return FALSE;
970 }
971
972 Status = NtQueryInformationFile(hFile,
973 &IoStatusBlock,
974 &FileBasic,
975 sizeof(FileBasic),
976 FileBasicInformation);
977 if (NT_SUCCESS(Status))
978 {
979 *dwFileAttributes = FileBasic.FileAttributes;
980 return TRUE;
981 }
982
983 SetLastErrorByStatus(Status);
984 return FALSE;
985 }
986
987
988 /*
989 * @implemented
990 */
991 BOOL STDCALL
992 SetFileAttributesByHandle(IN HANDLE hFile,
993 IN DWORD dwFileAttributes,
994 IN DWORD dwFlags)
995 {
996 FILE_BASIC_INFORMATION FileBasic;
997 IO_STATUS_BLOCK IoStatusBlock;
998 NTSTATUS Status;
999
1000 UNREFERENCED_PARAMETER(dwFlags);
1001
1002 if (IsConsoleHandle(hFile))
1003 {
1004 SetLastError(ERROR_INVALID_HANDLE);
1005 return FALSE;
1006 }
1007
1008 Status = NtQueryInformationFile(hFile,
1009 &IoStatusBlock,
1010 &FileBasic,
1011 sizeof(FileBasic),
1012 FileBasicInformation);
1013 if (NT_SUCCESS(Status))
1014 {
1015 FileBasic.FileAttributes = dwFileAttributes;
1016
1017 Status = NtSetInformationFile(hFile,
1018 &IoStatusBlock,
1019 &FileBasic,
1020 sizeof(FileBasic),
1021 FileBasicInformation);
1022 }
1023
1024 if (!NT_SUCCESS(Status))
1025 {
1026 SetLastErrorByStatus(Status);
1027 return FALSE;
1028 }
1029
1030 return TRUE;
1031 }
1032
1033
1034 /*
1035 * @implemented
1036 */
1037 BOOL STDCALL
1038 SetFileAttributesA(
1039 LPCSTR lpFileName,
1040 DWORD dwFileAttributes)
1041 {
1042 PWCHAR FileNameW;
1043
1044 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
1045 return FALSE;
1046
1047 return SetFileAttributesW(FileNameW, dwFileAttributes);
1048 }
1049
1050
1051 /*
1052 * @implemented
1053 */
1054 BOOL STDCALL
1055 SetFileAttributesW(LPCWSTR lpFileName,
1056 DWORD dwFileAttributes)
1057 {
1058 FILE_BASIC_INFORMATION FileInformation;
1059 OBJECT_ATTRIBUTES ObjectAttributes;
1060 IO_STATUS_BLOCK IoStatusBlock;
1061 UNICODE_STRING FileName;
1062 HANDLE FileHandle;
1063 NTSTATUS Status;
1064
1065 DPRINT ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
1066
1067 /* Validate and translate the filename */
1068 if (!RtlDosPathNameToNtPathName_U (lpFileName,
1069 &FileName,
1070 NULL,
1071 NULL))
1072 {
1073 DPRINT ("Invalid path\n");
1074 SetLastError (ERROR_BAD_PATHNAME);
1075 return FALSE;
1076 }
1077 DPRINT ("FileName: \'%wZ\'\n", &FileName);
1078
1079 /* build the object attributes */
1080 InitializeObjectAttributes (&ObjectAttributes,
1081 &FileName,
1082 OBJ_CASE_INSENSITIVE,
1083 NULL,
1084 NULL);
1085
1086 /* Open the file */
1087 Status = NtOpenFile (&FileHandle,
1088 SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
1089 &ObjectAttributes,
1090 &IoStatusBlock,
1091 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1092 FILE_SYNCHRONOUS_IO_NONALERT);
1093 RtlFreeUnicodeString (&FileName);
1094 if (!NT_SUCCESS (Status))
1095 {
1096 DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
1097 SetLastErrorByStatus (Status);
1098 return FALSE;
1099 }
1100
1101 Status = NtQueryInformationFile(FileHandle,
1102 &IoStatusBlock,
1103 &FileInformation,
1104 sizeof(FILE_BASIC_INFORMATION),
1105 FileBasicInformation);
1106 if (!NT_SUCCESS(Status))
1107 {
1108 DPRINT ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
1109 NtClose (FileHandle);
1110 SetLastErrorByStatus (Status);
1111 return FALSE;
1112 }
1113
1114 FileInformation.FileAttributes = dwFileAttributes;
1115 Status = NtSetInformationFile(FileHandle,
1116 &IoStatusBlock,
1117 &FileInformation,
1118 sizeof(FILE_BASIC_INFORMATION),
1119 FileBasicInformation);
1120 NtClose (FileHandle);
1121 if (!NT_SUCCESS(Status))
1122 {
1123 DPRINT ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
1124 SetLastErrorByStatus (Status);
1125 return FALSE;
1126 }
1127
1128 return TRUE;
1129 }
1130
1131
1132
1133
1134 /***********************************************************************
1135 * GetTempFileNameA (KERNEL32.@)
1136 */
1137 UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
1138 {
1139 WCHAR BufferW[MAX_PATH];
1140 PWCHAR PathW;
1141 WCHAR PrefixW[3+1];
1142 UINT ret;
1143
1144 if (!(PathW = FilenameA2W(path, FALSE)))
1145 return 0;
1146
1147 if (prefix)
1148 FilenameA2W_N(PrefixW, 3+1, prefix, -1);
1149
1150 ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
1151
1152 if (ret)
1153 FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
1154
1155 return ret;
1156 }
1157
1158 /***********************************************************************
1159 * GetTempFileNameW (KERNEL32.@)
1160 */
1161 UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer )
1162 {
1163 static const WCHAR formatW[] = L"%x.tmp";
1164
1165 int i;
1166 LPWSTR p;
1167
1168 if ( !path || !prefix || !buffer )
1169 {
1170 SetLastError( ERROR_INVALID_PARAMETER );
1171 return 0;
1172 }
1173
1174 wcscpy( buffer, path );
1175 p = buffer + wcslen(buffer);
1176
1177 /* add a \, if there isn't one */
1178 if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
1179
1180 for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
1181
1182 unique &= 0xffff;
1183
1184 if (unique) swprintf( p, formatW, unique );
1185 else
1186 {
1187 /* get a "random" unique number and try to create the file */
1188 HANDLE handle;
1189 UINT num = GetTickCount() & 0xffff;
1190
1191 if (!num) num = 1;
1192 unique = num;
1193 do
1194 {
1195 swprintf( p, formatW, unique );
1196 handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
1197 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1198 if (handle != INVALID_HANDLE_VALUE)
1199 { /* We created it */
1200 DPRINT("created %S\n", buffer);
1201 CloseHandle( handle );
1202 break;
1203 }
1204 if (GetLastError() != ERROR_FILE_EXISTS &&
1205 GetLastError() != ERROR_SHARING_VIOLATION)
1206 break; /* No need to go on */
1207 if (!(++unique & 0xffff)) unique = 1;
1208 } while (unique != num);
1209 }
1210
1211 DPRINT("returning %S\n", buffer);
1212 return unique;
1213 }
1214
1215
1216
1217
1218
1219 /*
1220 * @implemented
1221 */
1222 BOOL STDCALL
1223 GetFileTime(HANDLE hFile,
1224 LPFILETIME lpCreationTime,
1225 LPFILETIME lpLastAccessTime,
1226 LPFILETIME lpLastWriteTime)
1227 {
1228 IO_STATUS_BLOCK IoStatusBlock;
1229 FILE_BASIC_INFORMATION FileBasic;
1230 NTSTATUS Status;
1231
1232 if(IsConsoleHandle(hFile))
1233 {
1234 SetLastError(ERROR_INVALID_HANDLE);
1235 return FALSE;
1236 }
1237
1238 Status = NtQueryInformationFile(hFile,
1239 &IoStatusBlock,
1240 &FileBasic,
1241 sizeof(FILE_BASIC_INFORMATION),
1242 FileBasicInformation);
1243 if (!NT_SUCCESS(Status))
1244 {
1245 SetLastErrorByStatus(Status);
1246 return FALSE;
1247 }
1248
1249 if (lpCreationTime)
1250 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
1251 if (lpLastAccessTime)
1252 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
1253 if (lpLastWriteTime)
1254 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
1255
1256 return TRUE;
1257 }
1258
1259
1260 /*
1261 * @implemented
1262 */
1263 BOOL STDCALL
1264 SetFileTime(HANDLE hFile,
1265 CONST FILETIME *lpCreationTime,
1266 CONST FILETIME *lpLastAccessTime,
1267 CONST FILETIME *lpLastWriteTime)
1268 {
1269 FILE_BASIC_INFORMATION FileBasic;
1270 IO_STATUS_BLOCK IoStatusBlock;
1271 NTSTATUS Status;
1272
1273 if(IsConsoleHandle(hFile))
1274 {
1275 SetLastError(ERROR_INVALID_HANDLE);
1276 return FALSE;
1277 }
1278
1279 Status = NtQueryInformationFile(hFile,
1280 &IoStatusBlock,
1281 &FileBasic,
1282 sizeof(FILE_BASIC_INFORMATION),
1283 FileBasicInformation);
1284 if (!NT_SUCCESS(Status))
1285 {
1286 SetLastErrorByStatus(Status);
1287 return FALSE;
1288 }
1289
1290 if (lpCreationTime)
1291 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
1292 if (lpLastAccessTime)
1293 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
1294 if (lpLastWriteTime)
1295 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
1296
1297 // should i initialize changetime ???
1298
1299 Status = NtSetInformationFile(hFile,
1300 &IoStatusBlock,
1301 &FileBasic,
1302 sizeof(FILE_BASIC_INFORMATION),
1303 FileBasicInformation);
1304 if (!NT_SUCCESS(Status))
1305 {
1306 SetLastErrorByStatus(Status);
1307 return FALSE;
1308 }
1309
1310 return TRUE;
1311 }
1312
1313
1314 /*
1315 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1316 *
1317 * @implemented
1318 */
1319 BOOL STDCALL
1320 SetEndOfFile(HANDLE hFile)
1321 {
1322 IO_STATUS_BLOCK IoStatusBlock;
1323 FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
1324 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
1325 FILE_POSITION_INFORMATION FilePosInfo;
1326 NTSTATUS Status;
1327
1328 if(IsConsoleHandle(hFile))
1329 {
1330 SetLastError(ERROR_INVALID_HANDLE);
1331 return FALSE;
1332 }
1333
1334 //get current position
1335 Status = NtQueryInformationFile(
1336 hFile,
1337 &IoStatusBlock,
1338 &FilePosInfo,
1339 sizeof(FILE_POSITION_INFORMATION),
1340 FilePositionInformation
1341 );
1342
1343 if (!NT_SUCCESS(Status)){
1344 SetLastErrorByStatus(Status);
1345 return FALSE;
1346 }
1347
1348 EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1349
1350 /*
1351 NOTE:
1352 This call is not supposed to free up any space after the eof marker
1353 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1354 But...most file systems dispatch both FileEndOfFileInformation
1355 and FileAllocationInformation as they were the same command.
1356
1357 */
1358 Status = NtSetInformationFile(
1359 hFile,
1360 &IoStatusBlock, //out
1361 &EndOfFileInfo,
1362 sizeof(FILE_END_OF_FILE_INFORMATION),
1363 FileEndOfFileInformation
1364 );
1365
1366 if (!NT_SUCCESS(Status)){
1367 SetLastErrorByStatus(Status);
1368 return FALSE;
1369 }
1370
1371 FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1372
1373
1374 Status = NtSetInformationFile(
1375 hFile,
1376 &IoStatusBlock, //out
1377 &FileAllocationInfo,
1378 sizeof(FILE_ALLOCATION_INFORMATION),
1379 FileAllocationInformation
1380 );
1381
1382 if (!NT_SUCCESS(Status)){
1383 SetLastErrorByStatus(Status);
1384 return FALSE;
1385 }
1386
1387 return TRUE;
1388
1389 }
1390
1391
1392 /*
1393 * @implemented
1394 */
1395 BOOL
1396 STDCALL
1397 SetFileValidData(
1398 HANDLE hFile,
1399 LONGLONG ValidDataLength
1400 )
1401 {
1402 IO_STATUS_BLOCK IoStatusBlock;
1403 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
1404 NTSTATUS Status;
1405
1406 ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
1407
1408 Status = NtSetInformationFile(
1409 hFile,
1410 &IoStatusBlock, //out
1411 &ValidDataLengthInformation,
1412 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
1413 FileValidDataLengthInformation
1414 );
1415
1416 if (!NT_SUCCESS(Status)){
1417 SetLastErrorByStatus(Status);
1418 return FALSE;
1419 }
1420
1421 return TRUE;
1422 }
1423
1424
1425
1426 /*
1427 * @implemented
1428 */
1429 BOOL
1430 STDCALL
1431 SetFileShortNameW(
1432 HANDLE hFile,
1433 LPCWSTR lpShortName)
1434 {
1435 NTSTATUS Status;
1436 ULONG NeededSize;
1437 UNICODE_STRING ShortName;
1438 IO_STATUS_BLOCK IoStatusBlock;
1439 PFILE_NAME_INFORMATION FileNameInfo;
1440
1441 if(IsConsoleHandle(hFile))
1442 {
1443 SetLastError(ERROR_INVALID_HANDLE);
1444 return FALSE;
1445 }
1446
1447 if(!lpShortName)
1448 {
1449 SetLastError(ERROR_INVALID_PARAMETER);
1450 return FALSE;
1451 }
1452
1453 RtlInitUnicodeString(&ShortName, lpShortName);
1454
1455 NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR);
1456 if(!(FileNameInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize)))
1457 {
1458 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1459 return FALSE;
1460 }
1461
1462 FileNameInfo->FileNameLength = ShortName.Length;
1463 RtlCopyMemory(FileNameInfo->FileName, ShortName.Buffer, ShortName.Length);
1464
1465 Status = NtSetInformationFile(hFile,
1466 &IoStatusBlock, //out
1467 FileNameInfo,
1468 NeededSize,
1469 FileShortNameInformation);
1470
1471 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo);
1472 if(!NT_SUCCESS(Status))
1473 {
1474 SetLastErrorByStatus(Status);
1475 return FALSE;
1476 }
1477
1478 return TRUE;
1479 }
1480
1481
1482 /*
1483 * @implemented
1484 */
1485 BOOL
1486 STDCALL
1487 SetFileShortNameA(
1488 HANDLE hFile,
1489 LPCSTR lpShortName
1490 )
1491 {
1492 PWCHAR ShortNameW;
1493
1494 if(IsConsoleHandle(hFile))
1495 {
1496 SetLastError(ERROR_INVALID_HANDLE);
1497 return FALSE;
1498 }
1499
1500 if(!lpShortName)
1501 {
1502 SetLastError(ERROR_INVALID_PARAMETER);
1503 return FALSE;
1504 }
1505
1506 if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
1507 return FALSE;
1508
1509 return SetFileShortNameW(hFile, ShortNameW);
1510 }
1511
1512
1513 /*
1514 * @implemented
1515 */
1516 BOOL
1517 STDCALL
1518 CheckNameLegalDOS8Dot3W(
1519 LPCWSTR lpName,
1520 LPSTR lpOemName OPTIONAL,
1521 DWORD OemNameSize OPTIONAL,
1522 PBOOL pbNameContainsSpaces OPTIONAL,
1523 PBOOL pbNameLegal
1524 )
1525 {
1526 UNICODE_STRING Name;
1527 ANSI_STRING AnsiName;
1528
1529 if(lpName == NULL ||
1530 (lpOemName == NULL && OemNameSize != 0) ||
1531 pbNameLegal == NULL)
1532 {
1533 SetLastError(ERROR_INVALID_PARAMETER);
1534 return FALSE;
1535 }
1536
1537 if(lpOemName != NULL)
1538 {
1539 AnsiName.Buffer = lpOemName;
1540 AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
1541 AnsiName.Length = 0;
1542 }
1543
1544 RtlInitUnicodeString(&Name, lpName);
1545
1546 *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
1547 (lpOemName ? &AnsiName : NULL),
1548 (BOOLEAN*)pbNameContainsSpaces);
1549
1550 return TRUE;
1551 }
1552
1553
1554 /*
1555 * @implemented
1556 */
1557 BOOL
1558 STDCALL
1559 CheckNameLegalDOS8Dot3A(
1560 LPCSTR lpName,
1561 LPSTR lpOemName OPTIONAL,
1562 DWORD OemNameSize OPTIONAL,
1563 PBOOL pbNameContainsSpaces OPTIONAL,
1564 PBOOL pbNameLegal
1565 )
1566 {
1567 UNICODE_STRING Name;
1568 ANSI_STRING AnsiName, AnsiInputName;
1569 NTSTATUS Status;
1570
1571 if(lpName == NULL ||
1572 (lpOemName == NULL && OemNameSize != 0) ||
1573 pbNameLegal == NULL)
1574 {
1575 SetLastError(ERROR_INVALID_PARAMETER);
1576 return FALSE;
1577 }
1578
1579 if(lpOemName != NULL)
1580 {
1581 AnsiName.Buffer = lpOemName;
1582 AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
1583 AnsiName.Length = 0;
1584 }
1585
1586 RtlInitAnsiString(&AnsiInputName, (LPSTR)lpName);
1587 if(bIsFileApiAnsi)
1588 Status = RtlAnsiStringToUnicodeString(&Name, &AnsiInputName, TRUE);
1589 else
1590 Status = RtlOemStringToUnicodeString(&Name, &AnsiInputName, TRUE);
1591
1592 if(!NT_SUCCESS(Status))
1593 {
1594 SetLastErrorByStatus(Status);
1595 return FALSE;
1596 }
1597
1598 *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
1599 (lpOemName ? &AnsiName : NULL),
1600 (BOOLEAN*)pbNameContainsSpaces);
1601
1602 RtlFreeUnicodeString(&Name);
1603
1604 return TRUE;
1605 }
1606
1607
1608 /*
1609 * @implemented
1610 */
1611 DWORD
1612 WINAPI
1613 GetFinalPathNameByHandleA(IN HANDLE hFile,
1614 OUT LPSTR lpszFilePath,
1615 IN DWORD cchFilePath,
1616 IN DWORD dwFlags)
1617 {
1618 WCHAR FilePathW[MAX_PATH];
1619 UNICODE_STRING FilePathU;
1620 DWORD PrevLastError;
1621 DWORD Ret = 0;
1622
1623 if (cchFilePath != 0 &&
1624 cchFilePath > sizeof(FilePathW) / sizeof(FilePathW[0]))
1625 {
1626 FilePathU.Length = 0;
1627 FilePathU.MaximumLength = (USHORT)cchFilePath * sizeof(WCHAR);
1628 FilePathU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
1629 0,
1630 FilePathU.MaximumLength);
1631 if (FilePathU.Buffer == NULL)
1632 {
1633 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1634 return 0;
1635 }
1636 }
1637 else
1638 {
1639 FilePathU.Length = 0;
1640 FilePathU.MaximumLength = sizeof(FilePathW);
1641 FilePathU.Buffer = FilePathW;
1642 }
1643
1644 /* save the last error code */
1645 PrevLastError = GetLastError();
1646 SetLastError(ERROR_SUCCESS);
1647
1648 /* call the unicode version that does all the work */
1649 Ret = GetFinalPathNameByHandleW(hFile,
1650 FilePathU.Buffer,
1651 cchFilePath,
1652 dwFlags);
1653
1654 if (GetLastError() == ERROR_SUCCESS)
1655 {
1656 /* no error, restore the last error code and convert the string */
1657 SetLastError(PrevLastError);
1658
1659 Ret = FilenameU2A_FitOrFail(lpszFilePath,
1660 cchFilePath,
1661 &FilePathU);
1662 }
1663
1664 /* free allocated memory if necessary */
1665 if (FilePathU.Buffer != FilePathW)
1666 {
1667 RtlFreeHeap(RtlGetProcessHeap(),
1668 0,
1669 FilePathU.Buffer);
1670 }
1671
1672 return Ret;
1673 }
1674
1675
1676 /*
1677 * @unimplemented
1678 */
1679 DWORD
1680 WINAPI
1681 GetFinalPathNameByHandleW(IN HANDLE hFile,
1682 OUT LPWSTR lpszFilePath,
1683 IN DWORD cchFilePath,
1684 IN DWORD dwFlags)
1685 {
1686 if (dwFlags & ~(VOLUME_NAME_DOS | VOLUME_NAME_GUID | VOLUME_NAME_NT |
1687 VOLUME_NAME_NONE | FILE_NAME_NORMALIZED | FILE_NAME_OPENED))
1688 {
1689 SetLastError(ERROR_INVALID_PARAMETER);
1690 return 0;
1691 }
1692
1693 UNIMPLEMENTED;
1694 return 0;
1695 }
1696
1697
1698 /*
1699 * @unimplemented
1700 */
1701 BOOL
1702 WINAPI
1703 SetFileBandwidthReservation(IN HANDLE hFile,
1704 IN DWORD nPeriodMilliseconds,
1705 IN DWORD nBytesPerPeriod,
1706 IN BOOL bDiscardable,
1707 OUT LPDWORD lpTransferSize,
1708 OUT LPDWORD lpNumOutstandingRequests)
1709 {
1710 UNIMPLEMENTED;
1711 return FALSE;
1712 }
1713
1714
1715 /*
1716 * @unimplemented
1717 */
1718 BOOL
1719 WINAPI
1720 GetFileBandwidthReservation(IN HANDLE hFile,
1721 OUT LPDWORD lpPeriodMilliseconds,
1722 OUT LPDWORD lpBytesPerPeriod,
1723 OUT LPBOOL pDiscardable,
1724 OUT LPDWORD lpTransferSize,
1725 OUT LPDWORD lpNumOutstandingRequests)
1726 {
1727 UNIMPLEMENTED;
1728 return FALSE;
1729 }
1730
1731
1732 /*
1733 * @unimplemented
1734 */
1735 BOOL
1736 WINAPI
1737 SetFileCompletionNotificationModes(IN HANDLE FileHandle,
1738 IN UCHAR Flags)
1739 {
1740 if (Flags & ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS | FILE_SKIP_SET_EVENT_ON_HANDLE))
1741 {
1742 SetLastError(ERROR_INVALID_PARAMETER);
1743 return FALSE;
1744 }
1745
1746 UNIMPLEMENTED;
1747 return FALSE;
1748 }
1749
1750
1751 /*
1752 * @unimplemented
1753 */
1754 HANDLE
1755 WINAPI
1756 OpenFileById(IN HANDLE hFile,
1757 IN LPFILE_ID_DESCRIPTOR lpFileID,
1758 IN DWORD dwDesiredAccess,
1759 IN DWORD dwShareMode,
1760 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
1761 IN DWORD dwFlags)
1762 {
1763 UNIMPLEMENTED;
1764 return INVALID_HANDLE_VALUE;
1765 }
1766
1767 /* EOF */