Bring back ext2 code 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 <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 if (lpDistanceToMoveHigh)
398 {
399 Distance.u.HighPart = *lpDistanceToMoveHigh;
400 Distance.u.LowPart = lDistanceToMove;
401 }
402 else
403 {
404 Distance.QuadPart = lDistanceToMove;
405 }
406
407 switch(dwMoveMethod)
408 {
409 case FILE_CURRENT:
410 NtQueryInformationFile(hFile,
411 &IoStatusBlock,
412 &FilePosition,
413 sizeof(FILE_POSITION_INFORMATION),
414 FilePositionInformation);
415 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
416 break;
417 case FILE_END:
418 NtQueryInformationFile(hFile,
419 &IoStatusBlock,
420 &FileStandard,
421 sizeof(FILE_STANDARD_INFORMATION),
422 FileStandardInformation);
423 FilePosition.CurrentByteOffset.QuadPart =
424 FileStandard.EndOfFile.QuadPart + Distance.QuadPart;
425 break;
426 case FILE_BEGIN:
427 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
428 break;
429 default:
430 SetLastError(ERROR_INVALID_PARAMETER);
431 return -1;
432 }
433
434 if(FilePosition.CurrentByteOffset.QuadPart < 0)
435 {
436 SetLastError(ERROR_NEGATIVE_SEEK);
437 return -1;
438 }
439
440 if (lpDistanceToMoveHigh == NULL && FilePosition.CurrentByteOffset.HighPart != 0)
441 {
442 /* If we're moving the pointer outside of the 32 bit boundaries but
443 the application only passed a 32 bit value we need to bail out! */
444 SetLastError(ERROR_INVALID_PARAMETER);
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 if (lpDistanceToMoveHigh != NULL)
456 *lpDistanceToMoveHigh = -1;
457
458 SetLastErrorByStatus(errCode);
459 return -1;
460 }
461
462 if (lpDistanceToMoveHigh != NULL)
463 {
464 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
465 }
466
467 if (FilePosition.CurrentByteOffset.u.LowPart == -1)
468 {
469 /* The value of -1 is valid here, especially when the new
470 file position is greater than 4 GB. Since NtSetInformationFile
471 succeeded we never set an error code and we explicitly need
472 to clear a previously set error code in this case, which
473 an application will check if INVALID_SET_FILE_POINTER is returned! */
474 SetLastError(ERROR_SUCCESS);
475 }
476
477 return FilePosition.CurrentByteOffset.u.LowPart;
478 }
479
480
481 /*
482 * @implemented
483 */
484 BOOL
485 STDCALL
486 SetFilePointerEx(HANDLE hFile,
487 LARGE_INTEGER liDistanceToMove,
488 PLARGE_INTEGER lpNewFilePointer,
489 DWORD dwMoveMethod)
490 {
491 FILE_POSITION_INFORMATION FilePosition;
492 FILE_STANDARD_INFORMATION FileStandard;
493 NTSTATUS errCode;
494 IO_STATUS_BLOCK IoStatusBlock;
495
496 if(IsConsoleHandle(hFile))
497 {
498 SetLastError(ERROR_INVALID_HANDLE);
499 return FALSE;
500 }
501
502 switch(dwMoveMethod)
503 {
504 case FILE_CURRENT:
505 NtQueryInformationFile(hFile,
506 &IoStatusBlock,
507 &FilePosition,
508 sizeof(FILE_POSITION_INFORMATION),
509 FilePositionInformation);
510 FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart;
511 break;
512 case FILE_END:
513 NtQueryInformationFile(hFile,
514 &IoStatusBlock,
515 &FileStandard,
516 sizeof(FILE_STANDARD_INFORMATION),
517 FileStandardInformation);
518 FilePosition.CurrentByteOffset.QuadPart =
519 FileStandard.EndOfFile.QuadPart + liDistanceToMove.QuadPart;
520 break;
521 case FILE_BEGIN:
522 FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart;
523 break;
524 default:
525 SetLastError(ERROR_INVALID_PARAMETER);
526 return FALSE;
527 }
528
529 if(FilePosition.CurrentByteOffset.QuadPart < 0)
530 {
531 SetLastError(ERROR_NEGATIVE_SEEK);
532 return FALSE;
533 }
534
535 errCode = NtSetInformationFile(hFile,
536 &IoStatusBlock,
537 &FilePosition,
538 sizeof(FILE_POSITION_INFORMATION),
539 FilePositionInformation);
540 if (!NT_SUCCESS(errCode))
541 {
542 SetLastErrorByStatus(errCode);
543 return FALSE;
544 }
545
546 if (lpNewFilePointer)
547 {
548 *lpNewFilePointer = FilePosition.CurrentByteOffset;
549 }
550 return TRUE;
551 }
552
553
554 /*
555 * @implemented
556 */
557 DWORD STDCALL
558 GetFileType(HANDLE hFile)
559 {
560 FILE_FS_DEVICE_INFORMATION DeviceInfo;
561 IO_STATUS_BLOCK StatusBlock;
562 NTSTATUS Status;
563
564 /* Get real handle */
565 switch ((ULONG)hFile)
566 {
567 case STD_INPUT_HANDLE:
568 hFile = NtCurrentPeb()->ProcessParameters->StandardInput;
569 break;
570
571 case STD_OUTPUT_HANDLE:
572 hFile = NtCurrentPeb()->ProcessParameters->StandardOutput;
573 break;
574
575 case STD_ERROR_HANDLE:
576 hFile = NtCurrentPeb()->ProcessParameters->StandardError;
577 break;
578 }
579
580 /* Check for console handle */
581 if (IsConsoleHandle(hFile))
582 {
583 if (VerifyConsoleIoHandle(hFile))
584 return FILE_TYPE_CHAR;
585 }
586
587 Status = NtQueryVolumeInformationFile(hFile,
588 &StatusBlock,
589 &DeviceInfo,
590 sizeof(FILE_FS_DEVICE_INFORMATION),
591 FileFsDeviceInformation);
592 if (!NT_SUCCESS(Status))
593 {
594 SetLastErrorByStatus(Status);
595 return FILE_TYPE_UNKNOWN;
596 }
597
598 switch (DeviceInfo.DeviceType)
599 {
600 case FILE_DEVICE_CD_ROM:
601 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
602 case FILE_DEVICE_CONTROLLER:
603 case FILE_DEVICE_DATALINK:
604 case FILE_DEVICE_DFS:
605 case FILE_DEVICE_DISK:
606 case FILE_DEVICE_DISK_FILE_SYSTEM:
607 case FILE_DEVICE_VIRTUAL_DISK:
608 return FILE_TYPE_DISK;
609
610 case FILE_DEVICE_KEYBOARD:
611 case FILE_DEVICE_MOUSE:
612 case FILE_DEVICE_NULL:
613 case FILE_DEVICE_PARALLEL_PORT:
614 case FILE_DEVICE_PRINTER:
615 case FILE_DEVICE_SERIAL_PORT:
616 case FILE_DEVICE_SCREEN:
617 case FILE_DEVICE_SOUND:
618 case FILE_DEVICE_MODEM:
619 return FILE_TYPE_CHAR;
620
621 case FILE_DEVICE_NAMED_PIPE:
622 return FILE_TYPE_PIPE;
623 }
624
625 return FILE_TYPE_UNKNOWN;
626 }
627
628
629 /*
630 * @implemented
631 */
632 DWORD STDCALL
633 GetFileSize(HANDLE hFile,
634 LPDWORD lpFileSizeHigh)
635 {
636 NTSTATUS errCode;
637 FILE_STANDARD_INFORMATION FileStandard;
638 IO_STATUS_BLOCK IoStatusBlock;
639
640 errCode = NtQueryInformationFile(hFile,
641 &IoStatusBlock,
642 &FileStandard,
643 sizeof(FILE_STANDARD_INFORMATION),
644 FileStandardInformation);
645 if (!NT_SUCCESS(errCode))
646 {
647 SetLastErrorByStatus(errCode);
648 if ( lpFileSizeHigh == NULL )
649 {
650 return -1;
651 }
652 else
653 {
654 return 0;
655 }
656 }
657 if ( lpFileSizeHigh != NULL )
658 *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
659
660 return FileStandard.EndOfFile.u.LowPart;
661 }
662
663
664 /*
665 * @implemented
666 */
667 BOOL
668 STDCALL
669 GetFileSizeEx(
670 HANDLE hFile,
671 PLARGE_INTEGER lpFileSize
672 )
673 {
674 NTSTATUS errCode;
675 FILE_STANDARD_INFORMATION FileStandard;
676 IO_STATUS_BLOCK IoStatusBlock;
677
678 errCode = NtQueryInformationFile(hFile,
679 &IoStatusBlock,
680 &FileStandard,
681 sizeof(FILE_STANDARD_INFORMATION),
682 FileStandardInformation);
683 if (!NT_SUCCESS(errCode))
684 {
685 SetLastErrorByStatus(errCode);
686 return FALSE;
687 }
688 if (lpFileSize)
689 *lpFileSize = FileStandard.EndOfFile;
690
691 return TRUE;
692 }
693
694
695 /*
696 * @implemented
697 */
698 DWORD STDCALL
699 GetCompressedFileSizeA(LPCSTR lpFileName,
700 LPDWORD lpFileSizeHigh)
701 {
702 PWCHAR FileNameW;
703
704 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
705 return INVALID_FILE_SIZE;
706
707 return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
708 }
709
710
711 /*
712 * @implemented
713 */
714 DWORD STDCALL
715 GetCompressedFileSizeW(LPCWSTR lpFileName,
716 LPDWORD lpFileSizeHigh)
717 {
718 FILE_COMPRESSION_INFORMATION FileCompression;
719 NTSTATUS errCode;
720 IO_STATUS_BLOCK IoStatusBlock;
721 HANDLE hFile;
722
723 hFile = CreateFileW(lpFileName,
724 GENERIC_READ,
725 FILE_SHARE_READ,
726 NULL,
727 OPEN_EXISTING,
728 FILE_ATTRIBUTE_NORMAL,
729 NULL);
730
731 if (hFile == INVALID_HANDLE_VALUE)
732 return INVALID_FILE_SIZE;
733
734 errCode = NtQueryInformationFile(hFile,
735 &IoStatusBlock,
736 &FileCompression,
737 sizeof(FILE_COMPRESSION_INFORMATION),
738 FileCompressionInformation);
739
740 CloseHandle(hFile);
741
742 if (!NT_SUCCESS(errCode))
743 {
744 SetLastErrorByStatus(errCode);
745 return INVALID_FILE_SIZE;
746 }
747
748 if(lpFileSizeHigh)
749 *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
750
751 SetLastError(NO_ERROR);
752 return FileCompression.CompressedFileSize.u.LowPart;
753 }
754
755
756 /*
757 * @implemented
758 */
759 BOOL STDCALL
760 GetFileInformationByHandle(HANDLE hFile,
761 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
762 {
763 struct
764 {
765 FILE_FS_VOLUME_INFORMATION FileFsVolume;
766 WCHAR Name[255];
767 }
768 FileFsVolume;
769
770 FILE_BASIC_INFORMATION FileBasic;
771 FILE_INTERNAL_INFORMATION FileInternal;
772 FILE_STANDARD_INFORMATION FileStandard;
773 NTSTATUS errCode;
774 IO_STATUS_BLOCK IoStatusBlock;
775
776 if(IsConsoleHandle(hFile))
777 {
778 SetLastError(ERROR_INVALID_HANDLE);
779 return FALSE;
780 }
781
782 errCode = NtQueryInformationFile(hFile,
783 &IoStatusBlock,
784 &FileBasic,
785 sizeof(FILE_BASIC_INFORMATION),
786 FileBasicInformation);
787 if (!NT_SUCCESS(errCode))
788 {
789 SetLastErrorByStatus(errCode);
790 return FALSE;
791 }
792
793 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
794
795 lpFileInformation->ftCreationTime.dwHighDateTime = FileBasic.CreationTime.u.HighPart;
796 lpFileInformation->ftCreationTime.dwLowDateTime = FileBasic.CreationTime.u.LowPart;
797
798 lpFileInformation->ftLastAccessTime.dwHighDateTime = FileBasic.LastAccessTime.u.HighPart;
799 lpFileInformation->ftLastAccessTime.dwLowDateTime = FileBasic.LastAccessTime.u.LowPart;
800
801 lpFileInformation->ftLastWriteTime.dwHighDateTime = FileBasic.LastWriteTime.u.HighPart;
802 lpFileInformation->ftLastWriteTime.dwLowDateTime = FileBasic.LastWriteTime.u.LowPart;
803
804 errCode = NtQueryInformationFile(hFile,
805 &IoStatusBlock,
806 &FileInternal,
807 sizeof(FILE_INTERNAL_INFORMATION),
808 FileInternalInformation);
809 if (!NT_SUCCESS(errCode))
810 {
811 SetLastErrorByStatus(errCode);
812 return FALSE;
813 }
814
815 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
816 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
817
818 errCode = NtQueryVolumeInformationFile(hFile,
819 &IoStatusBlock,
820 &FileFsVolume,
821 sizeof(FileFsVolume),
822 FileFsVolumeInformation);
823 if (!NT_SUCCESS(errCode))
824 {
825 SetLastErrorByStatus(errCode);
826 return FALSE;
827 }
828
829 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
830
831 errCode = NtQueryInformationFile(hFile,
832 &IoStatusBlock,
833 &FileStandard,
834 sizeof(FILE_STANDARD_INFORMATION),
835 FileStandardInformation);
836 if (!NT_SUCCESS(errCode))
837 {
838 SetLastErrorByStatus(errCode);
839 return FALSE;
840 }
841
842 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
843 lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
844 lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
845
846 return TRUE;
847 }
848
849
850 /*
851 * @implemented
852 */
853 BOOL STDCALL
854 GetFileAttributesExW(LPCWSTR lpFileName,
855 GET_FILEEX_INFO_LEVELS fInfoLevelId,
856 LPVOID lpFileInformation)
857 {
858 FILE_NETWORK_OPEN_INFORMATION FileInformation;
859 OBJECT_ATTRIBUTES ObjectAttributes;
860 UNICODE_STRING FileName;
861 NTSTATUS Status;
862 WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
863
864 DPRINT("GetFileAttributesExW(%S) called\n", lpFileName);
865
866
867 if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
868 {
869 SetLastError(ERROR_INVALID_PARAMETER);
870 return FALSE;
871 }
872
873 /* Validate and translate the filename */
874 if (!RtlDosPathNameToNtPathName_U (lpFileName,
875 &FileName,
876 NULL,
877 NULL))
878 {
879 DPRINT1 ("Invalid path '%S'\n", lpFileName);
880 SetLastError (ERROR_BAD_PATHNAME);
881 return FALSE;
882 }
883
884 /* build the object attributes */
885 InitializeObjectAttributes (&ObjectAttributes,
886 &FileName,
887 OBJ_CASE_INSENSITIVE,
888 NULL,
889 NULL);
890
891 /* Get file attributes */
892 Status = NtQueryFullAttributesFile(&ObjectAttributes,
893 &FileInformation);
894
895 RtlFreeUnicodeString (&FileName);
896 if (!NT_SUCCESS (Status))
897 {
898 DPRINT ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status);
899 SetLastErrorByStatus (Status);
900 return FALSE;
901 }
902
903 FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation;
904 FileAttributeData->dwFileAttributes = FileInformation.FileAttributes;
905 FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart;
906 FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart;
907 FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart;
908 FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart;
909 FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart;
910 FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart;
911 FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart;
912 FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart;
913
914 return TRUE;
915 }
916
917 /*
918 * @implemented
919 */
920 BOOL STDCALL
921 GetFileAttributesExA(LPCSTR lpFileName,
922 GET_FILEEX_INFO_LEVELS fInfoLevelId,
923 LPVOID lpFileInformation)
924 {
925 PWCHAR FileNameW;
926
927 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
928 return FALSE;
929
930 return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
931 }
932
933
934 /*
935 * @implemented
936 */
937 DWORD STDCALL
938 GetFileAttributesA(LPCSTR lpFileName)
939 {
940 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
941 PWSTR FileNameW;
942 BOOL ret;
943
944 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
945 return INVALID_FILE_ATTRIBUTES;
946
947 ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
948
949 return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
950 }
951
952
953 /*
954 * @implemented
955 */
956 DWORD STDCALL
957 GetFileAttributesW(LPCWSTR lpFileName)
958 {
959 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
960 BOOL Result;
961
962 DPRINT ("GetFileAttributeW(%S) called\n", lpFileName);
963
964 Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
965
966 return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
967 }
968
969
970 /*
971 * @implemented
972 */
973 BOOL STDCALL
974 GetFileAttributesByHandle(IN HANDLE hFile,
975 OUT LPDWORD dwFileAttributes,
976 IN DWORD dwFlags)
977 {
978 FILE_BASIC_INFORMATION FileBasic;
979 IO_STATUS_BLOCK IoStatusBlock;
980 NTSTATUS Status;
981
982 UNREFERENCED_PARAMETER(dwFlags);
983
984 if (IsConsoleHandle(hFile))
985 {
986 SetLastError(ERROR_INVALID_HANDLE);
987 return FALSE;
988 }
989
990 Status = NtQueryInformationFile(hFile,
991 &IoStatusBlock,
992 &FileBasic,
993 sizeof(FileBasic),
994 FileBasicInformation);
995 if (NT_SUCCESS(Status))
996 {
997 *dwFileAttributes = FileBasic.FileAttributes;
998 return TRUE;
999 }
1000
1001 SetLastErrorByStatus(Status);
1002 return FALSE;
1003 }
1004
1005
1006 /*
1007 * @implemented
1008 */
1009 BOOL STDCALL
1010 SetFileAttributesByHandle(IN HANDLE hFile,
1011 IN DWORD dwFileAttributes,
1012 IN DWORD dwFlags)
1013 {
1014 FILE_BASIC_INFORMATION FileBasic;
1015 IO_STATUS_BLOCK IoStatusBlock;
1016 NTSTATUS Status;
1017
1018 UNREFERENCED_PARAMETER(dwFlags);
1019
1020 if (IsConsoleHandle(hFile))
1021 {
1022 SetLastError(ERROR_INVALID_HANDLE);
1023 return FALSE;
1024 }
1025
1026 Status = NtQueryInformationFile(hFile,
1027 &IoStatusBlock,
1028 &FileBasic,
1029 sizeof(FileBasic),
1030 FileBasicInformation);
1031 if (NT_SUCCESS(Status))
1032 {
1033 FileBasic.FileAttributes = dwFileAttributes;
1034
1035 Status = NtSetInformationFile(hFile,
1036 &IoStatusBlock,
1037 &FileBasic,
1038 sizeof(FileBasic),
1039 FileBasicInformation);
1040 }
1041
1042 if (!NT_SUCCESS(Status))
1043 {
1044 SetLastErrorByStatus(Status);
1045 return FALSE;
1046 }
1047
1048 return TRUE;
1049 }
1050
1051
1052 /*
1053 * @implemented
1054 */
1055 BOOL STDCALL
1056 SetFileAttributesA(
1057 LPCSTR lpFileName,
1058 DWORD dwFileAttributes)
1059 {
1060 PWCHAR FileNameW;
1061
1062 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
1063 return FALSE;
1064
1065 return SetFileAttributesW(FileNameW, dwFileAttributes);
1066 }
1067
1068
1069 /*
1070 * @implemented
1071 */
1072 BOOL STDCALL
1073 SetFileAttributesW(LPCWSTR lpFileName,
1074 DWORD dwFileAttributes)
1075 {
1076 FILE_BASIC_INFORMATION FileInformation;
1077 OBJECT_ATTRIBUTES ObjectAttributes;
1078 IO_STATUS_BLOCK IoStatusBlock;
1079 UNICODE_STRING FileName;
1080 HANDLE FileHandle;
1081 NTSTATUS Status;
1082
1083 DPRINT ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
1084
1085 /* Validate and translate the filename */
1086 if (!RtlDosPathNameToNtPathName_U (lpFileName,
1087 &FileName,
1088 NULL,
1089 NULL))
1090 {
1091 DPRINT ("Invalid path\n");
1092 SetLastError (ERROR_BAD_PATHNAME);
1093 return FALSE;
1094 }
1095 DPRINT ("FileName: \'%wZ\'\n", &FileName);
1096
1097 /* build the object attributes */
1098 InitializeObjectAttributes (&ObjectAttributes,
1099 &FileName,
1100 OBJ_CASE_INSENSITIVE,
1101 NULL,
1102 NULL);
1103
1104 /* Open the file */
1105 Status = NtOpenFile (&FileHandle,
1106 SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
1107 &ObjectAttributes,
1108 &IoStatusBlock,
1109 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1110 FILE_SYNCHRONOUS_IO_NONALERT);
1111 RtlFreeUnicodeString (&FileName);
1112 if (!NT_SUCCESS (Status))
1113 {
1114 DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
1115 SetLastErrorByStatus (Status);
1116 return FALSE;
1117 }
1118
1119 Status = NtQueryInformationFile(FileHandle,
1120 &IoStatusBlock,
1121 &FileInformation,
1122 sizeof(FILE_BASIC_INFORMATION),
1123 FileBasicInformation);
1124 if (!NT_SUCCESS(Status))
1125 {
1126 DPRINT ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
1127 NtClose (FileHandle);
1128 SetLastErrorByStatus (Status);
1129 return FALSE;
1130 }
1131
1132 FileInformation.FileAttributes = dwFileAttributes;
1133 Status = NtSetInformationFile(FileHandle,
1134 &IoStatusBlock,
1135 &FileInformation,
1136 sizeof(FILE_BASIC_INFORMATION),
1137 FileBasicInformation);
1138 NtClose (FileHandle);
1139 if (!NT_SUCCESS(Status))
1140 {
1141 DPRINT ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
1142 SetLastErrorByStatus (Status);
1143 return FALSE;
1144 }
1145
1146 return TRUE;
1147 }
1148
1149
1150
1151
1152 /***********************************************************************
1153 * GetTempFileNameA (KERNEL32.@)
1154 */
1155 UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
1156 {
1157 WCHAR BufferW[MAX_PATH];
1158 PWCHAR PathW;
1159 WCHAR PrefixW[3+1];
1160 UINT ret;
1161
1162 if (!(PathW = FilenameA2W(path, FALSE)))
1163 return 0;
1164
1165 if (prefix)
1166 FilenameA2W_N(PrefixW, 3+1, prefix, -1);
1167
1168 ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
1169
1170 if (ret)
1171 FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
1172
1173 return ret;
1174 }
1175
1176 /***********************************************************************
1177 * GetTempFileNameW (KERNEL32.@)
1178 */
1179 UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer )
1180 {
1181 static const WCHAR formatW[] = L"%x.tmp";
1182
1183 int i;
1184 LPWSTR p;
1185
1186 if ( !path || !buffer )
1187 {
1188 SetLastError( ERROR_INVALID_PARAMETER );
1189 return 0;
1190 }
1191
1192 wcscpy( buffer, path );
1193 p = buffer + wcslen(buffer);
1194
1195 /* add a \, if there isn't one */
1196 if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
1197
1198 if ( prefix )
1199 for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
1200
1201 unique &= 0xffff;
1202
1203 if (unique) swprintf( p, formatW, unique );
1204 else
1205 {
1206 /* get a "random" unique number and try to create the file */
1207 HANDLE handle;
1208 UINT num = GetTickCount() & 0xffff;
1209
1210 if (!num) num = 1;
1211 unique = num;
1212 do
1213 {
1214 swprintf( p, formatW, unique );
1215 handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
1216 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1217 if (handle != INVALID_HANDLE_VALUE)
1218 { /* We created it */
1219 DPRINT("created %S\n", buffer);
1220 CloseHandle( handle );
1221 break;
1222 }
1223 if (GetLastError() != ERROR_FILE_EXISTS &&
1224 GetLastError() != ERROR_SHARING_VIOLATION)
1225 break; /* No need to go on */
1226 if (!(++unique & 0xffff)) unique = 1;
1227 } while (unique != num);
1228 }
1229
1230 DPRINT("returning %S\n", buffer);
1231 return unique;
1232 }
1233
1234
1235
1236
1237
1238 /*
1239 * @implemented
1240 */
1241 BOOL STDCALL
1242 GetFileTime(HANDLE hFile,
1243 LPFILETIME lpCreationTime,
1244 LPFILETIME lpLastAccessTime,
1245 LPFILETIME lpLastWriteTime)
1246 {
1247 IO_STATUS_BLOCK IoStatusBlock;
1248 FILE_BASIC_INFORMATION FileBasic;
1249 NTSTATUS Status;
1250
1251 if(IsConsoleHandle(hFile))
1252 {
1253 SetLastError(ERROR_INVALID_HANDLE);
1254 return FALSE;
1255 }
1256
1257 Status = NtQueryInformationFile(hFile,
1258 &IoStatusBlock,
1259 &FileBasic,
1260 sizeof(FILE_BASIC_INFORMATION),
1261 FileBasicInformation);
1262 if (!NT_SUCCESS(Status))
1263 {
1264 SetLastErrorByStatus(Status);
1265 return FALSE;
1266 }
1267
1268 if (lpCreationTime)
1269 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
1270 if (lpLastAccessTime)
1271 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
1272 if (lpLastWriteTime)
1273 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
1274
1275 return TRUE;
1276 }
1277
1278
1279 /*
1280 * @implemented
1281 */
1282 BOOL STDCALL
1283 SetFileTime(HANDLE hFile,
1284 CONST FILETIME *lpCreationTime,
1285 CONST FILETIME *lpLastAccessTime,
1286 CONST FILETIME *lpLastWriteTime)
1287 {
1288 FILE_BASIC_INFORMATION FileBasic;
1289 IO_STATUS_BLOCK IoStatusBlock;
1290 NTSTATUS Status;
1291
1292 if(IsConsoleHandle(hFile))
1293 {
1294 SetLastError(ERROR_INVALID_HANDLE);
1295 return FALSE;
1296 }
1297
1298 Status = NtQueryInformationFile(hFile,
1299 &IoStatusBlock,
1300 &FileBasic,
1301 sizeof(FILE_BASIC_INFORMATION),
1302 FileBasicInformation);
1303 if (!NT_SUCCESS(Status))
1304 {
1305 SetLastErrorByStatus(Status);
1306 return FALSE;
1307 }
1308
1309 if (lpCreationTime)
1310 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
1311 if (lpLastAccessTime)
1312 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
1313 if (lpLastWriteTime)
1314 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
1315
1316 // should i initialize changetime ???
1317
1318 Status = NtSetInformationFile(hFile,
1319 &IoStatusBlock,
1320 &FileBasic,
1321 sizeof(FILE_BASIC_INFORMATION),
1322 FileBasicInformation);
1323 if (!NT_SUCCESS(Status))
1324 {
1325 SetLastErrorByStatus(Status);
1326 return FALSE;
1327 }
1328
1329 return TRUE;
1330 }
1331
1332
1333 /*
1334 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1335 *
1336 * @implemented
1337 */
1338 BOOL STDCALL
1339 SetEndOfFile(HANDLE hFile)
1340 {
1341 IO_STATUS_BLOCK IoStatusBlock;
1342 FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
1343 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
1344 FILE_POSITION_INFORMATION FilePosInfo;
1345 NTSTATUS Status;
1346
1347 if(IsConsoleHandle(hFile))
1348 {
1349 SetLastError(ERROR_INVALID_HANDLE);
1350 return FALSE;
1351 }
1352
1353 //get current position
1354 Status = NtQueryInformationFile(
1355 hFile,
1356 &IoStatusBlock,
1357 &FilePosInfo,
1358 sizeof(FILE_POSITION_INFORMATION),
1359 FilePositionInformation
1360 );
1361
1362 if (!NT_SUCCESS(Status)){
1363 SetLastErrorByStatus(Status);
1364 return FALSE;
1365 }
1366
1367 EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1368
1369 /*
1370 NOTE:
1371 This call is not supposed to free up any space after the eof marker
1372 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1373 But...most file systems dispatch both FileEndOfFileInformation
1374 and FileAllocationInformation as they were the same command.
1375
1376 */
1377 Status = NtSetInformationFile(
1378 hFile,
1379 &IoStatusBlock, //out
1380 &EndOfFileInfo,
1381 sizeof(FILE_END_OF_FILE_INFORMATION),
1382 FileEndOfFileInformation
1383 );
1384
1385 if (!NT_SUCCESS(Status)){
1386 SetLastErrorByStatus(Status);
1387 return FALSE;
1388 }
1389
1390 FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1391
1392
1393 Status = NtSetInformationFile(
1394 hFile,
1395 &IoStatusBlock, //out
1396 &FileAllocationInfo,
1397 sizeof(FILE_ALLOCATION_INFORMATION),
1398 FileAllocationInformation
1399 );
1400
1401 if (!NT_SUCCESS(Status)){
1402 SetLastErrorByStatus(Status);
1403 return FALSE;
1404 }
1405
1406 return TRUE;
1407
1408 }
1409
1410
1411 /*
1412 * @implemented
1413 */
1414 BOOL
1415 STDCALL
1416 SetFileValidData(
1417 HANDLE hFile,
1418 LONGLONG ValidDataLength
1419 )
1420 {
1421 IO_STATUS_BLOCK IoStatusBlock;
1422 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
1423 NTSTATUS Status;
1424
1425 ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
1426
1427 Status = NtSetInformationFile(
1428 hFile,
1429 &IoStatusBlock, //out
1430 &ValidDataLengthInformation,
1431 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
1432 FileValidDataLengthInformation
1433 );
1434
1435 if (!NT_SUCCESS(Status)){
1436 SetLastErrorByStatus(Status);
1437 return FALSE;
1438 }
1439
1440 return TRUE;
1441 }
1442
1443
1444
1445 /*
1446 * @implemented
1447 */
1448 BOOL
1449 STDCALL
1450 SetFileShortNameW(
1451 HANDLE hFile,
1452 LPCWSTR lpShortName)
1453 {
1454 NTSTATUS Status;
1455 ULONG NeededSize;
1456 UNICODE_STRING ShortName;
1457 IO_STATUS_BLOCK IoStatusBlock;
1458 PFILE_NAME_INFORMATION FileNameInfo;
1459
1460 if(IsConsoleHandle(hFile))
1461 {
1462 SetLastError(ERROR_INVALID_HANDLE);
1463 return FALSE;
1464 }
1465
1466 if(!lpShortName)
1467 {
1468 SetLastError(ERROR_INVALID_PARAMETER);
1469 return FALSE;
1470 }
1471
1472 RtlInitUnicodeString(&ShortName, lpShortName);
1473
1474 NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR);
1475 if(!(FileNameInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize)))
1476 {
1477 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1478 return FALSE;
1479 }
1480
1481 FileNameInfo->FileNameLength = ShortName.Length;
1482 RtlCopyMemory(FileNameInfo->FileName, ShortName.Buffer, ShortName.Length);
1483
1484 Status = NtSetInformationFile(hFile,
1485 &IoStatusBlock, //out
1486 FileNameInfo,
1487 NeededSize,
1488 FileShortNameInformation);
1489
1490 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo);
1491 if(!NT_SUCCESS(Status))
1492 {
1493 SetLastErrorByStatus(Status);
1494 return FALSE;
1495 }
1496
1497 return TRUE;
1498 }
1499
1500
1501 /*
1502 * @implemented
1503 */
1504 BOOL
1505 STDCALL
1506 SetFileShortNameA(
1507 HANDLE hFile,
1508 LPCSTR lpShortName
1509 )
1510 {
1511 PWCHAR ShortNameW;
1512
1513 if(IsConsoleHandle(hFile))
1514 {
1515 SetLastError(ERROR_INVALID_HANDLE);
1516 return FALSE;
1517 }
1518
1519 if(!lpShortName)
1520 {
1521 SetLastError(ERROR_INVALID_PARAMETER);
1522 return FALSE;
1523 }
1524
1525 if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
1526 return FALSE;
1527
1528 return SetFileShortNameW(hFile, ShortNameW);
1529 }
1530
1531
1532 /*
1533 * @implemented
1534 */
1535 BOOL
1536 STDCALL
1537 CheckNameLegalDOS8Dot3W(
1538 LPCWSTR lpName,
1539 LPSTR lpOemName OPTIONAL,
1540 DWORD OemNameSize OPTIONAL,
1541 PBOOL pbNameContainsSpaces OPTIONAL,
1542 PBOOL pbNameLegal
1543 )
1544 {
1545 UNICODE_STRING Name;
1546 ANSI_STRING AnsiName;
1547
1548 if(lpName == NULL ||
1549 (lpOemName == NULL && OemNameSize != 0) ||
1550 pbNameLegal == NULL)
1551 {
1552 SetLastError(ERROR_INVALID_PARAMETER);
1553 return FALSE;
1554 }
1555
1556 if(lpOemName != NULL)
1557 {
1558 AnsiName.Buffer = lpOemName;
1559 AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
1560 AnsiName.Length = 0;
1561 }
1562
1563 RtlInitUnicodeString(&Name, lpName);
1564
1565 *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
1566 (lpOemName ? &AnsiName : NULL),
1567 (BOOLEAN*)pbNameContainsSpaces);
1568
1569 return TRUE;
1570 }
1571
1572
1573 /*
1574 * @implemented
1575 */
1576 BOOL
1577 STDCALL
1578 CheckNameLegalDOS8Dot3A(
1579 LPCSTR lpName,
1580 LPSTR lpOemName OPTIONAL,
1581 DWORD OemNameSize OPTIONAL,
1582 PBOOL pbNameContainsSpaces OPTIONAL,
1583 PBOOL pbNameLegal
1584 )
1585 {
1586 UNICODE_STRING Name;
1587 ANSI_STRING AnsiName, AnsiInputName;
1588 NTSTATUS Status;
1589
1590 if(lpName == NULL ||
1591 (lpOemName == NULL && OemNameSize != 0) ||
1592 pbNameLegal == NULL)
1593 {
1594 SetLastError(ERROR_INVALID_PARAMETER);
1595 return FALSE;
1596 }
1597
1598 if(lpOemName != NULL)
1599 {
1600 AnsiName.Buffer = lpOemName;
1601 AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
1602 AnsiName.Length = 0;
1603 }
1604
1605 RtlInitAnsiString(&AnsiInputName, (LPSTR)lpName);
1606 if(bIsFileApiAnsi)
1607 Status = RtlAnsiStringToUnicodeString(&Name, &AnsiInputName, TRUE);
1608 else
1609 Status = RtlOemStringToUnicodeString(&Name, &AnsiInputName, TRUE);
1610
1611 if(!NT_SUCCESS(Status))
1612 {
1613 SetLastErrorByStatus(Status);
1614 return FALSE;
1615 }
1616
1617 *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
1618 (lpOemName ? &AnsiName : NULL),
1619 (BOOLEAN*)pbNameContainsSpaces);
1620
1621 RtlFreeUnicodeString(&Name);
1622
1623 return TRUE;
1624 }
1625
1626
1627 /*
1628 * @implemented
1629 */
1630 DWORD
1631 WINAPI
1632 GetFinalPathNameByHandleA(IN HANDLE hFile,
1633 OUT LPSTR lpszFilePath,
1634 IN DWORD cchFilePath,
1635 IN DWORD dwFlags)
1636 {
1637 WCHAR FilePathW[MAX_PATH];
1638 UNICODE_STRING FilePathU;
1639 DWORD PrevLastError;
1640 DWORD Ret = 0;
1641
1642 if (cchFilePath != 0 &&
1643 cchFilePath > sizeof(FilePathW) / sizeof(FilePathW[0]))
1644 {
1645 FilePathU.Length = 0;
1646 FilePathU.MaximumLength = (USHORT)cchFilePath * sizeof(WCHAR);
1647 FilePathU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
1648 0,
1649 FilePathU.MaximumLength);
1650 if (FilePathU.Buffer == NULL)
1651 {
1652 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1653 return 0;
1654 }
1655 }
1656 else
1657 {
1658 FilePathU.Length = 0;
1659 FilePathU.MaximumLength = sizeof(FilePathW);
1660 FilePathU.Buffer = FilePathW;
1661 }
1662
1663 /* save the last error code */
1664 PrevLastError = GetLastError();
1665 SetLastError(ERROR_SUCCESS);
1666
1667 /* call the unicode version that does all the work */
1668 Ret = GetFinalPathNameByHandleW(hFile,
1669 FilePathU.Buffer,
1670 cchFilePath,
1671 dwFlags);
1672
1673 if (GetLastError() == ERROR_SUCCESS)
1674 {
1675 /* no error, restore the last error code and convert the string */
1676 SetLastError(PrevLastError);
1677
1678 Ret = FilenameU2A_FitOrFail(lpszFilePath,
1679 cchFilePath,
1680 &FilePathU);
1681 }
1682
1683 /* free allocated memory if necessary */
1684 if (FilePathU.Buffer != FilePathW)
1685 {
1686 RtlFreeHeap(RtlGetProcessHeap(),
1687 0,
1688 FilePathU.Buffer);
1689 }
1690
1691 return Ret;
1692 }
1693
1694
1695 /*
1696 * @unimplemented
1697 */
1698 DWORD
1699 WINAPI
1700 GetFinalPathNameByHandleW(IN HANDLE hFile,
1701 OUT LPWSTR lpszFilePath,
1702 IN DWORD cchFilePath,
1703 IN DWORD dwFlags)
1704 {
1705 if (dwFlags & ~(VOLUME_NAME_DOS | VOLUME_NAME_GUID | VOLUME_NAME_NT |
1706 VOLUME_NAME_NONE | FILE_NAME_NORMALIZED | FILE_NAME_OPENED))
1707 {
1708 SetLastError(ERROR_INVALID_PARAMETER);
1709 return 0;
1710 }
1711
1712 UNIMPLEMENTED;
1713 return 0;
1714 }
1715
1716
1717 /*
1718 * @unimplemented
1719 */
1720 BOOL
1721 WINAPI
1722 SetFileBandwidthReservation(IN HANDLE hFile,
1723 IN DWORD nPeriodMilliseconds,
1724 IN DWORD nBytesPerPeriod,
1725 IN BOOL bDiscardable,
1726 OUT LPDWORD lpTransferSize,
1727 OUT LPDWORD lpNumOutstandingRequests)
1728 {
1729 UNIMPLEMENTED;
1730 return FALSE;
1731 }
1732
1733
1734 /*
1735 * @unimplemented
1736 */
1737 BOOL
1738 WINAPI
1739 GetFileBandwidthReservation(IN HANDLE hFile,
1740 OUT LPDWORD lpPeriodMilliseconds,
1741 OUT LPDWORD lpBytesPerPeriod,
1742 OUT LPBOOL pDiscardable,
1743 OUT LPDWORD lpTransferSize,
1744 OUT LPDWORD lpNumOutstandingRequests)
1745 {
1746 UNIMPLEMENTED;
1747 return FALSE;
1748 }
1749
1750
1751 /*
1752 * @unimplemented
1753 */
1754 BOOL
1755 WINAPI
1756 SetFileCompletionNotificationModes(IN HANDLE FileHandle,
1757 IN UCHAR Flags)
1758 {
1759 if (Flags & ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS | FILE_SKIP_SET_EVENT_ON_HANDLE))
1760 {
1761 SetLastError(ERROR_INVALID_PARAMETER);
1762 return FALSE;
1763 }
1764
1765 UNIMPLEMENTED;
1766 return FALSE;
1767 }
1768
1769
1770 /*
1771 * @unimplemented
1772 */
1773 HANDLE
1774 WINAPI
1775 OpenFileById(IN HANDLE hFile,
1776 IN LPFILE_ID_DESCRIPTOR lpFileID,
1777 IN DWORD dwDesiredAccess,
1778 IN DWORD dwShareMode,
1779 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
1780 IN DWORD dwFlags)
1781 {
1782 UNIMPLEMENTED;
1783 return INVALID_HANDLE_VALUE;
1784 }
1785
1786 /* EOF */