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