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