check for console handles in Get/SetFileAttributesByHandle()
[reactos.git] / reactos / lib / kernel32 / file / file.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/file.c
6 * PURPOSE: Directory functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * GetTempFileName is modified from WINE [ Alexandre Juiliard ]
9 * UPDATE HISTORY:
10 * Created 01/11/98
11 */
12
13 /* INCLUDES *****************************************************************/
14
15 #include <k32.h>
16
17 #define NDEBUG
18 #include "../include/debug.h"
19
20
21 /* GLOBALS ******************************************************************/
22
23 BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
24
25 /* FUNCTIONS ****************************************************************/
26
27
28
29 PWCHAR
30 FilenameA2W(LPCSTR NameA, BOOL alloc)
31 {
32 ANSI_STRING str;
33 UNICODE_STRING strW;
34 PUNICODE_STRING pstrW;
35 NTSTATUS Status;
36
37 ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
38 ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer));
39
40 RtlInitAnsiString(&str, NameA);
41 pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
42
43 if (bIsFileApiAnsi)
44 Status= RtlAnsiStringToUnicodeString( pstrW, &str, alloc );
45 else
46 Status= RtlOemStringToUnicodeString( pstrW, &str, 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 = 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 = 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 ((LPWSTR)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 RtlFreeUnicodeString(&FileNameString);
313 return (HFILE)NULL;
314 }
315
316 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
317 ObjectAttributes.RootDirectory = NULL;
318 ObjectAttributes.ObjectName = &FileNameString;
319 ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
320 ObjectAttributes.SecurityDescriptor = NULL;
321 ObjectAttributes.SecurityQualityOfService = NULL;
322
323 errCode = NtOpenFile (&FileHandle,
324 GENERIC_READ|SYNCHRONIZE,
325 &ObjectAttributes,
326 &IoStatusBlock,
327 FILE_SHARE_READ,
328 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
329
330 RtlFreeUnicodeString(&FileNameString);
331
332 lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
333
334 if (!NT_SUCCESS(errCode))
335 {
336 SetLastErrorByStatus (errCode);
337 return (HFILE)INVALID_HANDLE_VALUE;
338 }
339
340 return (HFILE)FileHandle;
341 }
342
343
344 /*
345 * @implemented
346 */
347 BOOL STDCALL
348 FlushFileBuffers(HANDLE hFile)
349 {
350 NTSTATUS errCode;
351 IO_STATUS_BLOCK IoStatusBlock;
352
353 if (IsConsoleHandle(hFile))
354 {
355 return FALSE;
356 }
357
358 errCode = NtFlushBuffersFile(hFile,
359 &IoStatusBlock);
360 if (!NT_SUCCESS(errCode))
361 {
362 SetLastErrorByStatus(errCode);
363 return(FALSE);
364 }
365 return(TRUE);
366 }
367
368
369 /*
370 * @implemented
371 */
372 DWORD STDCALL
373 SetFilePointer(HANDLE hFile,
374 LONG lDistanceToMove,
375 PLONG lpDistanceToMoveHigh,
376 DWORD dwMoveMethod)
377 {
378 FILE_POSITION_INFORMATION FilePosition;
379 FILE_STANDARD_INFORMATION FileStandard;
380 NTSTATUS errCode;
381 IO_STATUS_BLOCK IoStatusBlock;
382 LARGE_INTEGER Distance;
383
384 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
385 hFile,lDistanceToMove,dwMoveMethod);
386
387 if(IsConsoleHandle(hFile))
388 {
389 SetLastError(ERROR_INVALID_HANDLE);
390 return -1;
391 }
392
393 Distance.u.LowPart = lDistanceToMove;
394 if (lpDistanceToMoveHigh)
395 {
396 Distance.u.HighPart = *lpDistanceToMoveHigh;
397 }
398 else if (lDistanceToMove >= 0)
399 {
400 Distance.u.HighPart = 0;
401 }
402 else
403 {
404 Distance.u.HighPart = -1;
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 errCode = NtSetInformationFile(hFile,
441 &IoStatusBlock,
442 &FilePosition,
443 sizeof(FILE_POSITION_INFORMATION),
444 FilePositionInformation);
445 if (!NT_SUCCESS(errCode))
446 {
447 SetLastErrorByStatus(errCode);
448 return -1;
449 }
450
451 if (lpDistanceToMoveHigh != NULL)
452 {
453 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
454 }
455 return FilePosition.CurrentByteOffset.u.LowPart;
456 }
457
458
459 /*
460 * @implemented
461 */
462 BOOL
463 STDCALL
464 SetFilePointerEx(HANDLE hFile,
465 LARGE_INTEGER liDistanceToMove,
466 PLARGE_INTEGER lpNewFilePointer,
467 DWORD dwMoveMethod)
468 {
469 FILE_POSITION_INFORMATION FilePosition;
470 FILE_STANDARD_INFORMATION FileStandard;
471 NTSTATUS errCode;
472 IO_STATUS_BLOCK IoStatusBlock;
473
474 if(IsConsoleHandle(hFile))
475 {
476 SetLastError(ERROR_INVALID_HANDLE);
477 return FALSE;
478 }
479
480 switch(dwMoveMethod)
481 {
482 case FILE_CURRENT:
483 NtQueryInformationFile(hFile,
484 &IoStatusBlock,
485 &FilePosition,
486 sizeof(FILE_POSITION_INFORMATION),
487 FilePositionInformation);
488 FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart;
489 break;
490 case FILE_END:
491 NtQueryInformationFile(hFile,
492 &IoStatusBlock,
493 &FileStandard,
494 sizeof(FILE_STANDARD_INFORMATION),
495 FileStandardInformation);
496 FilePosition.CurrentByteOffset.QuadPart =
497 FileStandard.EndOfFile.QuadPart + liDistanceToMove.QuadPart;
498 break;
499 case FILE_BEGIN:
500 FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart;
501 break;
502 default:
503 SetLastError(ERROR_INVALID_PARAMETER);
504 return FALSE;
505 }
506
507 if(FilePosition.CurrentByteOffset.QuadPart < 0)
508 {
509 SetLastError(ERROR_NEGATIVE_SEEK);
510 return FALSE;
511 }
512
513 errCode = NtSetInformationFile(hFile,
514 &IoStatusBlock,
515 &FilePosition,
516 sizeof(FILE_POSITION_INFORMATION),
517 FilePositionInformation);
518 if (!NT_SUCCESS(errCode))
519 {
520 SetLastErrorByStatus(errCode);
521 return FALSE;
522 }
523
524 if (lpNewFilePointer)
525 {
526 *lpNewFilePointer = FilePosition.CurrentByteOffset;
527 }
528 return TRUE;
529 }
530
531
532 /*
533 * @implemented
534 */
535 DWORD STDCALL
536 GetFileType(HANDLE hFile)
537 {
538 FILE_FS_DEVICE_INFORMATION DeviceInfo;
539 IO_STATUS_BLOCK StatusBlock;
540 NTSTATUS Status;
541
542 /* Get real handle */
543 switch ((ULONG)hFile)
544 {
545 case STD_INPUT_HANDLE:
546 hFile = NtCurrentPeb()->ProcessParameters->StandardInput;
547 break;
548
549 case STD_OUTPUT_HANDLE:
550 hFile = NtCurrentPeb()->ProcessParameters->StandardOutput;
551 break;
552
553 case STD_ERROR_HANDLE:
554 hFile = NtCurrentPeb()->ProcessParameters->StandardError;
555 break;
556 }
557
558 /* Check for console handle */
559 if (IsConsoleHandle(hFile))
560 {
561 if (VerifyConsoleIoHandle(hFile))
562 return FILE_TYPE_CHAR;
563 }
564
565 Status = NtQueryVolumeInformationFile(hFile,
566 &StatusBlock,
567 &DeviceInfo,
568 sizeof(FILE_FS_DEVICE_INFORMATION),
569 FileFsDeviceInformation);
570 if (!NT_SUCCESS(Status))
571 {
572 SetLastErrorByStatus(Status);
573 return FILE_TYPE_UNKNOWN;
574 }
575
576 switch (DeviceInfo.DeviceType)
577 {
578 case FILE_DEVICE_CD_ROM:
579 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
580 case FILE_DEVICE_CONTROLLER:
581 case FILE_DEVICE_DATALINK:
582 case FILE_DEVICE_DFS:
583 case FILE_DEVICE_DISK:
584 case FILE_DEVICE_DISK_FILE_SYSTEM:
585 case FILE_DEVICE_VIRTUAL_DISK:
586 return FILE_TYPE_DISK;
587
588 case FILE_DEVICE_KEYBOARD:
589 case FILE_DEVICE_MOUSE:
590 case FILE_DEVICE_NULL:
591 case FILE_DEVICE_PARALLEL_PORT:
592 case FILE_DEVICE_PRINTER:
593 case FILE_DEVICE_SERIAL_PORT:
594 case FILE_DEVICE_SCREEN:
595 case FILE_DEVICE_SOUND:
596 case FILE_DEVICE_MODEM:
597 return FILE_TYPE_CHAR;
598
599 case FILE_DEVICE_NAMED_PIPE:
600 return FILE_TYPE_PIPE;
601 }
602
603 return FILE_TYPE_UNKNOWN;
604 }
605
606
607 /*
608 * @implemented
609 */
610 DWORD STDCALL
611 GetFileSize(HANDLE hFile,
612 LPDWORD lpFileSizeHigh)
613 {
614 NTSTATUS errCode;
615 FILE_STANDARD_INFORMATION FileStandard;
616 IO_STATUS_BLOCK IoStatusBlock;
617
618 errCode = NtQueryInformationFile(hFile,
619 &IoStatusBlock,
620 &FileStandard,
621 sizeof(FILE_STANDARD_INFORMATION),
622 FileStandardInformation);
623 if (!NT_SUCCESS(errCode))
624 {
625 SetLastErrorByStatus(errCode);
626 if ( lpFileSizeHigh == NULL )
627 {
628 return -1;
629 }
630 else
631 {
632 return 0;
633 }
634 }
635 if ( lpFileSizeHigh != NULL )
636 *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
637
638 return FileStandard.EndOfFile.u.LowPart;
639 }
640
641
642 /*
643 * @implemented
644 */
645 BOOL
646 STDCALL
647 GetFileSizeEx(
648 HANDLE hFile,
649 PLARGE_INTEGER lpFileSize
650 )
651 {
652 NTSTATUS errCode;
653 FILE_STANDARD_INFORMATION FileStandard;
654 IO_STATUS_BLOCK IoStatusBlock;
655
656 errCode = NtQueryInformationFile(hFile,
657 &IoStatusBlock,
658 &FileStandard,
659 sizeof(FILE_STANDARD_INFORMATION),
660 FileStandardInformation);
661 if (!NT_SUCCESS(errCode))
662 {
663 SetLastErrorByStatus(errCode);
664 return FALSE;
665 }
666 if (lpFileSize)
667 *lpFileSize = FileStandard.EndOfFile;
668
669 return TRUE;
670 }
671
672
673 /*
674 * @implemented
675 */
676 DWORD STDCALL
677 GetCompressedFileSizeA(LPCSTR lpFileName,
678 LPDWORD lpFileSizeHigh)
679 {
680 PWCHAR FileNameW;
681
682 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
683 return INVALID_FILE_SIZE;
684
685 return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
686 }
687
688
689 /*
690 * @implemented
691 */
692 DWORD STDCALL
693 GetCompressedFileSizeW(LPCWSTR lpFileName,
694 LPDWORD lpFileSizeHigh)
695 {
696 FILE_COMPRESSION_INFORMATION FileCompression;
697 NTSTATUS errCode;
698 IO_STATUS_BLOCK IoStatusBlock;
699 HANDLE hFile;
700
701 hFile = CreateFileW(lpFileName,
702 GENERIC_READ,
703 FILE_SHARE_READ,
704 NULL,
705 OPEN_EXISTING,
706 FILE_ATTRIBUTE_NORMAL,
707 NULL);
708
709 if (hFile == INVALID_HANDLE_VALUE)
710 return INVALID_FILE_SIZE;
711
712 errCode = NtQueryInformationFile(hFile,
713 &IoStatusBlock,
714 &FileCompression,
715 sizeof(FILE_COMPRESSION_INFORMATION),
716 FileCompressionInformation);
717
718 CloseHandle(hFile);
719
720 if (!NT_SUCCESS(errCode))
721 {
722 SetLastErrorByStatus(errCode);
723 return INVALID_FILE_SIZE;
724 }
725
726 if(lpFileSizeHigh)
727 *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
728
729 SetLastError(NO_ERROR);
730 return FileCompression.CompressedFileSize.u.LowPart;
731 }
732
733
734 /*
735 * @implemented
736 */
737 BOOL STDCALL
738 GetFileInformationByHandle(HANDLE hFile,
739 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
740 {
741 struct
742 {
743 FILE_FS_VOLUME_INFORMATION FileFsVolume;
744 WCHAR Name[255];
745 }
746 FileFsVolume;
747
748 FILE_BASIC_INFORMATION FileBasic;
749 FILE_INTERNAL_INFORMATION FileInternal;
750 FILE_STANDARD_INFORMATION FileStandard;
751 NTSTATUS errCode;
752 IO_STATUS_BLOCK IoStatusBlock;
753
754 if(IsConsoleHandle(hFile))
755 {
756 SetLastError(ERROR_INVALID_HANDLE);
757 return FALSE;
758 }
759
760 errCode = NtQueryInformationFile(hFile,
761 &IoStatusBlock,
762 &FileBasic,
763 sizeof(FILE_BASIC_INFORMATION),
764 FileBasicInformation);
765 if (!NT_SUCCESS(errCode))
766 {
767 SetLastErrorByStatus(errCode);
768 return FALSE;
769 }
770
771 lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
772
773 lpFileInformation->ftCreationTime.dwHighDateTime = FileBasic.CreationTime.u.HighPart;
774 lpFileInformation->ftCreationTime.dwLowDateTime = FileBasic.CreationTime.u.LowPart;
775
776 lpFileInformation->ftLastAccessTime.dwHighDateTime = FileBasic.LastAccessTime.u.HighPart;
777 lpFileInformation->ftLastAccessTime.dwLowDateTime = FileBasic.LastAccessTime.u.LowPart;
778
779 lpFileInformation->ftLastWriteTime.dwHighDateTime = FileBasic.LastWriteTime.u.HighPart;
780 lpFileInformation->ftLastWriteTime.dwLowDateTime = FileBasic.LastWriteTime.u.LowPart;
781
782 errCode = NtQueryInformationFile(hFile,
783 &IoStatusBlock,
784 &FileInternal,
785 sizeof(FILE_INTERNAL_INFORMATION),
786 FileInternalInformation);
787 if (!NT_SUCCESS(errCode))
788 {
789 SetLastErrorByStatus(errCode);
790 return FALSE;
791 }
792
793 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
794 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
795
796 errCode = NtQueryVolumeInformationFile(hFile,
797 &IoStatusBlock,
798 &FileFsVolume,
799 sizeof(FileFsVolume),
800 FileFsVolumeInformation);
801 if (!NT_SUCCESS(errCode))
802 {
803 SetLastErrorByStatus(errCode);
804 return FALSE;
805 }
806
807 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
808
809 errCode = NtQueryInformationFile(hFile,
810 &IoStatusBlock,
811 &FileStandard,
812 sizeof(FILE_STANDARD_INFORMATION),
813 FileStandardInformation);
814 if (!NT_SUCCESS(errCode))
815 {
816 SetLastErrorByStatus(errCode);
817 return FALSE;
818 }
819
820 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
821 lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
822 lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
823
824 return TRUE;
825 }
826
827
828 /*
829 * @implemented
830 */
831 BOOL STDCALL
832 GetFileAttributesExW(LPCWSTR lpFileName,
833 GET_FILEEX_INFO_LEVELS fInfoLevelId,
834 LPVOID lpFileInformation)
835 {
836 FILE_NETWORK_OPEN_INFORMATION FileInformation;
837 OBJECT_ATTRIBUTES ObjectAttributes;
838 IO_STATUS_BLOCK IoStatusBlock;
839 UNICODE_STRING FileName;
840 HANDLE FileHandle;
841 NTSTATUS Status;
842 WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
843
844 DPRINT("GetFileAttributesExW(%S) called\n", lpFileName);
845
846
847 if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
848 {
849 SetLastError(ERROR_INVALID_PARAMETER);
850 return FALSE;
851 }
852
853 /* Validate and translate the filename */
854 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
855 &FileName,
856 NULL,
857 NULL))
858 {
859 DPRINT1 ("Invalid path\n");
860 SetLastError (ERROR_BAD_PATHNAME);
861 return FALSE;
862 }
863
864 /* build the object attributes */
865 InitializeObjectAttributes (&ObjectAttributes,
866 &FileName,
867 OBJ_CASE_INSENSITIVE,
868 NULL,
869 NULL);
870
871 /* Open the file */
872 Status = NtOpenFile (&FileHandle,
873 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
874 &ObjectAttributes,
875 &IoStatusBlock,
876 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
877 FILE_SYNCHRONOUS_IO_NONALERT);
878 RtlFreeUnicodeString (&FileName);
879 if (!NT_SUCCESS (Status))
880 {
881 DPRINT ("NtOpenFile() failed %x (Status %lx)\n", &ObjectAttributes, Status);
882 SetLastErrorByStatus (Status);
883 return FALSE;
884 }
885
886 /* Get file attributes */
887 Status = NtQueryInformationFile (FileHandle,
888 &IoStatusBlock,
889 &FileInformation,
890 sizeof(FILE_NETWORK_OPEN_INFORMATION),
891 FileNetworkOpenInformation);
892 NtClose (FileHandle);
893
894 if (!NT_SUCCESS (Status))
895 {
896 DPRINT1 ("NtQueryInformationFile() failed (Status %lx)\n", Status);
897 SetLastErrorByStatus (Status);
898 return FALSE;
899 }
900
901 FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation;
902 FileAttributeData->dwFileAttributes = FileInformation.FileAttributes;
903 FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart;
904 FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart;
905 FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart;
906 FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart;
907 FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart;
908 FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart;
909 FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart;
910 FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart;
911
912 return TRUE;
913 }
914
915 /*
916 * @implemented
917 */
918 BOOL STDCALL
919 GetFileAttributesExA(LPCSTR lpFileName,
920 GET_FILEEX_INFO_LEVELS fInfoLevelId,
921 LPVOID lpFileInformation)
922 {
923 PWCHAR FileNameW;
924
925 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
926 return FALSE;
927
928 return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
929 }
930
931
932 /*
933 * @implemented
934 */
935 DWORD STDCALL
936 GetFileAttributesA(LPCSTR lpFileName)
937 {
938 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
939 PWSTR FileNameW;
940 BOOL ret;
941
942 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
943 return INVALID_FILE_ATTRIBUTES;
944
945 ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
946
947 return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
948 }
949
950
951 /*
952 * @implemented
953 */
954 DWORD STDCALL
955 GetFileAttributesW(LPCWSTR lpFileName)
956 {
957 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
958 BOOL Result;
959
960 DPRINT ("GetFileAttributeW(%S) called\n", lpFileName);
961
962 Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
963
964 return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
965 }
966
967
968 /*
969 * @implemented
970 */
971 BOOL STDCALL
972 GetFileAttributesByHandle(IN HANDLE hFile,
973 OUT LPDWORD dwFileAttributes,
974 IN DWORD dwFlags)
975 {
976 FILE_BASIC_INFORMATION FileBasic;
977 IO_STATUS_BLOCK IoStatusBlock;
978 NTSTATUS Status;
979
980 UNREFERENCED_PARAMETER(dwFlags);
981
982 if (IsConsoleHandle(hFile))
983 {
984 SetLastError(ERROR_INVALID_HANDLE);
985 return FALSE;
986 }
987
988 Status = NtQueryInformationFile(hFile,
989 &IoStatusBlock,
990 &FileBasic,
991 sizeof(FileBasic),
992 FileBasicInformation);
993 if (NT_SUCCESS(Status))
994 {
995 *dwFileAttributes = FileBasic.FileAttributes;
996 return TRUE;
997 }
998
999 SetLastErrorByStatus(Status);
1000 return FALSE;
1001 }
1002
1003
1004 /*
1005 * @implemented
1006 */
1007 BOOL STDCALL
1008 SetFileAttributesByHandle(IN HANDLE hFile,
1009 IN DWORD dwFileAttributes,
1010 IN DWORD dwFlags)
1011 {
1012 FILE_BASIC_INFORMATION FileBasic;
1013 IO_STATUS_BLOCK IoStatusBlock;
1014 NTSTATUS Status;
1015
1016 UNREFERENCED_PARAMETER(dwFlags);
1017
1018 if (IsConsoleHandle(hFile))
1019 {
1020 SetLastError(ERROR_INVALID_HANDLE);
1021 return FALSE;
1022 }
1023
1024 Status = NtQueryInformationFile(hFile,
1025 &IoStatusBlock,
1026 &FileBasic,
1027 sizeof(FileBasic),
1028 FileBasicInformation);
1029 if (NT_SUCCESS(Status))
1030 {
1031 FileBasic.FileAttributes = dwFileAttributes;
1032
1033 Status = NtSetInformationFile(hFile,
1034 &IoStatusBlock,
1035 &FileBasic,
1036 sizeof(FileBasic),
1037 FileBasicInformation);
1038 }
1039
1040 if (!NT_SUCCESS(Status))
1041 {
1042 SetLastErrorByStatus(Status);
1043 return FALSE;
1044 }
1045
1046 return TRUE;
1047 }
1048
1049
1050 /*
1051 * @implemented
1052 */
1053 BOOL STDCALL
1054 SetFileAttributesA(
1055 LPCSTR lpFileName,
1056 DWORD dwFileAttributes)
1057 {
1058 PWCHAR FileNameW;
1059
1060 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
1061 return FALSE;
1062
1063 return SetFileAttributesW(FileNameW, dwFileAttributes);
1064 }
1065
1066
1067 /*
1068 * @implemented
1069 */
1070 BOOL STDCALL
1071 SetFileAttributesW(LPCWSTR lpFileName,
1072 DWORD dwFileAttributes)
1073 {
1074 FILE_BASIC_INFORMATION FileInformation;
1075 OBJECT_ATTRIBUTES ObjectAttributes;
1076 IO_STATUS_BLOCK IoStatusBlock;
1077 UNICODE_STRING FileName;
1078 HANDLE FileHandle;
1079 NTSTATUS Status;
1080
1081 DPRINT ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
1082
1083 /* Validate and translate the filename */
1084 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
1085 &FileName,
1086 NULL,
1087 NULL))
1088 {
1089 DPRINT ("Invalid path\n");
1090 SetLastError (ERROR_BAD_PATHNAME);
1091 return FALSE;
1092 }
1093 DPRINT ("FileName: \'%wZ\'\n", &FileName);
1094
1095 /* build the object attributes */
1096 InitializeObjectAttributes (&ObjectAttributes,
1097 &FileName,
1098 OBJ_CASE_INSENSITIVE,
1099 NULL,
1100 NULL);
1101
1102 /* Open the file */
1103 Status = NtOpenFile (&FileHandle,
1104 SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
1105 &ObjectAttributes,
1106 &IoStatusBlock,
1107 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1108 FILE_SYNCHRONOUS_IO_NONALERT);
1109 RtlFreeUnicodeString (&FileName);
1110 if (!NT_SUCCESS (Status))
1111 {
1112 DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
1113 SetLastErrorByStatus (Status);
1114 return FALSE;
1115 }
1116
1117 Status = NtQueryInformationFile(FileHandle,
1118 &IoStatusBlock,
1119 &FileInformation,
1120 sizeof(FILE_BASIC_INFORMATION),
1121 FileBasicInformation);
1122 if (!NT_SUCCESS(Status))
1123 {
1124 DPRINT ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
1125 NtClose (FileHandle);
1126 SetLastErrorByStatus (Status);
1127 return FALSE;
1128 }
1129
1130 FileInformation.FileAttributes = dwFileAttributes;
1131 Status = NtSetInformationFile(FileHandle,
1132 &IoStatusBlock,
1133 &FileInformation,
1134 sizeof(FILE_BASIC_INFORMATION),
1135 FileBasicInformation);
1136 NtClose (FileHandle);
1137 if (!NT_SUCCESS(Status))
1138 {
1139 DPRINT ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
1140 SetLastErrorByStatus (Status);
1141 return FALSE;
1142 }
1143
1144 return TRUE;
1145 }
1146
1147
1148
1149
1150 /***********************************************************************
1151 * GetTempFileNameA (KERNEL32.@)
1152 */
1153 UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
1154 {
1155 WCHAR BufferW[MAX_PATH];
1156 PWCHAR PathW;
1157 WCHAR PrefixW[3+1];
1158 UINT ret;
1159
1160 if (!(PathW = FilenameA2W(path, FALSE)))
1161 return 0;
1162
1163 if (prefix)
1164 FilenameA2W_N(PrefixW, 3+1, prefix, -1);
1165
1166 ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
1167
1168 if (ret)
1169 FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
1170
1171 return ret;
1172 }
1173
1174 /***********************************************************************
1175 * GetTempFileNameW (KERNEL32.@)
1176 */
1177 UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer )
1178 {
1179 static const WCHAR formatW[] = L"%x.tmp";
1180
1181 int i;
1182 LPWSTR p;
1183
1184 if ( !path || !prefix || !buffer )
1185 {
1186 SetLastError( ERROR_INVALID_PARAMETER );
1187 return 0;
1188 }
1189
1190 wcscpy( buffer, path );
1191 p = buffer + wcslen(buffer);
1192
1193 /* add a \, if there isn't one */
1194 if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
1195
1196 for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
1197
1198 unique &= 0xffff;
1199
1200 if (unique) swprintf( p, formatW, unique );
1201 else
1202 {
1203 /* get a "random" unique number and try to create the file */
1204 HANDLE handle;
1205 UINT num = GetTickCount() & 0xffff;
1206
1207 if (!num) num = 1;
1208 unique = num;
1209 do
1210 {
1211 swprintf( p, formatW, unique );
1212 handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
1213 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1214 if (handle != INVALID_HANDLE_VALUE)
1215 { /* We created it */
1216 DPRINT("created %S\n", buffer);
1217 CloseHandle( handle );
1218 break;
1219 }
1220 if (GetLastError() != ERROR_FILE_EXISTS &&
1221 GetLastError() != ERROR_SHARING_VIOLATION)
1222 break; /* No need to go on */
1223 if (!(++unique & 0xffff)) unique = 1;
1224 } while (unique != num);
1225 }
1226
1227 DPRINT("returning %S\n", buffer);
1228 return unique;
1229 }
1230
1231
1232
1233
1234
1235 /*
1236 * @implemented
1237 */
1238 BOOL STDCALL
1239 GetFileTime(HANDLE hFile,
1240 LPFILETIME lpCreationTime,
1241 LPFILETIME lpLastAccessTime,
1242 LPFILETIME lpLastWriteTime)
1243 {
1244 IO_STATUS_BLOCK IoStatusBlock;
1245 FILE_BASIC_INFORMATION FileBasic;
1246 NTSTATUS Status;
1247
1248 if(IsConsoleHandle(hFile))
1249 {
1250 SetLastError(ERROR_INVALID_HANDLE);
1251 return FALSE;
1252 }
1253
1254 Status = NtQueryInformationFile(hFile,
1255 &IoStatusBlock,
1256 &FileBasic,
1257 sizeof(FILE_BASIC_INFORMATION),
1258 FileBasicInformation);
1259 if (!NT_SUCCESS(Status))
1260 {
1261 SetLastErrorByStatus(Status);
1262 return FALSE;
1263 }
1264
1265 if (lpCreationTime)
1266 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
1267 if (lpLastAccessTime)
1268 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
1269 if (lpLastWriteTime)
1270 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
1271
1272 return TRUE;
1273 }
1274
1275
1276 /*
1277 * @implemented
1278 */
1279 BOOL STDCALL
1280 SetFileTime(HANDLE hFile,
1281 CONST FILETIME *lpCreationTime,
1282 CONST FILETIME *lpLastAccessTime,
1283 CONST FILETIME *lpLastWriteTime)
1284 {
1285 FILE_BASIC_INFORMATION FileBasic;
1286 IO_STATUS_BLOCK IoStatusBlock;
1287 NTSTATUS Status;
1288
1289 if(IsConsoleHandle(hFile))
1290 {
1291 SetLastError(ERROR_INVALID_HANDLE);
1292 return FALSE;
1293 }
1294
1295 Status = NtQueryInformationFile(hFile,
1296 &IoStatusBlock,
1297 &FileBasic,
1298 sizeof(FILE_BASIC_INFORMATION),
1299 FileBasicInformation);
1300 if (!NT_SUCCESS(Status))
1301 {
1302 SetLastErrorByStatus(Status);
1303 return FALSE;
1304 }
1305
1306 if (lpCreationTime)
1307 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
1308 if (lpLastAccessTime)
1309 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
1310 if (lpLastWriteTime)
1311 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
1312
1313 // should i initialize changetime ???
1314
1315 Status = NtSetInformationFile(hFile,
1316 &IoStatusBlock,
1317 &FileBasic,
1318 sizeof(FILE_BASIC_INFORMATION),
1319 FileBasicInformation);
1320 if (!NT_SUCCESS(Status))
1321 {
1322 SetLastErrorByStatus(Status);
1323 return FALSE;
1324 }
1325
1326 return TRUE;
1327 }
1328
1329
1330 /*
1331 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1332 *
1333 * @implemented
1334 */
1335 BOOL STDCALL
1336 SetEndOfFile(HANDLE hFile)
1337 {
1338 IO_STATUS_BLOCK IoStatusBlock;
1339 FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
1340 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
1341 FILE_POSITION_INFORMATION FilePosInfo;
1342 NTSTATUS Status;
1343
1344 if(IsConsoleHandle(hFile))
1345 {
1346 SetLastError(ERROR_INVALID_HANDLE);
1347 return FALSE;
1348 }
1349
1350 //get current position
1351 Status = NtQueryInformationFile(
1352 hFile,
1353 &IoStatusBlock,
1354 &FilePosInfo,
1355 sizeof(FILE_POSITION_INFORMATION),
1356 FilePositionInformation
1357 );
1358
1359 if (!NT_SUCCESS(Status)){
1360 SetLastErrorByStatus(Status);
1361 return FALSE;
1362 }
1363
1364 EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1365
1366 /*
1367 NOTE:
1368 This call is not supposed to free up any space after the eof marker
1369 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1370 But...most file systems dispatch both FileEndOfFileInformation
1371 and FileAllocationInformation as they were the same command.
1372
1373 */
1374 Status = NtSetInformationFile(
1375 hFile,
1376 &IoStatusBlock, //out
1377 &EndOfFileInfo,
1378 sizeof(FILE_END_OF_FILE_INFORMATION),
1379 FileEndOfFileInformation
1380 );
1381
1382 if (!NT_SUCCESS(Status)){
1383 SetLastErrorByStatus(Status);
1384 return FALSE;
1385 }
1386
1387 FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1388
1389
1390 Status = NtSetInformationFile(
1391 hFile,
1392 &IoStatusBlock, //out
1393 &FileAllocationInfo,
1394 sizeof(FILE_ALLOCATION_INFORMATION),
1395 FileAllocationInformation
1396 );
1397
1398 if (!NT_SUCCESS(Status)){
1399 SetLastErrorByStatus(Status);
1400 return FALSE;
1401 }
1402
1403 return TRUE;
1404
1405 }
1406
1407
1408 /*
1409 * @implemented
1410 */
1411 BOOL
1412 STDCALL
1413 SetFileValidData(
1414 HANDLE hFile,
1415 LONGLONG ValidDataLength
1416 )
1417 {
1418 IO_STATUS_BLOCK IoStatusBlock;
1419 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
1420 NTSTATUS Status;
1421
1422 ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
1423
1424 Status = NtSetInformationFile(
1425 hFile,
1426 &IoStatusBlock, //out
1427 &ValidDataLengthInformation,
1428 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
1429 FileValidDataLengthInformation
1430 );
1431
1432 if (!NT_SUCCESS(Status)){
1433 SetLastErrorByStatus(Status);
1434 return FALSE;
1435 }
1436
1437 return TRUE;
1438 }
1439
1440
1441
1442 /*
1443 * @implemented
1444 */
1445 BOOL
1446 STDCALL
1447 SetFileShortNameW(
1448 HANDLE hFile,
1449 LPCWSTR lpShortName)
1450 {
1451 NTSTATUS Status;
1452 ULONG NeededSize;
1453 UNICODE_STRING ShortName;
1454 IO_STATUS_BLOCK IoStatusBlock;
1455 PFILE_NAME_INFORMATION FileNameInformation;
1456
1457 if(IsConsoleHandle(hFile))
1458 {
1459 SetLastError(ERROR_INVALID_HANDLE);
1460 return FALSE;
1461 }
1462
1463 if(!lpShortName)
1464 {
1465 SetLastError(ERROR_INVALID_PARAMETER);
1466 return FALSE;
1467 }
1468
1469 RtlInitUnicodeString(&ShortName, lpShortName);
1470
1471 NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR);
1472 if(!(FileNameInformation = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize)))
1473 {
1474 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1475 return FALSE;
1476 }
1477
1478 FileNameInformation->FileNameLength = ShortName.Length;
1479 RtlCopyMemory(FileNameInformation->FileName, ShortName.Buffer, ShortName.Length);
1480
1481 Status = NtSetInformationFile(hFile,
1482 &IoStatusBlock, //out
1483 FileNameInformation,
1484 NeededSize,
1485 FileShortNameInformation);
1486
1487 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInformation);
1488 if(!NT_SUCCESS(Status))
1489 {
1490
1491 SetLastErrorByStatus(Status);
1492 }
1493
1494 return NT_SUCCESS(Status);
1495 }
1496
1497
1498 /*
1499 * @implemented
1500 */
1501 BOOL
1502 STDCALL
1503 SetFileShortNameA(
1504 HANDLE hFile,
1505 LPCSTR lpShortName
1506 )
1507 {
1508 PWCHAR ShortNameW;
1509
1510 if(IsConsoleHandle(hFile))
1511 {
1512 SetLastError(ERROR_INVALID_HANDLE);
1513 return FALSE;
1514 }
1515
1516 if(!lpShortName)
1517 {
1518 SetLastError(ERROR_INVALID_PARAMETER);
1519 return FALSE;
1520 }
1521
1522 if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
1523 return FALSE;
1524
1525 return SetFileShortNameW(hFile, ShortNameW);
1526 }
1527
1528
1529 /*
1530 * @implemented
1531 */
1532 BOOL
1533 STDCALL
1534 CheckNameLegalDOS8Dot3W(
1535 LPCWSTR lpName,
1536 LPSTR lpOemName OPTIONAL,
1537 DWORD OemNameSize OPTIONAL,
1538 PBOOL pbNameContainsSpaces OPTIONAL,
1539 PBOOL pbNameLegal
1540 )
1541 {
1542 UNICODE_STRING Name;
1543 ANSI_STRING AnsiName;
1544
1545 if(lpName == NULL ||
1546 (lpOemName == NULL && OemNameSize != 0) ||
1547 pbNameLegal == NULL)
1548 {
1549 SetLastError(ERROR_INVALID_PARAMETER);
1550 return FALSE;
1551 }
1552
1553 if(lpOemName != NULL)
1554 {
1555 AnsiName.Buffer = lpOemName;
1556 AnsiName.MaximumLength = OemNameSize * sizeof(CHAR);
1557 AnsiName.Length = 0;
1558 }
1559
1560 RtlInitUnicodeString(&Name, lpName);
1561
1562 *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
1563 (lpOemName ? &AnsiName : NULL),
1564 (BOOLEAN*)pbNameContainsSpaces);
1565
1566 return TRUE;
1567 }
1568
1569
1570 /*
1571 * @implemented
1572 */
1573 BOOL
1574 STDCALL
1575 CheckNameLegalDOS8Dot3A(
1576 LPCSTR lpName,
1577 LPSTR lpOemName OPTIONAL,
1578 DWORD OemNameSize OPTIONAL,
1579 PBOOL pbNameContainsSpaces OPTIONAL,
1580 PBOOL pbNameLegal
1581 )
1582 {
1583 UNICODE_STRING Name;
1584 ANSI_STRING AnsiName, AnsiInputName;
1585 NTSTATUS Status;
1586
1587 if(lpName == NULL ||
1588 (lpOemName == NULL && OemNameSize != 0) ||
1589 pbNameLegal == NULL)
1590 {
1591 SetLastError(ERROR_INVALID_PARAMETER);
1592 return FALSE;
1593 }
1594
1595 if(lpOemName != NULL)
1596 {
1597 AnsiName.Buffer = lpOemName;
1598 AnsiName.MaximumLength = OemNameSize * sizeof(CHAR);
1599 AnsiName.Length = 0;
1600 }
1601
1602 RtlInitAnsiString(&AnsiInputName, (LPSTR)lpName);
1603 if(bIsFileApiAnsi)
1604 Status = RtlAnsiStringToUnicodeString(&Name, &AnsiInputName, TRUE);
1605 else
1606 Status = RtlOemStringToUnicodeString(&Name, &AnsiInputName, TRUE);
1607
1608 if(!NT_SUCCESS(Status))
1609 {
1610 SetLastErrorByStatus(Status);
1611 return FALSE;
1612 }
1613
1614 *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
1615 (lpOemName ? &AnsiName : NULL),
1616 (BOOLEAN*)pbNameContainsSpaces);
1617
1618 RtlFreeUnicodeString(&Name);
1619
1620 return TRUE;
1621 }
1622
1623 /* EOF */