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