migrate substitution keywords to SVN
[reactos.git] / reactos / lib / kernel32 / file / volume.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/volume.c
6 * PURPOSE: File volume functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * Erik Bos, Alexandre Julliard :
9 * GetLogicalDriveStringsA,
10 * GetLogicalDriveStringsW, GetLogicalDrives
11 * UPDATE HISTORY:
12 * Created 01/11/98
13 */
14 //WINE copyright notice:
15 /*
16 * DOS drives handling functions
17 *
18 * Copyright 1993 Erik Bos
19 * Copyright 1996 Alexandre Julliard
20 */
21
22 #include <k32.h>
23
24 #define NDEBUG
25 #include "../include/debug.h"
26
27
28 #define MAX_DOS_DRIVES 26
29
30
31 static HANDLE
32 InternalOpenDirW(LPCWSTR DirName,
33 BOOLEAN Write)
34 {
35 UNICODE_STRING NtPathU;
36 OBJECT_ATTRIBUTES ObjectAttributes;
37 NTSTATUS errCode;
38 IO_STATUS_BLOCK IoStatusBlock;
39 HANDLE hFile;
40
41 if (!RtlDosPathNameToNtPathName_U((LPWSTR)DirName,
42 &NtPathU,
43 NULL,
44 NULL))
45 {
46 DPRINT("Invalid path\n");
47 SetLastError(ERROR_BAD_PATHNAME);
48 return INVALID_HANDLE_VALUE;
49 }
50
51 InitializeObjectAttributes(&ObjectAttributes,
52 &NtPathU,
53 Write ? FILE_WRITE_ATTRIBUTES : FILE_READ_ATTRIBUTES,
54 NULL,
55 NULL);
56
57 errCode = NtCreateFile (&hFile,
58 Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ,
59 &ObjectAttributes,
60 &IoStatusBlock,
61 NULL,
62 0,
63 FILE_SHARE_READ|FILE_SHARE_WRITE,
64 FILE_OPEN,
65 0,
66 NULL,
67 0);
68
69 RtlFreeUnicodeString(&NtPathU);
70
71 if (!NT_SUCCESS(errCode))
72 {
73 SetLastErrorByStatus (errCode);
74 return INVALID_HANDLE_VALUE;
75 }
76 return hFile;
77 }
78
79
80 /*
81 * @implemented
82 */
83 DWORD STDCALL
84 GetLogicalDriveStringsA(DWORD nBufferLength,
85 LPSTR lpBuffer)
86 {
87 DWORD drive, count;
88 DWORD dwDriveMap;
89
90 dwDriveMap = GetLogicalDrives();
91
92 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
93 {
94 if (dwDriveMap & (1<<drive))
95 count++;
96 }
97
98
99 if (count * 4 * sizeof(char) <= nBufferLength)
100 {
101 LPSTR p = lpBuffer;
102
103 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
104 if (dwDriveMap & (1<<drive))
105 {
106 *p++ = 'A' + drive;
107 *p++ = ':';
108 *p++ = '\\';
109 *p++ = '\0';
110 }
111 *p = '\0';
112 }
113 return (count * 4 * sizeof(char));
114 }
115
116
117 /*
118 * @implemented
119 */
120 DWORD STDCALL
121 GetLogicalDriveStringsW(DWORD nBufferLength,
122 LPWSTR lpBuffer)
123 {
124 DWORD drive, count;
125 DWORD dwDriveMap;
126
127 dwDriveMap = GetLogicalDrives();
128
129 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
130 {
131 if (dwDriveMap & (1<<drive))
132 count++;
133 }
134
135 if (count * 4 * sizeof(WCHAR) <= nBufferLength)
136 {
137 LPWSTR p = lpBuffer;
138 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
139 if (dwDriveMap & (1<<drive))
140 {
141 *p++ = (WCHAR)('A' + drive);
142 *p++ = (WCHAR)':';
143 *p++ = (WCHAR)'\\';
144 *p++ = (WCHAR)'\0';
145 }
146 *p = (WCHAR)'\0';
147 }
148 return (count * 4 * sizeof(WCHAR));
149 }
150
151
152 /*
153 * @implemented
154 */
155 DWORD STDCALL
156 GetLogicalDrives(VOID)
157 {
158 NTSTATUS Status;
159 PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo;
160
161 /* Get the Device Map for this Process */
162 Status = NtQueryInformationProcess(NtCurrentProcess(),
163 ProcessDeviceMap,
164 &ProcessDeviceMapInfo,
165 sizeof(ProcessDeviceMapInfo),
166 NULL);
167
168 /* Return the Drive Map */
169 if (!NT_SUCCESS(Status))
170 {
171 SetLastErrorByStatus(Status);
172 return 0;
173 }
174
175 return ProcessDeviceMapInfo.Query.DriveMap;
176 }
177
178
179 /*
180 * @implemented
181 */
182 BOOL STDCALL
183 GetDiskFreeSpaceA (
184 LPCSTR lpRootPathName,
185 LPDWORD lpSectorsPerCluster,
186 LPDWORD lpBytesPerSector,
187 LPDWORD lpNumberOfFreeClusters,
188 LPDWORD lpTotalNumberOfClusters
189 )
190 {
191 UNICODE_STRING RootPathNameU;
192 ANSI_STRING RootPathName;
193 BOOL Result;
194
195 RtlInitAnsiString (&RootPathName,
196 (LPSTR)lpRootPathName);
197
198 RtlInitUnicodeString (&RootPathNameU,
199 NULL);
200
201 if (lpRootPathName)
202 {
203 /* convert ansi (or oem) string to unicode */
204 if (bIsFileApiAnsi)
205 RtlAnsiStringToUnicodeString (&RootPathNameU,
206 &RootPathName,
207 TRUE);
208 else
209 RtlOemStringToUnicodeString (&RootPathNameU,
210 &RootPathName,
211 TRUE);
212 }
213
214 Result = GetDiskFreeSpaceW (RootPathNameU.Buffer,
215 lpSectorsPerCluster,
216 lpBytesPerSector,
217 lpNumberOfFreeClusters,
218 lpTotalNumberOfClusters);
219
220 if (lpRootPathName)
221 {
222 RtlFreeHeap (RtlGetProcessHeap (),
223 0,
224 RootPathNameU.Buffer);
225 }
226
227 return Result;
228 }
229
230
231 /*
232 * @implemented
233 */
234 BOOL STDCALL
235 GetDiskFreeSpaceW(
236 LPCWSTR lpRootPathName,
237 LPDWORD lpSectorsPerCluster,
238 LPDWORD lpBytesPerSector,
239 LPDWORD lpNumberOfFreeClusters,
240 LPDWORD lpTotalNumberOfClusters
241 )
242 {
243 FILE_FS_SIZE_INFORMATION FileFsSize;
244 IO_STATUS_BLOCK IoStatusBlock;
245 WCHAR RootPathName[MAX_PATH];
246 HANDLE hFile;
247 NTSTATUS errCode;
248
249 if (lpRootPathName)
250 {
251 wcsncpy (RootPathName, lpRootPathName, 3);
252 }
253 else
254 {
255 GetCurrentDirectoryW (MAX_PATH, RootPathName);
256 }
257 RootPathName[3] = 0;
258
259 hFile = InternalOpenDirW(RootPathName, FALSE);
260 if (INVALID_HANDLE_VALUE == hFile)
261 {
262 SetLastError(ERROR_PATH_NOT_FOUND);
263 return FALSE;
264 }
265
266 errCode = NtQueryVolumeInformationFile(hFile,
267 &IoStatusBlock,
268 &FileFsSize,
269 sizeof(FILE_FS_SIZE_INFORMATION),
270 FileFsSizeInformation);
271 if (!NT_SUCCESS(errCode))
272 {
273 CloseHandle(hFile);
274 SetLastErrorByStatus (errCode);
275 return FALSE;
276 }
277
278 *lpBytesPerSector = FileFsSize.BytesPerSector;
279 *lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
280 *lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
281 *lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
282 CloseHandle(hFile);
283
284 return TRUE;
285 }
286
287
288 /*
289 * @implemented
290 */
291 BOOL STDCALL
292 GetDiskFreeSpaceExA (
293 LPCSTR lpDirectoryName,
294 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
295 PULARGE_INTEGER lpTotalNumberOfBytes,
296 PULARGE_INTEGER lpTotalNumberOfFreeBytes
297 )
298 {
299 UNICODE_STRING DirectoryNameU;
300 ANSI_STRING DirectoryName;
301 BOOL Result;
302
303 RtlInitAnsiString (&DirectoryName,
304 (LPSTR)lpDirectoryName);
305
306 RtlInitUnicodeString (&DirectoryNameU,
307 NULL);
308
309 if (lpDirectoryName)
310 {
311 /* convert ansi (or oem) string to unicode */
312 if (bIsFileApiAnsi)
313 RtlAnsiStringToUnicodeString (&DirectoryNameU,
314 &DirectoryName,
315 TRUE);
316 else
317 RtlOemStringToUnicodeString (&DirectoryNameU,
318 &DirectoryName,
319 TRUE);
320 }
321
322 Result = GetDiskFreeSpaceExW (DirectoryNameU.Buffer,
323 lpFreeBytesAvailableToCaller,
324 lpTotalNumberOfBytes,
325 lpTotalNumberOfFreeBytes);
326
327 if (lpDirectoryName)
328 {
329 RtlFreeHeap (RtlGetProcessHeap (),
330 0,
331 DirectoryNameU.Buffer);
332 }
333
334 return Result;
335 }
336
337
338 /*
339 * @implemented
340 */
341 BOOL STDCALL
342 GetDiskFreeSpaceExW(
343 LPCWSTR lpDirectoryName,
344 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
345 PULARGE_INTEGER lpTotalNumberOfBytes,
346 PULARGE_INTEGER lpTotalNumberOfFreeBytes
347 )
348 {
349 FILE_FS_SIZE_INFORMATION FileFsSize;
350 IO_STATUS_BLOCK IoStatusBlock;
351 ULARGE_INTEGER BytesPerCluster;
352 WCHAR RootPathName[MAX_PATH];
353 HANDLE hFile;
354 NTSTATUS errCode;
355
356 if (lpDirectoryName)
357 {
358 wcsncpy (RootPathName, lpDirectoryName, 3);
359 }
360 else
361 {
362 GetCurrentDirectoryW (MAX_PATH, RootPathName);
363 }
364 RootPathName[3] = 0;
365
366 hFile = InternalOpenDirW(RootPathName, FALSE);
367 if (INVALID_HANDLE_VALUE == hFile)
368 {
369 return FALSE;
370 }
371
372 errCode = NtQueryVolumeInformationFile(hFile,
373 &IoStatusBlock,
374 &FileFsSize,
375 sizeof(FILE_FS_SIZE_INFORMATION),
376 FileFsSizeInformation);
377 if (!NT_SUCCESS(errCode))
378 {
379 CloseHandle(hFile);
380 SetLastErrorByStatus (errCode);
381 return FALSE;
382 }
383
384 BytesPerCluster.QuadPart =
385 FileFsSize.BytesPerSector * FileFsSize.SectorsPerAllocationUnit;
386
387 // FIXME: Use quota information
388 if (lpFreeBytesAvailableToCaller)
389 lpFreeBytesAvailableToCaller->QuadPart =
390 BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
391
392 if (lpTotalNumberOfBytes)
393 lpTotalNumberOfBytes->QuadPart =
394 BytesPerCluster.QuadPart * FileFsSize.TotalAllocationUnits.QuadPart;
395 if (lpTotalNumberOfFreeBytes)
396 lpTotalNumberOfFreeBytes->QuadPart =
397 BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
398
399 CloseHandle(hFile);
400
401 return TRUE;
402 }
403
404
405 /*
406 * @implemented
407 */
408 UINT STDCALL
409 GetDriveTypeA(LPCSTR lpRootPathName)
410 {
411 UNICODE_STRING RootPathNameU;
412 ANSI_STRING RootPathName;
413 UINT Result;
414
415 RtlInitAnsiString (&RootPathName,
416 (LPSTR)lpRootPathName);
417
418 /* convert ansi (or oem) string to unicode */
419 if (bIsFileApiAnsi)
420 RtlAnsiStringToUnicodeString (&RootPathNameU,
421 &RootPathName,
422 TRUE);
423 else
424 RtlOemStringToUnicodeString (&RootPathNameU,
425 &RootPathName,
426 TRUE);
427
428 Result = GetDriveTypeW (RootPathNameU.Buffer);
429
430 RtlFreeHeap (RtlGetProcessHeap (),
431 0,
432 RootPathNameU.Buffer);
433
434 return Result;
435 }
436
437
438 /*
439 * @implemented
440 */
441 UINT STDCALL
442 GetDriveTypeW(LPCWSTR lpRootPathName)
443 {
444 FILE_FS_DEVICE_INFORMATION FileFsDevice;
445 IO_STATUS_BLOCK IoStatusBlock;
446
447 HANDLE hFile;
448 NTSTATUS errCode;
449
450 hFile = InternalOpenDirW(lpRootPathName, FALSE);
451 if (hFile == INVALID_HANDLE_VALUE)
452 {
453 return DRIVE_NO_ROOT_DIR; /* According to WINE regression tests */
454 }
455
456 errCode = NtQueryVolumeInformationFile (hFile,
457 &IoStatusBlock,
458 &FileFsDevice,
459 sizeof(FILE_FS_DEVICE_INFORMATION),
460 FileFsDeviceInformation);
461 if (!NT_SUCCESS(errCode))
462 {
463 CloseHandle(hFile);
464 SetLastErrorByStatus (errCode);
465 return 0;
466 }
467 CloseHandle(hFile);
468
469 switch (FileFsDevice.DeviceType)
470 {
471 case FILE_DEVICE_CD_ROM:
472 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
473 return DRIVE_CDROM;
474 case FILE_DEVICE_VIRTUAL_DISK:
475 return DRIVE_RAMDISK;
476 case FILE_DEVICE_NETWORK_FILE_SYSTEM:
477 return DRIVE_REMOTE;
478 case FILE_DEVICE_DISK:
479 case FILE_DEVICE_DISK_FILE_SYSTEM:
480 if (FileFsDevice.Characteristics & FILE_REMOTE_DEVICE)
481 return DRIVE_REMOTE;
482 if (FileFsDevice.Characteristics & FILE_REMOVABLE_MEDIA)
483 return DRIVE_REMOVABLE;
484 return DRIVE_FIXED;
485 }
486
487 DPRINT1("Returning DRIVE_UNKNOWN for device type %d\n", FileFsDevice.DeviceType);
488
489 return DRIVE_UNKNOWN;
490 }
491
492
493 /*
494 * @implemented
495 */
496 BOOL STDCALL
497 GetVolumeInformationA(
498 LPCSTR lpRootPathName,
499 LPSTR lpVolumeNameBuffer,
500 DWORD nVolumeNameSize,
501 LPDWORD lpVolumeSerialNumber,
502 LPDWORD lpMaximumComponentLength,
503 LPDWORD lpFileSystemFlags,
504 LPSTR lpFileSystemNameBuffer,
505 DWORD nFileSystemNameSize
506 )
507 {
508 UNICODE_STRING RootPathNameU;
509 UNICODE_STRING FileSystemNameU;
510 UNICODE_STRING VolumeNameU;
511 ANSI_STRING RootPathName;
512 ANSI_STRING VolumeName;
513 ANSI_STRING FileSystemName;
514 BOOL Result;
515
516 RtlInitAnsiString (&RootPathName,
517 (LPSTR)lpRootPathName);
518
519 /* convert ansi (or oem) string to unicode */
520 if (bIsFileApiAnsi)
521 RtlAnsiStringToUnicodeString (&RootPathNameU,
522 &RootPathName,
523 TRUE);
524 else
525 RtlOemStringToUnicodeString (&RootPathNameU,
526 &RootPathName,
527 TRUE);
528
529 if (lpVolumeNameBuffer)
530 {
531 VolumeNameU.Length = 0;
532 VolumeNameU.MaximumLength = nVolumeNameSize * sizeof(WCHAR);
533 VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
534 0,
535 VolumeNameU.MaximumLength);
536 }
537
538 if (lpFileSystemNameBuffer)
539 {
540 FileSystemNameU.Length = 0;
541 FileSystemNameU.MaximumLength = nFileSystemNameSize * sizeof(WCHAR);
542 FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
543 0,
544 FileSystemNameU.MaximumLength);
545 }
546
547 Result = GetVolumeInformationW (RootPathNameU.Buffer,
548 lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL,
549 nVolumeNameSize,
550 lpVolumeSerialNumber,
551 lpMaximumComponentLength,
552 lpFileSystemFlags,
553 lpFileSystemNameBuffer ? FileSystemNameU.Buffer : NULL,
554 nFileSystemNameSize);
555
556 if (Result)
557 {
558 if (lpVolumeNameBuffer)
559 {
560 VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR);
561 VolumeName.Length = 0;
562 VolumeName.MaximumLength = nVolumeNameSize;
563 VolumeName.Buffer = lpVolumeNameBuffer;
564 }
565
566 if (lpFileSystemNameBuffer)
567 {
568 FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR);
569 FileSystemName.Length = 0;
570 FileSystemName.MaximumLength = nFileSystemNameSize;
571 FileSystemName.Buffer = lpFileSystemNameBuffer;
572 }
573
574 /* convert unicode strings to ansi (or oem) */
575 if (bIsFileApiAnsi)
576 {
577 if (lpVolumeNameBuffer)
578 {
579 RtlUnicodeStringToAnsiString (&VolumeName,
580 &VolumeNameU,
581 FALSE);
582 }
583 if (lpFileSystemNameBuffer)
584 {
585 RtlUnicodeStringToAnsiString (&FileSystemName,
586 &FileSystemNameU,
587 FALSE);
588 }
589 }
590 else
591 {
592 if (lpVolumeNameBuffer)
593 {
594 RtlUnicodeStringToOemString (&VolumeName,
595 &VolumeNameU,
596 FALSE);
597 }
598 if (lpFileSystemNameBuffer)
599 {
600 RtlUnicodeStringToOemString (&FileSystemName,
601 &FileSystemNameU,
602 FALSE);
603 }
604 }
605 }
606
607 RtlFreeHeap (RtlGetProcessHeap (),
608 0,
609 RootPathNameU.Buffer);
610 if (lpVolumeNameBuffer)
611 {
612 RtlFreeHeap (RtlGetProcessHeap (),
613 0,
614 VolumeNameU.Buffer);
615 }
616 if (lpFileSystemNameBuffer)
617 {
618 RtlFreeHeap (RtlGetProcessHeap (),
619 0,
620 FileSystemNameU.Buffer);
621 }
622
623 return Result;
624 }
625
626 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION))
627
628 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
629
630 /*
631 * @implemented
632 */
633 BOOL STDCALL
634 GetVolumeInformationW(
635 LPCWSTR lpRootPathName,
636 LPWSTR lpVolumeNameBuffer,
637 DWORD nVolumeNameSize,
638 LPDWORD lpVolumeSerialNumber,
639 LPDWORD lpMaximumComponentLength,
640 LPDWORD lpFileSystemFlags,
641 LPWSTR lpFileSystemNameBuffer,
642 DWORD nFileSystemNameSize
643 )
644 {
645 PFILE_FS_VOLUME_INFORMATION FileFsVolume;
646 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
647 IO_STATUS_BLOCK IoStatusBlock;
648 WCHAR RootPathName[MAX_PATH];
649 UCHAR Buffer[max(FS_VOLUME_BUFFER_SIZE, FS_ATTRIBUTE_BUFFER_SIZE)];
650
651 HANDLE hFile;
652 NTSTATUS errCode;
653
654 FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
655 FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
656
657 DPRINT("FileFsVolume %p\n", FileFsVolume);
658 DPRINT("FileFsAttribute %p\n", FileFsAttribute);
659
660 if (!lpRootPathName || !wcscmp(lpRootPathName, L""))
661 {
662 GetCurrentDirectoryW (MAX_PATH, RootPathName);
663 }
664 else
665 {
666 wcsncpy (RootPathName, lpRootPathName, 3);
667 }
668 RootPathName[3] = 0;
669
670 hFile = InternalOpenDirW(RootPathName, FALSE);
671 if (hFile == INVALID_HANDLE_VALUE)
672 {
673 return FALSE;
674 }
675
676 DPRINT("hFile: %x\n", hFile);
677 errCode = NtQueryVolumeInformationFile(hFile,
678 &IoStatusBlock,
679 FileFsVolume,
680 FS_VOLUME_BUFFER_SIZE,
681 FileFsVolumeInformation);
682 if ( !NT_SUCCESS(errCode) )
683 {
684 DPRINT("Status: %x\n", errCode);
685 CloseHandle(hFile);
686 SetLastErrorByStatus (errCode);
687 return FALSE;
688 }
689
690 if (lpVolumeSerialNumber)
691 *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
692
693 if (lpVolumeNameBuffer)
694 {
695 if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR))
696 {
697 memcpy(lpVolumeNameBuffer,
698 FileFsVolume->VolumeLabel,
699 FileFsVolume->VolumeLabelLength);
700 lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0;
701 }
702 else
703 {
704 CloseHandle(hFile);
705 SetLastError(ERROR_MORE_DATA);
706 return FALSE;
707 }
708 }
709
710 errCode = NtQueryVolumeInformationFile (hFile,
711 &IoStatusBlock,
712 FileFsAttribute,
713 FS_ATTRIBUTE_BUFFER_SIZE,
714 FileFsAttributeInformation);
715 CloseHandle(hFile);
716 if (!NT_SUCCESS(errCode))
717 {
718 DPRINT("Status: %x\n", errCode);
719 SetLastErrorByStatus (errCode);
720 return FALSE;
721 }
722
723 if (lpFileSystemFlags)
724 *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
725 if (lpMaximumComponentLength)
726 *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
727 if (lpFileSystemNameBuffer)
728 {
729 if (nFileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
730 {
731 memcpy(lpFileSystemNameBuffer,
732 FileFsAttribute->FileSystemName,
733 FileFsAttribute->FileSystemNameLength);
734 lpFileSystemNameBuffer[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0;
735 }
736 else
737 {
738 SetLastError(ERROR_MORE_DATA);
739 return FALSE;
740 }
741 }
742 return TRUE;
743 }
744
745
746 /*
747 * @implemented
748 */
749 BOOL
750 STDCALL
751 SetVolumeLabelA (
752 LPCSTR lpRootPathName,
753 LPCSTR lpVolumeName
754 )
755 {
756 UNICODE_STRING RootPathNameU;
757 ANSI_STRING RootPathName;
758 UNICODE_STRING VolumeNameU;
759 ANSI_STRING VolumeName;
760 BOOL Result;
761
762 RtlInitAnsiString (&RootPathName,
763 (LPSTR)lpRootPathName);
764 RtlInitAnsiString (&VolumeName,
765 (LPSTR)lpVolumeName);
766
767 /* convert ansi (or oem) strings to unicode */
768 if (bIsFileApiAnsi)
769 {
770 RtlAnsiStringToUnicodeString (&RootPathNameU,
771 &RootPathName,
772 TRUE);
773 RtlAnsiStringToUnicodeString (&VolumeNameU,
774 &VolumeName,
775 TRUE);
776 }
777 else
778 {
779 RtlOemStringToUnicodeString (&RootPathNameU,
780 &RootPathName,
781 TRUE);
782 RtlOemStringToUnicodeString (&VolumeNameU,
783 &VolumeName,
784 TRUE);
785 }
786
787 Result = SetVolumeLabelW (RootPathNameU.Buffer,
788 VolumeNameU.Buffer);
789
790 RtlFreeHeap (RtlGetProcessHeap (),
791 0,
792 RootPathNameU.Buffer);
793 RtlFreeHeap (RtlGetProcessHeap (),
794 0,
795 VolumeNameU.Buffer);
796
797 return Result;
798 }
799
800
801 /*
802 * @implemented
803 */
804 BOOL STDCALL
805 SetVolumeLabelW(LPCWSTR lpRootPathName,
806 LPCWSTR lpVolumeName)
807 {
808 PFILE_FS_LABEL_INFORMATION LabelInfo;
809 IO_STATUS_BLOCK IoStatusBlock;
810 ULONG LabelLength;
811 HANDLE hFile;
812 NTSTATUS Status;
813
814 LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR);
815 LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(),
816 0,
817 sizeof(FILE_FS_LABEL_INFORMATION) +
818 LabelLength);
819 LabelInfo->VolumeLabelLength = LabelLength;
820 memcpy(LabelInfo->VolumeLabel,
821 lpVolumeName,
822 LabelLength);
823
824 hFile = InternalOpenDirW(lpRootPathName, TRUE);
825 if (INVALID_HANDLE_VALUE == hFile)
826 {
827 RtlFreeHeap(RtlGetProcessHeap(),
828 0,
829 LabelInfo);
830 return FALSE;
831 }
832
833 Status = NtSetVolumeInformationFile(hFile,
834 &IoStatusBlock,
835 LabelInfo,
836 sizeof(FILE_FS_LABEL_INFORMATION) +
837 LabelLength,
838 FileFsLabelInformation);
839
840 RtlFreeHeap(RtlGetProcessHeap(),
841 0,
842 LabelInfo);
843
844 if (!NT_SUCCESS(Status))
845 {
846 DPRINT("Status: %x\n", Status);
847 CloseHandle(hFile);
848 SetLastErrorByStatus(Status);
849 return FALSE;
850 }
851
852 CloseHandle(hFile);
853 return TRUE;
854 }
855
856 /* EOF */