36de769a3196a56a2377f6d4a6944c92b86b3b02
[reactos.git] / reactos / lib / kernel32 / file / volume.c
1 /* $Id: volume.c,v 1.37 2004/01/23 16:37:11 ekohl Exp $
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 <kernel32/kernel32.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 = SharedUserData->DosDeviceMap;
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 = SharedUserData->DosDeviceMap;
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 return(SharedUserData->DosDeviceMap);
159 }
160
161
162 /*
163 * @implemented
164 */
165 BOOL STDCALL
166 GetDiskFreeSpaceA (
167 LPCSTR lpRootPathName,
168 LPDWORD lpSectorsPerCluster,
169 LPDWORD lpBytesPerSector,
170 LPDWORD lpNumberOfFreeClusters,
171 LPDWORD lpTotalNumberOfClusters
172 )
173 {
174 UNICODE_STRING RootPathNameU;
175 ANSI_STRING RootPathName;
176 BOOL Result;
177
178 RtlInitAnsiString (&RootPathName,
179 (LPSTR)lpRootPathName);
180
181 RtlInitUnicodeString (&RootPathNameU,
182 NULL);
183
184 if (lpRootPathName)
185 {
186 /* convert ansi (or oem) string to unicode */
187 if (bIsFileApiAnsi)
188 RtlAnsiStringToUnicodeString (&RootPathNameU,
189 &RootPathName,
190 TRUE);
191 else
192 RtlOemStringToUnicodeString (&RootPathNameU,
193 &RootPathName,
194 TRUE);
195 }
196
197 Result = GetDiskFreeSpaceW (RootPathNameU.Buffer,
198 lpSectorsPerCluster,
199 lpBytesPerSector,
200 lpNumberOfFreeClusters,
201 lpTotalNumberOfClusters);
202
203 if (lpRootPathName)
204 {
205 RtlFreeHeap (RtlGetProcessHeap (),
206 0,
207 RootPathNameU.Buffer);
208 }
209
210 return Result;
211 }
212
213
214 /*
215 * @implemented
216 */
217 BOOL STDCALL
218 GetDiskFreeSpaceW(
219 LPCWSTR lpRootPathName,
220 LPDWORD lpSectorsPerCluster,
221 LPDWORD lpBytesPerSector,
222 LPDWORD lpNumberOfFreeClusters,
223 LPDWORD lpTotalNumberOfClusters
224 )
225 {
226 FILE_FS_SIZE_INFORMATION FileFsSize;
227 IO_STATUS_BLOCK IoStatusBlock;
228 WCHAR RootPathName[MAX_PATH];
229 HANDLE hFile;
230 NTSTATUS errCode;
231
232 if (lpRootPathName)
233 {
234 wcsncpy (RootPathName, lpRootPathName, 3);
235 }
236 else
237 {
238 GetCurrentDirectoryW (MAX_PATH, RootPathName);
239 RootPathName[3] = 0;
240 }
241
242 hFile = InternalOpenDirW(RootPathName, FALSE);
243 if (INVALID_HANDLE_VALUE == hFile)
244 {
245 SetLastError(ERROR_PATH_NOT_FOUND);
246 return FALSE;
247 }
248
249 errCode = NtQueryVolumeInformationFile(hFile,
250 &IoStatusBlock,
251 &FileFsSize,
252 sizeof(FILE_FS_SIZE_INFORMATION),
253 FileFsSizeInformation);
254 if (!NT_SUCCESS(errCode))
255 {
256 CloseHandle(hFile);
257 SetLastErrorByStatus (errCode);
258 return FALSE;
259 }
260
261 *lpBytesPerSector = FileFsSize.BytesPerSector;
262 *lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
263 *lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
264 *lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
265 CloseHandle(hFile);
266 return TRUE;
267 }
268
269
270 /*
271 * @implemented
272 */
273 BOOL STDCALL
274 GetDiskFreeSpaceExA (
275 LPCSTR lpDirectoryName,
276 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
277 PULARGE_INTEGER lpTotalNumberOfBytes,
278 PULARGE_INTEGER lpTotalNumberOfFreeBytes
279 )
280 {
281 UNICODE_STRING DirectoryNameU;
282 ANSI_STRING DirectoryName;
283 BOOL Result;
284
285 RtlInitAnsiString (&DirectoryName,
286 (LPSTR)lpDirectoryName);
287
288 RtlInitUnicodeString (&DirectoryNameU,
289 NULL);
290
291 if (lpDirectoryName)
292 {
293 /* convert ansi (or oem) string to unicode */
294 if (bIsFileApiAnsi)
295 RtlAnsiStringToUnicodeString (&DirectoryNameU,
296 &DirectoryName,
297 TRUE);
298 else
299 RtlOemStringToUnicodeString (&DirectoryNameU,
300 &DirectoryName,
301 TRUE);
302 }
303
304 Result = GetDiskFreeSpaceExW (DirectoryNameU.Buffer,
305 lpFreeBytesAvailableToCaller,
306 lpTotalNumberOfBytes,
307 lpTotalNumberOfFreeBytes);
308
309 if (lpDirectoryName)
310 {
311 RtlFreeHeap (RtlGetProcessHeap (),
312 0,
313 DirectoryNameU.Buffer);
314 }
315
316 return Result;
317 }
318
319
320 /*
321 * @implemented
322 */
323 BOOL STDCALL
324 GetDiskFreeSpaceExW(
325 LPCWSTR lpDirectoryName,
326 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
327 PULARGE_INTEGER lpTotalNumberOfBytes,
328 PULARGE_INTEGER lpTotalNumberOfFreeBytes
329 )
330 {
331 FILE_FS_SIZE_INFORMATION FileFsSize;
332 IO_STATUS_BLOCK IoStatusBlock;
333 ULARGE_INTEGER BytesPerCluster;
334 WCHAR RootPathName[MAX_PATH];
335 HANDLE hFile;
336 NTSTATUS errCode;
337
338 if (lpDirectoryName)
339 {
340 wcsncpy (RootPathName, lpDirectoryName, 3);
341 }
342 else
343 {
344 GetCurrentDirectoryW (MAX_PATH, RootPathName);
345 RootPathName[3] = 0;
346 }
347
348 hFile = InternalOpenDirW(RootPathName, FALSE);
349 if (INVALID_HANDLE_VALUE == hFile)
350 {
351 return FALSE;
352 }
353
354 errCode = NtQueryVolumeInformationFile(hFile,
355 &IoStatusBlock,
356 &FileFsSize,
357 sizeof(FILE_FS_SIZE_INFORMATION),
358 FileFsSizeInformation);
359 if (!NT_SUCCESS(errCode))
360 {
361 CloseHandle(hFile);
362 SetLastErrorByStatus (errCode);
363 return FALSE;
364 }
365
366 BytesPerCluster.QuadPart =
367 FileFsSize.BytesPerSector * FileFsSize.SectorsPerAllocationUnit;
368
369 // FIXME: Use quota information
370 if (lpFreeBytesAvailableToCaller)
371 lpFreeBytesAvailableToCaller->QuadPart =
372 BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
373
374 if (lpTotalNumberOfBytes)
375 lpTotalNumberOfBytes->QuadPart =
376 BytesPerCluster.QuadPart * FileFsSize.TotalAllocationUnits.QuadPart;
377 if (lpTotalNumberOfFreeBytes)
378 lpTotalNumberOfFreeBytes->QuadPart =
379 BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
380
381 CloseHandle(hFile);
382 return TRUE;
383 }
384
385
386 /*
387 * @implemented
388 */
389 UINT STDCALL
390 GetDriveTypeA(LPCSTR lpRootPathName)
391 {
392 UNICODE_STRING RootPathNameU;
393 ANSI_STRING RootPathName;
394 UINT Result;
395
396 RtlInitAnsiString (&RootPathName,
397 (LPSTR)lpRootPathName);
398
399 /* convert ansi (or oem) string to unicode */
400 if (bIsFileApiAnsi)
401 RtlAnsiStringToUnicodeString (&RootPathNameU,
402 &RootPathName,
403 TRUE);
404 else
405 RtlOemStringToUnicodeString (&RootPathNameU,
406 &RootPathName,
407 TRUE);
408
409 Result = GetDriveTypeW (RootPathNameU.Buffer);
410
411 RtlFreeHeap (RtlGetProcessHeap (),
412 0,
413 RootPathNameU.Buffer);
414
415 return Result;
416 }
417
418
419 /*
420 * @implemented
421 */
422 UINT STDCALL
423 GetDriveTypeW(LPCWSTR lpRootPathName)
424 {
425 FILE_FS_DEVICE_INFORMATION FileFsDevice;
426 IO_STATUS_BLOCK IoStatusBlock;
427
428 HANDLE hFile;
429 NTSTATUS errCode;
430
431 hFile = InternalOpenDirW(lpRootPathName, FALSE);
432 if (hFile == INVALID_HANDLE_VALUE)
433 {
434 return DRIVE_NO_ROOT_DIR; /* According to WINE regression tests */
435 }
436
437 errCode = NtQueryVolumeInformationFile (hFile,
438 &IoStatusBlock,
439 &FileFsDevice,
440 sizeof(FILE_FS_DEVICE_INFORMATION),
441 FileFsDeviceInformation);
442 if (!NT_SUCCESS(errCode))
443 {
444 CloseHandle(hFile);
445 SetLastErrorByStatus (errCode);
446 return 0;
447 }
448 CloseHandle(hFile);
449 return (UINT)FileFsDevice.DeviceType;
450 }
451
452
453 /*
454 * @implemented
455 */
456 BOOL STDCALL
457 GetVolumeInformationA(
458 LPCSTR lpRootPathName,
459 LPSTR lpVolumeNameBuffer,
460 DWORD nVolumeNameSize,
461 LPDWORD lpVolumeSerialNumber,
462 LPDWORD lpMaximumComponentLength,
463 LPDWORD lpFileSystemFlags,
464 LPSTR lpFileSystemNameBuffer,
465 DWORD nFileSystemNameSize
466 )
467 {
468 UNICODE_STRING RootPathNameU;
469 UNICODE_STRING FileSystemNameU;
470 UNICODE_STRING VolumeNameU;
471 ANSI_STRING RootPathName;
472 ANSI_STRING VolumeName;
473 ANSI_STRING FileSystemName;
474 BOOL Result;
475
476 RtlInitAnsiString (&RootPathName,
477 (LPSTR)lpRootPathName);
478
479 /* convert ansi (or oem) string to unicode */
480 if (bIsFileApiAnsi)
481 RtlAnsiStringToUnicodeString (&RootPathNameU,
482 &RootPathName,
483 TRUE);
484 else
485 RtlOemStringToUnicodeString (&RootPathNameU,
486 &RootPathName,
487 TRUE);
488
489 if (lpVolumeNameBuffer)
490 {
491 VolumeNameU.Length = 0;
492 VolumeNameU.MaximumLength = nVolumeNameSize * sizeof(WCHAR);
493 VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
494 0,
495 VolumeNameU.MaximumLength);
496 }
497
498 if (lpFileSystemNameBuffer)
499 {
500 FileSystemNameU.Length = 0;
501 FileSystemNameU.MaximumLength = nFileSystemNameSize * sizeof(WCHAR);
502 FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
503 0,
504 FileSystemNameU.MaximumLength);
505 }
506
507 Result = GetVolumeInformationW (RootPathNameU.Buffer,
508 lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL,
509 nVolumeNameSize,
510 lpVolumeSerialNumber,
511 lpMaximumComponentLength,
512 lpFileSystemFlags,
513 lpFileSystemNameBuffer ? FileSystemNameU.Buffer : NULL,
514 nFileSystemNameSize);
515
516 if (Result)
517 {
518 if (lpVolumeNameBuffer)
519 {
520 VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR);
521 VolumeName.Length = 0;
522 VolumeName.MaximumLength = nVolumeNameSize;
523 VolumeName.Buffer = lpVolumeNameBuffer;
524 }
525
526 if (lpFileSystemNameBuffer)
527 {
528 FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR);
529 FileSystemName.Length = 0;
530 FileSystemName.MaximumLength = nFileSystemNameSize;
531 FileSystemName.Buffer = lpFileSystemNameBuffer;
532 }
533
534 /* convert unicode strings to ansi (or oem) */
535 if (bIsFileApiAnsi)
536 {
537 if (lpVolumeNameBuffer)
538 {
539 RtlUnicodeStringToAnsiString (&VolumeName,
540 &VolumeNameU,
541 FALSE);
542 }
543 if (lpFileSystemNameBuffer)
544 {
545 RtlUnicodeStringToAnsiString (&FileSystemName,
546 &FileSystemNameU,
547 FALSE);
548 }
549 }
550 else
551 {
552 if (lpVolumeNameBuffer)
553 {
554 RtlUnicodeStringToOemString (&VolumeName,
555 &VolumeNameU,
556 FALSE);
557 }
558 if (lpFileSystemNameBuffer)
559 {
560 RtlUnicodeStringToOemString (&FileSystemName,
561 &FileSystemNameU,
562 FALSE);
563 }
564 }
565 }
566
567 RtlFreeHeap (RtlGetProcessHeap (),
568 0,
569 RootPathNameU.Buffer);
570 if (lpVolumeNameBuffer)
571 {
572 RtlFreeHeap (RtlGetProcessHeap (),
573 0,
574 VolumeNameU.Buffer);
575 }
576 if (lpFileSystemNameBuffer)
577 {
578 RtlFreeHeap (RtlGetProcessHeap (),
579 0,
580 FileSystemNameU.Buffer);
581 }
582
583 return Result;
584 }
585
586 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION))
587
588 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
589
590 /*
591 * @implemented
592 */
593 BOOL STDCALL
594 GetVolumeInformationW(
595 LPCWSTR lpRootPathName,
596 LPWSTR lpVolumeNameBuffer,
597 DWORD nVolumeNameSize,
598 LPDWORD lpVolumeSerialNumber,
599 LPDWORD lpMaximumComponentLength,
600 LPDWORD lpFileSystemFlags,
601 LPWSTR lpFileSystemNameBuffer,
602 DWORD nFileSystemNameSize
603 )
604 {
605 PFILE_FS_VOLUME_INFORMATION FileFsVolume;
606 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
607 IO_STATUS_BLOCK IoStatusBlock;
608 WCHAR RootPathName[MAX_PATH];
609 UCHAR Buffer[max(FS_VOLUME_BUFFER_SIZE, FS_ATTRIBUTE_BUFFER_SIZE)];
610
611 HANDLE hFile;
612 NTSTATUS errCode;
613
614 FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
615 FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
616
617 DPRINT("FileFsVolume %p\n", FileFsVolume);
618 DPRINT("FileFsAttribute %p\n", FileFsAttribute);
619
620 if (!lpRootPathName || !wcscmp(lpRootPathName, L""))
621 {
622 GetCurrentDirectoryW (MAX_PATH, RootPathName);
623 RootPathName[3] = 0;
624 }
625 else
626 {
627 wcsncpy (RootPathName, lpRootPathName, min(MAX_PATH, wcslen(lpRootPathName) + 1));
628 }
629
630 hFile = InternalOpenDirW(RootPathName, FALSE);
631 if (hFile == INVALID_HANDLE_VALUE)
632 {
633 return FALSE;
634 }
635
636 DPRINT("hFile: %x\n", hFile);
637 errCode = NtQueryVolumeInformationFile(hFile,
638 &IoStatusBlock,
639 FileFsVolume,
640 FS_VOLUME_BUFFER_SIZE,
641 FileFsVolumeInformation);
642 if ( !NT_SUCCESS(errCode) )
643 {
644 DPRINT("Status: %x\n", errCode);
645 CloseHandle(hFile);
646 SetLastErrorByStatus (errCode);
647 return FALSE;
648 }
649
650 if (lpVolumeSerialNumber)
651 *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
652
653 if (lpVolumeNameBuffer)
654 {
655 if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR))
656 {
657 memcpy(lpVolumeNameBuffer,
658 FileFsVolume->VolumeLabel,
659 FileFsVolume->VolumeLabelLength);
660 lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0;
661 }
662 else
663 {
664 CloseHandle(hFile);
665 SetLastError(ERROR_MORE_DATA);
666 return FALSE;
667 }
668 }
669
670 errCode = NtQueryVolumeInformationFile (hFile,
671 &IoStatusBlock,
672 FileFsAttribute,
673 FS_ATTRIBUTE_BUFFER_SIZE,
674 FileFsAttributeInformation);
675 CloseHandle(hFile);
676 if (!NT_SUCCESS(errCode))
677 {
678 DPRINT("Status: %x\n", errCode);
679 SetLastErrorByStatus (errCode);
680 return FALSE;
681 }
682
683 if (lpFileSystemFlags)
684 *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
685 if (lpMaximumComponentLength)
686 *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
687 if (lpFileSystemNameBuffer)
688 {
689 if (nFileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
690 {
691 memcpy(lpFileSystemNameBuffer,
692 FileFsAttribute->FileSystemName,
693 FileFsAttribute->FileSystemNameLength);
694 lpFileSystemNameBuffer[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0;
695 }
696 else
697 {
698 SetLastError(ERROR_MORE_DATA);
699 return FALSE;
700 }
701 }
702 return TRUE;
703 }
704
705
706 /*
707 * @implemented
708 */
709 BOOL
710 STDCALL
711 SetVolumeLabelA (
712 LPCSTR lpRootPathName,
713 LPCSTR lpVolumeName
714 )
715 {
716 UNICODE_STRING RootPathNameU;
717 ANSI_STRING RootPathName;
718 UNICODE_STRING VolumeNameU;
719 ANSI_STRING VolumeName;
720 BOOL Result;
721
722 RtlInitAnsiString (&RootPathName,
723 (LPSTR)lpRootPathName);
724 RtlInitAnsiString (&VolumeName,
725 (LPSTR)lpVolumeName);
726
727 /* convert ansi (or oem) strings to unicode */
728 if (bIsFileApiAnsi)
729 {
730 RtlAnsiStringToUnicodeString (&RootPathNameU,
731 &RootPathName,
732 TRUE);
733 RtlAnsiStringToUnicodeString (&VolumeNameU,
734 &VolumeName,
735 TRUE);
736 }
737 else
738 {
739 RtlOemStringToUnicodeString (&RootPathNameU,
740 &RootPathName,
741 TRUE);
742 RtlOemStringToUnicodeString (&VolumeNameU,
743 &VolumeName,
744 TRUE);
745 }
746
747 Result = SetVolumeLabelW (RootPathNameU.Buffer,
748 VolumeNameU.Buffer);
749
750 RtlFreeHeap (RtlGetProcessHeap (),
751 0,
752 RootPathNameU.Buffer);
753 RtlFreeHeap (RtlGetProcessHeap (),
754 0,
755 VolumeNameU.Buffer);
756
757 return Result;
758 }
759
760
761 /*
762 * @implemented
763 */
764 BOOL STDCALL
765 SetVolumeLabelW(LPCWSTR lpRootPathName,
766 LPCWSTR lpVolumeName)
767 {
768 PFILE_FS_LABEL_INFORMATION LabelInfo;
769 IO_STATUS_BLOCK IoStatusBlock;
770 ULONG LabelLength;
771 HANDLE hFile;
772 NTSTATUS Status;
773
774 LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR);
775 LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(),
776 0,
777 sizeof(FILE_FS_LABEL_INFORMATION) +
778 LabelLength);
779 LabelInfo->VolumeLabelLength = LabelLength;
780 memcpy(LabelInfo->VolumeLabel,
781 lpVolumeName,
782 LabelLength);
783
784 hFile = InternalOpenDirW(lpRootPathName, TRUE);
785 if (INVALID_HANDLE_VALUE == hFile)
786 {
787 RtlFreeHeap(RtlGetProcessHeap(),
788 0,
789 LabelInfo);
790 return FALSE;
791 }
792
793 Status = NtSetVolumeInformationFile(hFile,
794 &IoStatusBlock,
795 LabelInfo,
796 sizeof(FILE_FS_LABEL_INFORMATION) +
797 LabelLength,
798 FileFsLabelInformation);
799
800 RtlFreeHeap(RtlGetProcessHeap(),
801 0,
802 LabelInfo);
803
804 if (!NT_SUCCESS(Status))
805 {
806 DPRINT("Status: %x\n", Status);
807 CloseHandle(hFile);
808 SetLastErrorByStatus(Status);
809 return FALSE;
810 }
811
812 CloseHandle(hFile);
813 return TRUE;
814 }
815
816 /* EOF */