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 UCHAR Buffer[max(FS_VOLUME_BUFFER_SIZE, FS_ATTRIBUTE_BUFFER_SIZE)];
612 FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
613 FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
615 DPRINT("FileFsVolume %p\n", FileFsVolume);
616 DPRINT("FileFsAttribute %p\n", FileFsAttribute);
618 hFile = InternalOpenDirW(lpRootPathName, FALSE);
619 if (hFile == INVALID_HANDLE_VALUE)
624 DPRINT("hFile: %x\n", hFile);
625 errCode = NtQueryVolumeInformationFile(hFile,
628 FS_VOLUME_BUFFER_SIZE,
629 FileFsVolumeInformation);
630 if ( !NT_SUCCESS(errCode) )
632 DPRINT("Status: %x\n", errCode);
634 SetLastErrorByStatus (errCode);
638 if (lpVolumeSerialNumber)
639 *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
641 if (lpVolumeNameBuffer)
643 if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR))
645 memcpy(lpVolumeNameBuffer,
646 FileFsVolume->VolumeLabel,
647 FileFsVolume->VolumeLabelLength);
648 lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0;
653 SetLastError(ERROR_MORE_DATA);
658 errCode = NtQueryVolumeInformationFile (hFile,
661 FS_ATTRIBUTE_BUFFER_SIZE,
662 FileFsAttributeInformation);
664 if (!NT_SUCCESS(errCode))
666 DPRINT("Status: %x\n", errCode);
667 SetLastErrorByStatus (errCode);
671 if (lpFileSystemFlags)
672 *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
673 if (lpMaximumComponentLength)
674 *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
675 if (lpFileSystemNameBuffer)
677 if (nFileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
679 memcpy(lpFileSystemNameBuffer,
680 FileFsAttribute->FileSystemName,
681 FileFsAttribute->FileSystemNameLength);
682 lpFileSystemNameBuffer[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0;
686 SetLastError(ERROR_MORE_DATA);
700 LPCSTR lpRootPathName,
704 UNICODE_STRING RootPathNameU;
705 ANSI_STRING RootPathName;
706 UNICODE_STRING VolumeNameU;
707 ANSI_STRING VolumeName;
710 RtlInitAnsiString (&RootPathName,
711 (LPSTR)lpRootPathName);
712 RtlInitAnsiString (&VolumeName,
713 (LPSTR)lpVolumeName);
715 /* convert ansi (or oem) strings to unicode */
718 RtlAnsiStringToUnicodeString (&RootPathNameU,
721 RtlAnsiStringToUnicodeString (&VolumeNameU,
727 RtlOemStringToUnicodeString (&RootPathNameU,
730 RtlOemStringToUnicodeString (&VolumeNameU,
735 Result = SetVolumeLabelW (RootPathNameU.Buffer,
738 RtlFreeHeap (RtlGetProcessHeap (),
740 RootPathNameU.Buffer);
741 RtlFreeHeap (RtlGetProcessHeap (),
753 SetVolumeLabelW(LPCWSTR lpRootPathName,
754 LPCWSTR lpVolumeName)
756 PFILE_FS_LABEL_INFORMATION LabelInfo;
757 IO_STATUS_BLOCK IoStatusBlock;
762 LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR);
763 LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(),
765 sizeof(FILE_FS_LABEL_INFORMATION) +
767 LabelInfo->VolumeLabelLength = LabelLength;
768 memcpy(LabelInfo->VolumeLabel,
772 hFile = InternalOpenDirW(lpRootPathName, TRUE);
773 if (INVALID_HANDLE_VALUE == hFile)
775 RtlFreeHeap(RtlGetProcessHeap(),
781 Status = NtSetVolumeInformationFile(hFile,
784 sizeof(FILE_FS_LABEL_INFORMATION) +
786 FileFsLabelInformation);
788 RtlFreeHeap(RtlGetProcessHeap(),
792 if (!NT_SUCCESS(Status))
794 DPRINT("Status: %x\n", Status);
796 SetLastErrorByStatus(Status);