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
22 #include <ddk/ntddk.h>
24 #include <ntos/minmax.h>
27 #include <kernel32/kernel32.h>
28 #include <kernel32/error.h>
31 #define MAX_DOS_DRIVES 26
33 HANDLE InternalOpenDirW(PWCHAR DirName, BOOLEAN Write)
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;
80 GetLogicalDriveStringsA(DWORD nBufferLength,
86 dwDriveMap = SharedUserData->DosDeviceMap;
88 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
90 if (dwDriveMap & (1<<drive))
95 if (count * 4 * sizeof(char) <= nBufferLength)
99 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
100 if (dwDriveMap & (1<<drive))
109 return (count * 4 * sizeof(char));
114 GetLogicalDriveStringsW(DWORD nBufferLength,
120 dwDriveMap = SharedUserData->DosDeviceMap;
122 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
124 if (dwDriveMap & (1<<drive))
128 if (count * 4 * sizeof(WCHAR) <= nBufferLength)
131 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
132 if (dwDriveMap & (1<<drive))
134 *p++ = (WCHAR)('A' + drive);
141 return (count * 4 * sizeof(WCHAR));
146 GetLogicalDrives(VOID)
148 return(SharedUserData->DosDeviceMap);
154 LPCSTR lpRootPathName,
155 LPDWORD lpSectorsPerCluster,
156 LPDWORD lpBytesPerSector,
157 LPDWORD lpNumberOfFreeClusters,
158 LPDWORD lpTotalNumberOfClusters
161 UNICODE_STRING RootPathNameU;
162 ANSI_STRING RootPathName;
165 RtlInitAnsiString (&RootPathName,
166 (LPSTR)lpRootPathName);
168 RtlInitUnicodeString (&RootPathNameU,
173 /* convert ansi (or oem) string to unicode */
175 RtlAnsiStringToUnicodeString (&RootPathNameU,
179 RtlOemStringToUnicodeString (&RootPathNameU,
184 Result = GetDiskFreeSpaceW (RootPathNameU.Buffer,
187 lpNumberOfFreeClusters,
188 lpTotalNumberOfClusters);
192 RtlFreeHeap (RtlGetProcessHeap (),
194 RootPathNameU.Buffer);
203 LPCWSTR lpRootPathName,
204 LPDWORD lpSectorsPerCluster,
205 LPDWORD lpBytesPerSector,
206 LPDWORD lpNumberOfFreeClusters,
207 LPDWORD lpTotalNumberOfClusters
210 FILE_FS_SIZE_INFORMATION FileFsSize;
211 IO_STATUS_BLOCK IoStatusBlock;
212 WCHAR RootPathName[MAX_PATH];
218 wcsncpy (RootPathName, lpRootPathName, 3);
222 GetCurrentDirectoryW (MAX_PATH, RootPathName);
226 if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW((PWCHAR)lpRootPathName, FALSE)))
232 errCode = NtQueryVolumeInformationFile(hFile,
235 sizeof(FILE_FS_SIZE_INFORMATION),
236 FileFsSizeInformation);
237 if (!NT_SUCCESS(errCode))
240 SetLastErrorByStatus (errCode);
244 *lpBytesPerSector = FileFsSize.BytesPerSector;
245 *lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
246 *lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
247 *lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
254 GetDiskFreeSpaceExA (
255 LPCSTR lpDirectoryName,
256 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
257 PULARGE_INTEGER lpTotalNumberOfBytes,
258 PULARGE_INTEGER lpTotalNumberOfFreeBytes
261 UNICODE_STRING DirectoryNameU;
262 ANSI_STRING DirectoryName;
265 RtlInitAnsiString (&DirectoryName,
266 (LPSTR)lpDirectoryName);
268 RtlInitUnicodeString (&DirectoryNameU,
273 /* convert ansi (or oem) string to unicode */
275 RtlAnsiStringToUnicodeString (&DirectoryNameU,
279 RtlOemStringToUnicodeString (&DirectoryNameU,
284 Result = GetDiskFreeSpaceExW (DirectoryNameU.Buffer,
285 lpFreeBytesAvailableToCaller,
286 lpTotalNumberOfBytes,
287 lpTotalNumberOfFreeBytes);
291 RtlFreeHeap (RtlGetProcessHeap (),
293 DirectoryNameU.Buffer);
302 LPCWSTR lpDirectoryName,
303 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
304 PULARGE_INTEGER lpTotalNumberOfBytes,
305 PULARGE_INTEGER lpTotalNumberOfFreeBytes
308 FILE_FS_SIZE_INFORMATION FileFsSize;
309 IO_STATUS_BLOCK IoStatusBlock;
310 ULARGE_INTEGER BytesPerCluster;
311 WCHAR RootPathName[MAX_PATH];
317 wcsncpy (RootPathName, lpDirectoryName, 3);
321 GetCurrentDirectoryW (MAX_PATH, RootPathName);
325 if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW(lpDirectoryName, FALSE)))
330 errCode = NtQueryVolumeInformationFile(hFile,
333 sizeof(FILE_FS_SIZE_INFORMATION),
334 FileFsSizeInformation);
335 if (!NT_SUCCESS(errCode))
338 SetLastErrorByStatus (errCode);
342 BytesPerCluster.QuadPart =
343 FileFsSize.BytesPerSector * FileFsSize.SectorsPerAllocationUnit;
345 // FIXME: Use quota information
346 if (lpFreeBytesAvailableToCaller)
347 lpFreeBytesAvailableToCaller->QuadPart =
348 BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
350 if (lpTotalNumberOfBytes)
351 lpTotalNumberOfBytes->QuadPart =
352 BytesPerCluster.QuadPart * FileFsSize.TotalAllocationUnits.QuadPart;
353 if (lpTotalNumberOfFreeBytes)
354 lpTotalNumberOfFreeBytes->QuadPart =
355 BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
363 GetDriveTypeA(LPCSTR lpRootPathName)
365 UNICODE_STRING RootPathNameU;
366 ANSI_STRING RootPathName;
369 RtlInitAnsiString (&RootPathName,
370 (LPSTR)lpRootPathName);
372 /* convert ansi (or oem) string to unicode */
374 RtlAnsiStringToUnicodeString (&RootPathNameU,
378 RtlOemStringToUnicodeString (&RootPathNameU,
382 Result = GetDriveTypeW (RootPathNameU.Buffer);
384 RtlFreeHeap (RtlGetProcessHeap (),
386 RootPathNameU.Buffer);
392 GetDriveTypeW(LPCWSTR lpRootPathName)
394 FILE_FS_DEVICE_INFORMATION FileFsDevice;
395 IO_STATUS_BLOCK IoStatusBlock;
400 hFile = InternalOpenDirW(lpRootPathName, FALSE);
401 if (hFile == INVALID_HANDLE_VALUE)
406 errCode = NtQueryVolumeInformationFile (hFile,
409 sizeof(FILE_FS_DEVICE_INFORMATION),
410 FileFsDeviceInformation);
411 if (!NT_SUCCESS(errCode))
414 SetLastErrorByStatus (errCode);
418 return (UINT)FileFsDevice.DeviceType;
423 GetVolumeInformationA(
424 LPCSTR lpRootPathName,
425 LPSTR lpVolumeNameBuffer,
426 DWORD nVolumeNameSize,
427 LPDWORD lpVolumeSerialNumber,
428 LPDWORD lpMaximumComponentLength,
429 LPDWORD lpFileSystemFlags,
430 LPSTR lpFileSystemNameBuffer,
431 DWORD nFileSystemNameSize
434 UNICODE_STRING RootPathNameU;
435 UNICODE_STRING FileSystemNameU;
436 UNICODE_STRING VolumeNameU;
437 ANSI_STRING RootPathName;
438 ANSI_STRING VolumeName;
439 ANSI_STRING FileSystemName;
442 RtlInitAnsiString (&RootPathName,
443 (LPSTR)lpRootPathName);
445 /* convert ansi (or oem) string to unicode */
447 RtlAnsiStringToUnicodeString (&RootPathNameU,
451 RtlOemStringToUnicodeString (&RootPathNameU,
455 VolumeNameU.Length = 0;
456 VolumeNameU.MaximumLength = nVolumeNameSize * sizeof(WCHAR);
457 VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
459 VolumeNameU.MaximumLength);
461 FileSystemNameU.Length = 0;
462 FileSystemNameU.MaximumLength = nFileSystemNameSize * sizeof(WCHAR);
463 FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
465 FileSystemNameU.MaximumLength);
467 Result = GetVolumeInformationW (RootPathNameU.Buffer,
470 lpVolumeSerialNumber,
471 lpMaximumComponentLength,
473 FileSystemNameU.Buffer,
474 nFileSystemNameSize);
478 VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR);
479 VolumeName.Length = 0;
480 VolumeName.MaximumLength = nVolumeNameSize;
481 VolumeName.Buffer = lpVolumeNameBuffer;
483 FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR);
484 FileSystemName.Length = 0;
485 FileSystemName.MaximumLength = nFileSystemNameSize;
486 FileSystemName.Buffer = lpFileSystemNameBuffer;
488 /* convert unicode strings to ansi (or oem) */
491 RtlUnicodeStringToAnsiString (&VolumeName,
494 RtlUnicodeStringToAnsiString (&FileSystemName,
500 RtlUnicodeStringToOemString (&VolumeName,
503 RtlUnicodeStringToOemString (&FileSystemName,
509 RtlFreeHeap (RtlGetProcessHeap (),
511 RootPathNameU.Buffer);
512 RtlFreeHeap (RtlGetProcessHeap (),
515 RtlFreeHeap (RtlGetProcessHeap (),
517 FileSystemNameU.Buffer);
525 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
527 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
531 GetVolumeInformationW(
532 LPCWSTR lpRootPathName,
533 LPWSTR lpVolumeNameBuffer,
534 DWORD nVolumeNameSize,
535 LPDWORD lpVolumeSerialNumber,
536 LPDWORD lpMaximumComponentLength,
537 LPDWORD lpFileSystemFlags,
538 LPWSTR lpFileSystemNameBuffer,
539 DWORD nFileSystemNameSize
542 PFILE_FS_VOLUME_INFORMATION FileFsVolume;
543 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
544 IO_STATUS_BLOCK IoStatusBlock;
545 OBJECT_ATTRIBUTES ObjectAttributes;
546 USHORT Buffer[FS_VOLUME_BUFFER_SIZE];
547 USHORT Buffer2[FS_ATTRIBUTE_BUFFER_SIZE];
552 FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
553 FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer2;
555 DPRINT("FileFsVolume %p\n", FileFsVolume);
556 DPRINT("FileFsAttribute %p\n", FileFsAttribute);
558 hFile = InternalOpenDirW(lpRootPathName, FALSE);
559 if (hFile == INVALID_HANDLE_VALUE)
564 DPRINT("hFile: %x\n", hFile);
565 errCode = NtQueryVolumeInformationFile(hFile,
568 FS_VOLUME_BUFFER_SIZE,
569 FileFsVolumeInformation);
570 if ( !NT_SUCCESS(errCode) ) {
571 DPRINT("Status: %x\n", errCode);
573 SetLastErrorByStatus (errCode);
577 if (lpVolumeSerialNumber)
578 *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
580 if (lpVolumeNameBuffer)
581 wcsncpy (lpVolumeNameBuffer,
582 FileFsVolume->VolumeLabel,
583 min(nVolumeNameSize,MAX_PATH));
585 errCode = NtQueryVolumeInformationFile (hFile,
588 FS_ATTRIBUTE_BUFFER_SIZE,
589 FileFsAttributeInformation);
590 if (!NT_SUCCESS(errCode))
592 DPRINT("Status: %x\n", errCode);
594 SetLastErrorByStatus (errCode);
598 if (lpFileSystemFlags)
599 *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
600 if (lpMaximumComponentLength)
601 *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
602 if (lpFileSystemNameBuffer)
603 wcsncpy(lpFileSystemNameBuffer, FileFsAttribute->FileSystemName,min(nFileSystemNameSize,MAX_PATH));
613 LPCSTR lpRootPathName,
617 UNICODE_STRING RootPathNameU;
618 ANSI_STRING RootPathName;
619 UNICODE_STRING VolumeNameU;
620 ANSI_STRING VolumeName;
623 RtlInitAnsiString (&RootPathName,
624 (LPSTR)lpRootPathName);
625 RtlInitAnsiString (&VolumeName,
626 (LPSTR)lpVolumeName);
628 /* convert ansi (or oem) strings to unicode */
631 RtlAnsiStringToUnicodeString (&RootPathNameU,
634 RtlAnsiStringToUnicodeString (&VolumeNameU,
640 RtlOemStringToUnicodeString (&RootPathNameU,
643 RtlOemStringToUnicodeString (&VolumeNameU,
648 Result = SetVolumeLabelW (RootPathNameU.Buffer,
651 RtlFreeHeap (RtlGetProcessHeap (),
653 RootPathNameU.Buffer);
654 RtlFreeHeap (RtlGetProcessHeap (),
663 SetVolumeLabelW(LPCWSTR lpRootPathName,
664 LPCWSTR lpVolumeName)
666 PFILE_FS_LABEL_INFORMATION LabelInfo;
667 IO_STATUS_BLOCK IoStatusBlock;
672 LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR);
673 LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(),
675 sizeof(FILE_FS_LABEL_INFORMATION) +
677 LabelInfo->VolumeLabelLength = LabelLength;
678 wcscpy(LabelInfo->VolumeLabel,
681 if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW(lpRootPathName, TRUE)))
686 Status = NtSetVolumeInformationFile(hFile,
689 sizeof(FILE_FS_LABEL_INFORMATION) +
691 FileFsLabelInformation);
693 RtlFreeHeap(RtlGetProcessHeap(),
697 if (!NT_SUCCESS(Status))
699 DPRINT("Status: %x\n", Status);
701 SetLastErrorByStatus(Status);