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