1 /* $Id: volume.c,v 1.30 2003/07/20 09:40:13 hbirr Exp $
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
14 //WINE copyright notice:
16 * DOS drives handling functions
18 * Copyright 1993 Erik Bos
19 * Copyright 1996 Alexandre Julliard
25 #include <kernel32/kernel32.h>
28 #define MAX_DOS_DRIVES 26
32 InternalOpenDirW(LPCWSTR DirName
,
35 UNICODE_STRING NtPathU
;
36 OBJECT_ATTRIBUTES ObjectAttributes
;
38 IO_STATUS_BLOCK IoStatusBlock
;
41 if (!RtlDosPathNameToNtPathName_U((LPWSTR
)DirName
,
46 DPRINT("Invalid path\n");
47 SetLastError(ERROR_BAD_PATHNAME
);
48 return INVALID_HANDLE_VALUE
;
51 InitializeObjectAttributes(&ObjectAttributes
,
53 Write
? FILE_WRITE_ATTRIBUTES
: FILE_READ_ATTRIBUTES
,
57 errCode
= NtCreateFile (&hFile
,
58 Write
? FILE_GENERIC_WRITE
: FILE_GENERIC_READ
,
63 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
69 RtlFreeUnicodeString(&NtPathU
);
71 if (!NT_SUCCESS(errCode
))
73 SetLastErrorByStatus (errCode
);
74 return INVALID_HANDLE_VALUE
;
84 GetLogicalDriveStringsA(DWORD nBufferLength
,
90 dwDriveMap
= SharedUserData
->DosDeviceMap
;
92 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
94 if (dwDriveMap
& (1<<drive
))
99 if (count
* 4 * sizeof(char) <= nBufferLength
)
103 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
104 if (dwDriveMap
& (1<<drive
))
113 return (count
* 4 * sizeof(char));
121 GetLogicalDriveStringsW(DWORD nBufferLength
,
127 dwDriveMap
= SharedUserData
->DosDeviceMap
;
129 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
131 if (dwDriveMap
& (1<<drive
))
135 if (count
* 4 * sizeof(WCHAR
) <= nBufferLength
)
138 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
139 if (dwDriveMap
& (1<<drive
))
141 *p
++ = (WCHAR
)('A' + drive
);
148 return (count
* 4 * sizeof(WCHAR
));
156 GetLogicalDrives(VOID
)
158 return(SharedUserData
->DosDeviceMap
);
167 LPCSTR lpRootPathName
,
168 LPDWORD lpSectorsPerCluster
,
169 LPDWORD lpBytesPerSector
,
170 LPDWORD lpNumberOfFreeClusters
,
171 LPDWORD lpTotalNumberOfClusters
174 UNICODE_STRING RootPathNameU
;
175 ANSI_STRING RootPathName
;
178 RtlInitAnsiString (&RootPathName
,
179 (LPSTR
)lpRootPathName
);
181 RtlInitUnicodeString (&RootPathNameU
,
186 /* convert ansi (or oem) string to unicode */
188 RtlAnsiStringToUnicodeString (&RootPathNameU
,
192 RtlOemStringToUnicodeString (&RootPathNameU
,
197 Result
= GetDiskFreeSpaceW (RootPathNameU
.Buffer
,
200 lpNumberOfFreeClusters
,
201 lpTotalNumberOfClusters
);
205 RtlFreeHeap (RtlGetProcessHeap (),
207 RootPathNameU
.Buffer
);
219 LPCWSTR lpRootPathName
,
220 LPDWORD lpSectorsPerCluster
,
221 LPDWORD lpBytesPerSector
,
222 LPDWORD lpNumberOfFreeClusters
,
223 LPDWORD lpTotalNumberOfClusters
226 FILE_FS_SIZE_INFORMATION FileFsSize
;
227 IO_STATUS_BLOCK IoStatusBlock
;
228 WCHAR RootPathName
[MAX_PATH
];
234 wcsncpy (RootPathName
, lpRootPathName
, 3);
238 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
242 hFile
= InternalOpenDirW(lpRootPathName
, FALSE
);
243 if (INVALID_HANDLE_VALUE
== hFile
)
248 errCode
= NtQueryVolumeInformationFile(hFile
,
251 sizeof(FILE_FS_SIZE_INFORMATION
),
252 FileFsSizeInformation
);
253 if (!NT_SUCCESS(errCode
))
256 SetLastErrorByStatus (errCode
);
260 *lpBytesPerSector
= FileFsSize
.BytesPerSector
;
261 *lpSectorsPerCluster
= FileFsSize
.SectorsPerAllocationUnit
;
262 *lpNumberOfFreeClusters
= FileFsSize
.AvailableAllocationUnits
.u
.LowPart
;
263 *lpTotalNumberOfClusters
= FileFsSize
.TotalAllocationUnits
.u
.LowPart
;
273 GetDiskFreeSpaceExA (
274 LPCSTR lpDirectoryName
,
275 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
276 PULARGE_INTEGER lpTotalNumberOfBytes
,
277 PULARGE_INTEGER lpTotalNumberOfFreeBytes
280 UNICODE_STRING DirectoryNameU
;
281 ANSI_STRING DirectoryName
;
284 RtlInitAnsiString (&DirectoryName
,
285 (LPSTR
)lpDirectoryName
);
287 RtlInitUnicodeString (&DirectoryNameU
,
292 /* convert ansi (or oem) string to unicode */
294 RtlAnsiStringToUnicodeString (&DirectoryNameU
,
298 RtlOemStringToUnicodeString (&DirectoryNameU
,
303 Result
= GetDiskFreeSpaceExW (DirectoryNameU
.Buffer
,
304 lpFreeBytesAvailableToCaller
,
305 lpTotalNumberOfBytes
,
306 lpTotalNumberOfFreeBytes
);
310 RtlFreeHeap (RtlGetProcessHeap (),
312 DirectoryNameU
.Buffer
);
324 LPCWSTR lpDirectoryName
,
325 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
326 PULARGE_INTEGER lpTotalNumberOfBytes
,
327 PULARGE_INTEGER lpTotalNumberOfFreeBytes
330 FILE_FS_SIZE_INFORMATION FileFsSize
;
331 IO_STATUS_BLOCK IoStatusBlock
;
332 ULARGE_INTEGER BytesPerCluster
;
333 WCHAR RootPathName
[MAX_PATH
];
339 wcsncpy (RootPathName
, lpDirectoryName
, 3);
343 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
347 hFile
= InternalOpenDirW(lpDirectoryName
, FALSE
);
348 if (INVALID_HANDLE_VALUE
== hFile
)
353 errCode
= NtQueryVolumeInformationFile(hFile
,
356 sizeof(FILE_FS_SIZE_INFORMATION
),
357 FileFsSizeInformation
);
358 if (!NT_SUCCESS(errCode
))
361 SetLastErrorByStatus (errCode
);
365 BytesPerCluster
.QuadPart
=
366 FileFsSize
.BytesPerSector
* FileFsSize
.SectorsPerAllocationUnit
;
368 // FIXME: Use quota information
369 if (lpFreeBytesAvailableToCaller
)
370 lpFreeBytesAvailableToCaller
->QuadPart
=
371 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
373 if (lpTotalNumberOfBytes
)
374 lpTotalNumberOfBytes
->QuadPart
=
375 BytesPerCluster
.QuadPart
* FileFsSize
.TotalAllocationUnits
.QuadPart
;
376 if (lpTotalNumberOfFreeBytes
)
377 lpTotalNumberOfFreeBytes
->QuadPart
=
378 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
389 GetDriveTypeA(LPCSTR lpRootPathName
)
391 UNICODE_STRING RootPathNameU
;
392 ANSI_STRING RootPathName
;
395 RtlInitAnsiString (&RootPathName
,
396 (LPSTR
)lpRootPathName
);
398 /* convert ansi (or oem) string to unicode */
400 RtlAnsiStringToUnicodeString (&RootPathNameU
,
404 RtlOemStringToUnicodeString (&RootPathNameU
,
408 Result
= GetDriveTypeW (RootPathNameU
.Buffer
);
410 RtlFreeHeap (RtlGetProcessHeap (),
412 RootPathNameU
.Buffer
);
422 GetDriveTypeW(LPCWSTR lpRootPathName
)
424 FILE_FS_DEVICE_INFORMATION FileFsDevice
;
425 IO_STATUS_BLOCK IoStatusBlock
;
430 hFile
= InternalOpenDirW(lpRootPathName
, FALSE
);
431 if (hFile
== INVALID_HANDLE_VALUE
)
436 errCode
= NtQueryVolumeInformationFile (hFile
,
439 sizeof(FILE_FS_DEVICE_INFORMATION
),
440 FileFsDeviceInformation
);
441 if (!NT_SUCCESS(errCode
))
444 SetLastErrorByStatus (errCode
);
448 return (UINT
)FileFsDevice
.DeviceType
;
456 GetVolumeInformationA(
457 LPCSTR lpRootPathName
,
458 LPSTR lpVolumeNameBuffer
,
459 DWORD nVolumeNameSize
,
460 LPDWORD lpVolumeSerialNumber
,
461 LPDWORD lpMaximumComponentLength
,
462 LPDWORD lpFileSystemFlags
,
463 LPSTR lpFileSystemNameBuffer
,
464 DWORD nFileSystemNameSize
467 UNICODE_STRING RootPathNameU
;
468 UNICODE_STRING FileSystemNameU
;
469 UNICODE_STRING VolumeNameU
;
470 ANSI_STRING RootPathName
;
471 ANSI_STRING VolumeName
;
472 ANSI_STRING FileSystemName
;
475 RtlInitAnsiString (&RootPathName
,
476 (LPSTR
)lpRootPathName
);
478 /* convert ansi (or oem) string to unicode */
480 RtlAnsiStringToUnicodeString (&RootPathNameU
,
484 RtlOemStringToUnicodeString (&RootPathNameU
,
488 if (lpVolumeNameBuffer
)
490 VolumeNameU
.Length
= 0;
491 VolumeNameU
.MaximumLength
= nVolumeNameSize
* sizeof(WCHAR
);
492 VolumeNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
494 VolumeNameU
.MaximumLength
);
497 if (lpFileSystemNameBuffer
)
499 FileSystemNameU
.Length
= 0;
500 FileSystemNameU
.MaximumLength
= nFileSystemNameSize
* sizeof(WCHAR
);
501 FileSystemNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
503 FileSystemNameU
.MaximumLength
);
506 Result
= GetVolumeInformationW (RootPathNameU
.Buffer
,
507 lpVolumeNameBuffer
? VolumeNameU
.Buffer
: NULL
,
509 lpVolumeSerialNumber
,
510 lpMaximumComponentLength
,
512 lpFileSystemNameBuffer
? FileSystemNameU
.Buffer
: NULL
,
513 nFileSystemNameSize
);
517 if (lpVolumeNameBuffer
)
519 VolumeNameU
.Length
= wcslen(VolumeNameU
.Buffer
) * sizeof(WCHAR
);
520 VolumeName
.Length
= 0;
521 VolumeName
.MaximumLength
= nVolumeNameSize
;
522 VolumeName
.Buffer
= lpVolumeNameBuffer
;
525 if (lpFileSystemNameBuffer
)
527 FileSystemNameU
.Length
= wcslen(FileSystemNameU
.Buffer
) * sizeof(WCHAR
);
528 FileSystemName
.Length
= 0;
529 FileSystemName
.MaximumLength
= nFileSystemNameSize
;
530 FileSystemName
.Buffer
= lpFileSystemNameBuffer
;
533 /* convert unicode strings to ansi (or oem) */
536 if (lpVolumeNameBuffer
)
538 RtlUnicodeStringToAnsiString (&VolumeName
,
542 if (lpFileSystemNameBuffer
)
544 RtlUnicodeStringToAnsiString (&FileSystemName
,
551 if (lpVolumeNameBuffer
)
553 RtlUnicodeStringToOemString (&VolumeName
,
557 if (lpFileSystemNameBuffer
)
559 RtlUnicodeStringToOemString (&FileSystemName
,
566 RtlFreeHeap (RtlGetProcessHeap (),
568 RootPathNameU
.Buffer
);
569 if (lpVolumeNameBuffer
)
571 RtlFreeHeap (RtlGetProcessHeap (),
575 if (lpFileSystemNameBuffer
)
577 RtlFreeHeap (RtlGetProcessHeap (),
579 FileSystemNameU
.Buffer
);
585 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION))
587 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
593 GetVolumeInformationW(
594 LPCWSTR lpRootPathName
,
595 LPWSTR lpVolumeNameBuffer
,
596 DWORD nVolumeNameSize
,
597 LPDWORD lpVolumeSerialNumber
,
598 LPDWORD lpMaximumComponentLength
,
599 LPDWORD lpFileSystemFlags
,
600 LPWSTR lpFileSystemNameBuffer
,
601 DWORD nFileSystemNameSize
604 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
605 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
606 IO_STATUS_BLOCK IoStatusBlock
;
607 OBJECT_ATTRIBUTES ObjectAttributes
;
608 UCHAR Buffer
[max(FS_VOLUME_BUFFER_SIZE
, FS_ATTRIBUTE_BUFFER_SIZE
)];
613 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
614 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer
;
616 DPRINT("FileFsVolume %p\n", FileFsVolume
);
617 DPRINT("FileFsAttribute %p\n", FileFsAttribute
);
619 hFile
= InternalOpenDirW(lpRootPathName
, FALSE
);
620 if (hFile
== INVALID_HANDLE_VALUE
)
625 DPRINT("hFile: %x\n", hFile
);
626 errCode
= NtQueryVolumeInformationFile(hFile
,
629 FS_VOLUME_BUFFER_SIZE
,
630 FileFsVolumeInformation
);
631 if ( !NT_SUCCESS(errCode
) )
633 DPRINT("Status: %x\n", errCode
);
635 SetLastErrorByStatus (errCode
);
639 if (lpVolumeSerialNumber
)
640 *lpVolumeSerialNumber
= FileFsVolume
->VolumeSerialNumber
;
642 if (lpVolumeNameBuffer
)
644 if (nVolumeNameSize
* sizeof(WCHAR
) >= FileFsVolume
->VolumeLabelLength
+ sizeof(WCHAR
))
646 memcpy(lpVolumeNameBuffer
,
647 FileFsVolume
->VolumeLabel
,
648 FileFsVolume
->VolumeLabelLength
);
649 lpVolumeNameBuffer
[FileFsVolume
->VolumeLabelLength
/ sizeof(WCHAR
)];
654 SetLastError(ERROR_MORE_DATA
);
659 errCode
= NtQueryVolumeInformationFile (hFile
,
662 FS_ATTRIBUTE_BUFFER_SIZE
,
663 FileFsAttributeInformation
);
665 if (!NT_SUCCESS(errCode
))
667 DPRINT("Status: %x\n", errCode
);
668 SetLastErrorByStatus (errCode
);
672 if (lpFileSystemFlags
)
673 *lpFileSystemFlags
= FileFsAttribute
->FileSystemAttributes
;
674 if (lpMaximumComponentLength
)
675 *lpMaximumComponentLength
= FileFsAttribute
->MaximumComponentNameLength
;
676 if (lpFileSystemNameBuffer
)
678 if (nFileSystemNameSize
* sizeof(WCHAR
) >= FileFsAttribute
->FileSystemNameLength
+ sizeof(WCHAR
))
680 memcpy(lpFileSystemNameBuffer
,
681 FileFsAttribute
->FileSystemName
,
682 FileFsAttribute
->FileSystemNameLength
);
683 lpFileSystemNameBuffer
[FileFsAttribute
->FileSystemNameLength
/ sizeof(WCHAR
)] = 0;
687 SetLastError(ERROR_MORE_DATA
);
701 LPCSTR lpRootPathName
,
705 UNICODE_STRING RootPathNameU
;
706 ANSI_STRING RootPathName
;
707 UNICODE_STRING VolumeNameU
;
708 ANSI_STRING VolumeName
;
711 RtlInitAnsiString (&RootPathName
,
712 (LPSTR
)lpRootPathName
);
713 RtlInitAnsiString (&VolumeName
,
714 (LPSTR
)lpVolumeName
);
716 /* convert ansi (or oem) strings to unicode */
719 RtlAnsiStringToUnicodeString (&RootPathNameU
,
722 RtlAnsiStringToUnicodeString (&VolumeNameU
,
728 RtlOemStringToUnicodeString (&RootPathNameU
,
731 RtlOemStringToUnicodeString (&VolumeNameU
,
736 Result
= SetVolumeLabelW (RootPathNameU
.Buffer
,
739 RtlFreeHeap (RtlGetProcessHeap (),
741 RootPathNameU
.Buffer
);
742 RtlFreeHeap (RtlGetProcessHeap (),
754 SetVolumeLabelW(LPCWSTR lpRootPathName
,
755 LPCWSTR lpVolumeName
)
757 PFILE_FS_LABEL_INFORMATION LabelInfo
;
758 IO_STATUS_BLOCK IoStatusBlock
;
763 LabelLength
= wcslen(lpVolumeName
) * sizeof(WCHAR
);
764 LabelInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
766 sizeof(FILE_FS_LABEL_INFORMATION
) +
768 LabelInfo
->VolumeLabelLength
= LabelLength
;
769 memcpy(LabelInfo
->VolumeLabel
,
773 hFile
= InternalOpenDirW(lpRootPathName
, TRUE
);
774 if (INVALID_HANDLE_VALUE
== hFile
)
776 RtlFreeHeap(RtlGetProcessHeap(),
782 Status
= NtSetVolumeInformationFile(hFile
,
785 sizeof(FILE_FS_LABEL_INFORMATION
) +
787 FileFsLabelInformation
);
789 RtlFreeHeap(RtlGetProcessHeap(),
793 if (!NT_SUCCESS(Status
))
795 DPRINT("Status: %x\n", Status
);
797 SetLastErrorByStatus(Status
);