Fix a handle leak.
[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 = (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 ((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 UNICODE_STRING FileName;
839 NTSTATUS Status;
840 WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
841
842 DPRINT("GetFileAttributesExW(%S) called\n", lpFileName);
843
844
845 if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
846 {
847 SetLastError(ERROR_INVALID_PARAMETER);
848 return FALSE;
849 }
850
851 /* Validate and translate the filename */
852 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
853 &FileName,
854 NULL,
855 NULL))
856 {
857 DPRINT1 ("Invalid path\n");
858 SetLastError (ERROR_BAD_PATHNAME);
859 return FALSE;
860 }
861
862 /* build the object attributes */
863 InitializeObjectAttributes (&ObjectAttributes,
864 &FileName,
865 OBJ_CASE_INSENSITIVE,
866 NULL,
867 NULL);
868
869 /* Get file attributes */
870 Status = NtQueryFullAttributesFile(&ObjectAttributes,
871 &FileInformation);
872
873 RtlFreeUnicodeString (&FileName);
874 if (!NT_SUCCESS (Status))
875 {
876 DPRINT ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status);
877 SetLastErrorByStatus (Status);
878 return FALSE;
879 }
880
881 FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation;
882 FileAttributeData->dwFileAttributes = FileInformation.FileAttributes;
883 FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart;
884 FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart;
885 FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart;
886 FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart;
887 FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart;
888 FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart;
889 FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart;
890 FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart;
891
892 return TRUE;
893 }
894
895 /*
896 * @implemented
897 */
898 BOOL STDCALL
899 GetFileAttributesExA(LPCSTR lpFileName,
900 GET_FILEEX_INFO_LEVELS fInfoLevelId,
901 LPVOID lpFileInformation)
902 {
903 PWCHAR FileNameW;
904
905 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
906 return FALSE;
907
908 return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
909 }
910
911
912 /*
913 * @implemented
914 */
915 DWORD STDCALL
916 GetFileAttributesA(LPCSTR lpFileName)
917 {
918 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
919 PWSTR FileNameW;
920 BOOL ret;
921
922 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
923 return INVALID_FILE_ATTRIBUTES;
924
925 ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
926
927 return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
928 }
929
930
931 /*
932 * @implemented
933 */
934 DWORD STDCALL
935 GetFileAttributesW(LPCWSTR lpFileName)
936 {
937 WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
938 BOOL Result;
939
940 DPRINT ("GetFileAttributeW(%S) called\n", lpFileName);
941
942 Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
943
944 return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
945 }
946
947
948 /*
949 * @implemented
950 */
951 BOOL STDCALL
952 GetFileAttributesByHandle(IN HANDLE hFile,
953 OUT LPDWORD dwFileAttributes,
954 IN DWORD dwFlags)
955 {
956 FILE_BASIC_INFORMATION FileBasic;
957 IO_STATUS_BLOCK IoStatusBlock;
958 NTSTATUS Status;
959
960 UNREFERENCED_PARAMETER(dwFlags);
961
962 if (IsConsoleHandle(hFile))
963 {
964 SetLastError(ERROR_INVALID_HANDLE);
965 return FALSE;
966 }
967
968 Status = NtQueryInformationFile(hFile,
969 &IoStatusBlock,
970 &FileBasic,
971 sizeof(FileBasic),
972 FileBasicInformation);
973 if (NT_SUCCESS(Status))
974 {
975 *dwFileAttributes = FileBasic.FileAttributes;
976 return TRUE;
977 }
978
979 SetLastErrorByStatus(Status);
980 return FALSE;
981 }
982
983
984 /*
985 * @implemented
986 */
987 BOOL STDCALL
988 SetFileAttributesByHandle(IN HANDLE hFile,
989 IN DWORD dwFileAttributes,
990 IN DWORD dwFlags)
991 {
992 FILE_BASIC_INFORMATION FileBasic;
993 IO_STATUS_BLOCK IoStatusBlock;
994 NTSTATUS Status;
995
996 UNREFERENCED_PARAMETER(dwFlags);
997
998 if (IsConsoleHandle(hFile))
999 {
1000 SetLastError(ERROR_INVALID_HANDLE);
1001 return FALSE;
1002 }
1003
1004 Status = NtQueryInformationFile(hFile,
1005 &IoStatusBlock,
1006 &FileBasic,
1007 sizeof(FileBasic),
1008 FileBasicInformation);
1009 if (NT_SUCCESS(Status))
1010 {
1011 FileBasic.FileAttributes = dwFileAttributes;
1012
1013 Status = NtSetInformationFile(hFile,
1014 &IoStatusBlock,
1015 &FileBasic,
1016 sizeof(FileBasic),
1017 FileBasicInformation);
1018 }
1019
1020 if (!NT_SUCCESS(Status))
1021 {
1022 SetLastErrorByStatus(Status);
1023 return FALSE;
1024 }
1025
1026 return TRUE;
1027 }
1028
1029
1030 /*
1031 * @implemented
1032 */
1033 BOOL STDCALL
1034 SetFileAttributesA(
1035 LPCSTR lpFileName,
1036 DWORD dwFileAttributes)
1037 {
1038 PWCHAR FileNameW;
1039
1040 if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
1041 return FALSE;
1042
1043 return SetFileAttributesW(FileNameW, dwFileAttributes);
1044 }
1045
1046
1047 /*
1048 * @implemented
1049 */
1050 BOOL STDCALL
1051 SetFileAttributesW(LPCWSTR lpFileName,
1052 DWORD dwFileAttributes)
1053 {
1054 FILE_BASIC_INFORMATION FileInformation;
1055 OBJECT_ATTRIBUTES ObjectAttributes;
1056 IO_STATUS_BLOCK IoStatusBlock;
1057 UNICODE_STRING FileName;
1058 HANDLE FileHandle;
1059 NTSTATUS Status;
1060
1061 DPRINT ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
1062
1063 /* Validate and translate the filename */
1064 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
1065 &FileName,
1066 NULL,
1067 NULL))
1068 {
1069 DPRINT ("Invalid path\n");
1070 SetLastError (ERROR_BAD_PATHNAME);
1071 return FALSE;
1072 }
1073 DPRINT ("FileName: \'%wZ\'\n", &FileName);
1074
1075 /* build the object attributes */
1076 InitializeObjectAttributes (&ObjectAttributes,
1077 &FileName,
1078 OBJ_CASE_INSENSITIVE,
1079 NULL,
1080 NULL);
1081
1082 /* Open the file */
1083 Status = NtOpenFile (&FileHandle,
1084 SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
1085 &ObjectAttributes,
1086 &IoStatusBlock,
1087 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1088 FILE_SYNCHRONOUS_IO_NONALERT);
1089 RtlFreeUnicodeString (&FileName);
1090 if (!NT_SUCCESS (Status))
1091 {
1092 DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
1093 SetLastErrorByStatus (Status);
1094 return FALSE;
1095 }
1096
1097 Status = NtQueryInformationFile(FileHandle,
1098 &IoStatusBlock,
1099 &FileInformation,
1100 sizeof(FILE_BASIC_INFORMATION),
1101 FileBasicInformation);
1102 if (!NT_SUCCESS(Status))
1103 {
1104 DPRINT ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
1105 NtClose (FileHandle);
1106 SetLastErrorByStatus (Status);
1107 return FALSE;
1108 }
1109
1110 FileInformation.FileAttributes = dwFileAttributes;
1111 Status = NtSetInformationFile(FileHandle,
1112 &IoStatusBlock,
1113 &FileInformation,
1114 sizeof(FILE_BASIC_INFORMATION),
1115 FileBasicInformation);
1116 NtClose (FileHandle);
1117 if (!NT_SUCCESS(Status))
1118 {
1119 DPRINT ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
1120 SetLastErrorByStatus (Status);
1121 return FALSE;
1122 }
1123
1124 return TRUE;
1125 }
1126
1127
1128
1129
1130 /***********************************************************************
1131 * GetTempFileNameA (KERNEL32.@)
1132 */
1133 UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
1134 {
1135 WCHAR BufferW[MAX_PATH];
1136 PWCHAR PathW;
1137 WCHAR PrefixW[3+1];
1138 UINT ret;
1139
1140 if (!(PathW = FilenameA2W(path, FALSE)))
1141 return 0;
1142
1143 if (prefix)
1144 FilenameA2W_N(PrefixW, 3+1, prefix, -1);
1145
1146 ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
1147
1148 if (ret)
1149 FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
1150
1151 return ret;
1152 }
1153
1154 /***********************************************************************
1155 * GetTempFileNameW (KERNEL32.@)
1156 */
1157 UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer )
1158 {
1159 static const WCHAR formatW[] = L"%x.tmp";
1160
1161 int i;
1162 LPWSTR p;
1163
1164 if ( !path || !prefix || !buffer )
1165 {
1166 SetLastError( ERROR_INVALID_PARAMETER );
1167 return 0;
1168 }
1169
1170 wcscpy( buffer, path );
1171 p = buffer + wcslen(buffer);
1172
1173 /* add a \, if there isn't one */
1174 if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
1175
1176 for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
1177
1178 unique &= 0xffff;
1179
1180 if (unique) swprintf( p, formatW, unique );
1181 else
1182 {
1183 /* get a "random" unique number and try to create the file */
1184 HANDLE handle;
1185 UINT num = GetTickCount() & 0xffff;
1186
1187 if (!num) num = 1;
1188 unique = num;
1189 do
1190 {
1191 swprintf( p, formatW, unique );
1192 handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
1193 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1194 if (handle != INVALID_HANDLE_VALUE)
1195 { /* We created it */
1196 DPRINT("created %S\n", buffer);
1197 CloseHandle( handle );
1198 break;
1199 }
1200 if (GetLastError() != ERROR_FILE_EXISTS &&
1201 GetLastError() != ERROR_SHARING_VIOLATION)
1202 break; /* No need to go on */
1203 if (!(++unique & 0xffff)) unique = 1;
1204 } while (unique != num);
1205 }
1206
1207 DPRINT("returning %S\n", buffer);
1208 return unique;
1209 }
1210
1211
1212
1213
1214
1215 /*
1216 * @implemented
1217 */
1218 BOOL STDCALL
1219 GetFileTime(HANDLE hFile,
1220 LPFILETIME lpCreationTime,
1221 LPFILETIME lpLastAccessTime,
1222 LPFILETIME lpLastWriteTime)
1223 {
1224 IO_STATUS_BLOCK IoStatusBlock;
1225 FILE_BASIC_INFORMATION FileBasic;
1226 NTSTATUS Status;
1227
1228 if(IsConsoleHandle(hFile))
1229 {
1230 SetLastError(ERROR_INVALID_HANDLE);
1231 return FALSE;
1232 }
1233
1234 Status = NtQueryInformationFile(hFile,
1235 &IoStatusBlock,
1236 &FileBasic,
1237 sizeof(FILE_BASIC_INFORMATION),
1238 FileBasicInformation);
1239 if (!NT_SUCCESS(Status))
1240 {
1241 SetLastErrorByStatus(Status);
1242 return FALSE;
1243 }
1244
1245 if (lpCreationTime)
1246 memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
1247 if (lpLastAccessTime)
1248 memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
1249 if (lpLastWriteTime)
1250 memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
1251
1252 return TRUE;
1253 }
1254
1255
1256 /*
1257 * @implemented
1258 */
1259 BOOL STDCALL
1260 SetFileTime(HANDLE hFile,
1261 CONST FILETIME *lpCreationTime,
1262 CONST FILETIME *lpLastAccessTime,
1263 CONST FILETIME *lpLastWriteTime)
1264 {
1265 FILE_BASIC_INFORMATION FileBasic;
1266 IO_STATUS_BLOCK IoStatusBlock;
1267 NTSTATUS Status;
1268
1269 if(IsConsoleHandle(hFile))
1270 {
1271 SetLastError(ERROR_INVALID_HANDLE);
1272 return FALSE;
1273 }
1274
1275 Status = NtQueryInformationFile(hFile,
1276 &IoStatusBlock,
1277 &FileBasic,
1278 sizeof(FILE_BASIC_INFORMATION),
1279 FileBasicInformation);
1280 if (!NT_SUCCESS(Status))
1281 {
1282 SetLastErrorByStatus(Status);
1283 return FALSE;
1284 }
1285
1286 if (lpCreationTime)
1287 memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
1288 if (lpLastAccessTime)
1289 memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
1290 if (lpLastWriteTime)
1291 memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
1292
1293 // should i initialize changetime ???
1294
1295 Status = NtSetInformationFile(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 return TRUE;
1307 }
1308
1309
1310 /*
1311 * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
1312 *
1313 * @implemented
1314 */
1315 BOOL STDCALL
1316 SetEndOfFile(HANDLE hFile)
1317 {
1318 IO_STATUS_BLOCK IoStatusBlock;
1319 FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
1320 FILE_ALLOCATION_INFORMATION FileAllocationInfo;
1321 FILE_POSITION_INFORMATION FilePosInfo;
1322 NTSTATUS Status;
1323
1324 if(IsConsoleHandle(hFile))
1325 {
1326 SetLastError(ERROR_INVALID_HANDLE);
1327 return FALSE;
1328 }
1329
1330 //get current position
1331 Status = NtQueryInformationFile(
1332 hFile,
1333 &IoStatusBlock,
1334 &FilePosInfo,
1335 sizeof(FILE_POSITION_INFORMATION),
1336 FilePositionInformation
1337 );
1338
1339 if (!NT_SUCCESS(Status)){
1340 SetLastErrorByStatus(Status);
1341 return FALSE;
1342 }
1343
1344 EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1345
1346 /*
1347 NOTE:
1348 This call is not supposed to free up any space after the eof marker
1349 if the file gets truncated. We have to deallocate the space explicitly afterwards.
1350 But...most file systems dispatch both FileEndOfFileInformation
1351 and FileAllocationInformation as they were the same command.
1352
1353 */
1354 Status = NtSetInformationFile(
1355 hFile,
1356 &IoStatusBlock, //out
1357 &EndOfFileInfo,
1358 sizeof(FILE_END_OF_FILE_INFORMATION),
1359 FileEndOfFileInformation
1360 );
1361
1362 if (!NT_SUCCESS(Status)){
1363 SetLastErrorByStatus(Status);
1364 return FALSE;
1365 }
1366
1367 FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
1368
1369
1370 Status = NtSetInformationFile(
1371 hFile,
1372 &IoStatusBlock, //out
1373 &FileAllocationInfo,
1374 sizeof(FILE_ALLOCATION_INFORMATION),
1375 FileAllocationInformation
1376 );
1377
1378 if (!NT_SUCCESS(Status)){
1379 SetLastErrorByStatus(Status);
1380 return FALSE;
1381 }
1382
1383 return TRUE;
1384
1385 }
1386
1387
1388 /*
1389 * @implemented
1390 */
1391 BOOL
1392 STDCALL
1393 SetFileValidData(
1394 HANDLE hFile,
1395 LONGLONG ValidDataLength
1396 )
1397 {
1398 IO_STATUS_BLOCK IoStatusBlock;
1399 FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
1400 NTSTATUS Status;
1401
1402 ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
1403
1404 Status = NtSetInformationFile(
1405 hFile,
1406 &IoStatusBlock, //out
1407 &ValidDataLengthInformation,
1408 sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
1409 FileValidDataLengthInformation
1410 );
1411
1412 if (!NT_SUCCESS(Status)){
1413 SetLastErrorByStatus(Status);
1414 return FALSE;
1415 }
1416
1417 return TRUE;
1418 }
1419
1420
1421
1422 /*
1423 * @implemented
1424 */
1425 BOOL
1426 STDCALL
1427 SetFileShortNameW(
1428 HANDLE hFile,
1429 LPCWSTR lpShortName)
1430 {
1431 NTSTATUS Status;
1432 ULONG NeededSize;
1433 UNICODE_STRING ShortName;
1434 IO_STATUS_BLOCK IoStatusBlock;
1435 PFILE_NAME_INFORMATION FileNameInformation;
1436
1437 if(IsConsoleHandle(hFile))
1438 {
1439 SetLastError(ERROR_INVALID_HANDLE);
1440 return FALSE;
1441 }
1442
1443 if(!lpShortName)
1444 {
1445 SetLastError(ERROR_INVALID_PARAMETER);
1446 return FALSE;
1447 }
1448
1449 RtlInitUnicodeString(&ShortName, lpShortName);
1450
1451 NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR);
1452 if(!(FileNameInformation = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize)))
1453 {
1454 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1455 return FALSE;
1456 }
1457
1458 FileNameInformation->FileNameLength = ShortName.Length;
1459 RtlCopyMemory(FileNameInformation->FileName, ShortName.Buffer, ShortName.Length);
1460
1461 Status = NtSetInformationFile(hFile,
1462 &IoStatusBlock, //out
1463 FileNameInformation,
1464 NeededSize,
1465 FileShortNameInformation);
1466
1467 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInformation);
1468 if(!NT_SUCCESS(Status))
1469 {
1470
1471 SetLastErrorByStatus(Status);
1472 }
1473
1474 return NT_SUCCESS(Status);
1475 }
1476
1477
1478 /*
1479 * @implemented
1480 */
1481 BOOL
1482 STDCALL
1483 SetFileShortNameA(
1484 HANDLE hFile,
1485 LPCSTR lpShortName
1486 )
1487 {
1488 PWCHAR ShortNameW;
1489
1490 if(IsConsoleHandle(hFile))
1491 {
1492 SetLastError(ERROR_INVALID_HANDLE);
1493 return FALSE;
1494 }
1495
1496 if(!lpShortName)
1497 {
1498 SetLastError(ERROR_INVALID_PARAMETER);
1499 return FALSE;
1500 }
1501
1502 if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
1503 return FALSE;
1504
1505 return SetFileShortNameW(hFile, ShortNameW);
1506 }
1507
1508
1509 /*
1510 * @implemented
1511 */
1512 BOOL
1513 STDCALL
1514 CheckNameLegalDOS8Dot3W(
1515 LPCWSTR lpName,
1516 LPSTR lpOemName OPTIONAL,
1517 DWORD OemNameSize OPTIONAL,
1518 PBOOL pbNameContainsSpaces OPTIONAL,
1519 PBOOL pbNameLegal
1520 )
1521 {
1522 UNICODE_STRING Name;
1523 ANSI_STRING AnsiName;
1524
1525 if(lpName == NULL ||
1526 (lpOemName == NULL && OemNameSize != 0) ||
1527 pbNameLegal == NULL)
1528 {
1529 SetLastError(ERROR_INVALID_PARAMETER);
1530 return FALSE;
1531 }
1532
1533 if(lpOemName != NULL)
1534 {
1535 AnsiName.Buffer = lpOemName;
1536 AnsiName.MaximumLength = OemNameSize * sizeof(CHAR);
1537 AnsiName.Length = 0;
1538 }
1539
1540 RtlInitUnicodeString(&Name, lpName);
1541
1542 *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
1543 (lpOemName ? &AnsiName : NULL),
1544 (BOOLEAN*)pbNameContainsSpaces);
1545
1546 return TRUE;
1547 }
1548
1549
1550 /*
1551 * @implemented
1552 */
1553 BOOL
1554 STDCALL
1555 CheckNameLegalDOS8Dot3A(
1556 LPCSTR lpName,
1557 LPSTR lpOemName OPTIONAL,
1558 DWORD OemNameSize OPTIONAL,
1559 PBOOL pbNameContainsSpaces OPTIONAL,
1560 PBOOL pbNameLegal
1561 )
1562 {
1563 UNICODE_STRING Name;
1564 ANSI_STRING AnsiName, AnsiInputName;
1565 NTSTATUS Status;
1566
1567 if(lpName == NULL ||
1568 (lpOemName == NULL && OemNameSize != 0) ||
1569 pbNameLegal == NULL)
1570 {
1571 SetLastError(ERROR_INVALID_PARAMETER);
1572 return FALSE;
1573 }
1574
1575 if(lpOemName != NULL)
1576 {
1577 AnsiName.Buffer = lpOemName;
1578 AnsiName.MaximumLength = OemNameSize * sizeof(CHAR);
1579 AnsiName.Length = 0;
1580 }
1581
1582 RtlInitAnsiString(&AnsiInputName, (LPSTR)lpName);
1583 if(bIsFileApiAnsi)
1584 Status = RtlAnsiStringToUnicodeString(&Name, &AnsiInputName, TRUE);
1585 else
1586 Status = RtlOemStringToUnicodeString(&Name, &AnsiInputName, TRUE);
1587
1588 if(!NT_SUCCESS(Status))
1589 {
1590 SetLastErrorByStatus(Status);
1591 return FALSE;
1592 }
1593
1594 *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
1595 (lpOemName ? &AnsiName : NULL),
1596 (BOOLEAN*)pbNameContainsSpaces);
1597
1598 RtlFreeUnicodeString(&Name);
1599
1600 return TRUE;
1601 }
1602
1603 /* EOF */