2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/volume.c
5 * PURPOSE: File volume functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Erik Bos, Alexandre Julliard :
8 * DRIVE_IsValid, GetLogicalDriveStringsA,
9 * GetLogicalDriveStringsW, GetLogicalDrives
13 //WINE copyright notice:
15 * DOS drives handling functions
17 * Copyright 1993 Erik Bos
18 * Copyright 1996 Alexandre Julliard
21 #include <ddk/ntddk.h>
25 #include <kernel32/kernel32.h>
28 #define MAX_DOS_DRIVES 26
31 int DRIVE_IsValid( int drive
)
39 Drives
[0] = 'A' + drive
-1;
40 if ((drive
< 0) || (drive
>= MAX_DOS_DRIVES
)) return 0;
41 if ( CreateFileA(Drives
,GENERIC_READ
,FILE_SHARE_READ
,NULL
,OPEN_EXISTING
,FILE_FLAG_BACKUP_SEMANTICS
|FILE_ATTRIBUTE_DIRECTORY
,NULL
) == INVALID_HANDLE_VALUE
) {
51 GetLogicalDriveStringsA(
58 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
59 if (DRIVE_IsValid(drive
)) count
++;
60 if (count
* 4 * sizeof(char) <= nBufferLength
)
63 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
64 if (DRIVE_IsValid(drive
))
73 return count
* 4 * sizeof(char);
79 GetLogicalDriveStringsW(
86 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
87 if (DRIVE_IsValid(drive
)) count
++;
88 if (count
* 4 * sizeof(WCHAR
) <= nBufferLength
)
91 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
92 if (DRIVE_IsValid(drive
))
94 *p
++ = (WCHAR
)('A' + drive
);
101 return count
* 4 * sizeof(WCHAR
);
107 GetLogicalDrives(VOID
)
112 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
113 if (DRIVE_IsValid(drive
)) ret
|= (1 << drive
);
121 LPCSTR lpRootPathName
,
122 LPDWORD lpSectorsPerCluster
,
123 LPDWORD lpBytesPerSector
,
124 LPDWORD lpNumberOfFreeClusters
,
125 LPDWORD lpTotalNumberOfClusters
128 UNICODE_STRING RootPathNameU
;
129 ANSI_STRING RootPathName
;
132 RtlInitAnsiString (&RootPathName
,
133 (LPSTR
)lpRootPathName
);
135 RtlInitUnicodeString (&RootPathNameU
,
140 /* convert ansi (or oem) string to unicode */
142 RtlAnsiStringToUnicodeString (&RootPathNameU
,
146 RtlOemStringToUnicodeString (&RootPathNameU
,
151 Result
= GetDiskFreeSpaceW (RootPathNameU
.Buffer
,
154 lpNumberOfFreeClusters
,
155 lpTotalNumberOfClusters
);
159 RtlFreeHeap (RtlGetProcessHeap (),
161 RootPathNameU
.Buffer
);
171 LPCWSTR lpRootPathName
,
172 LPDWORD lpSectorsPerCluster
,
173 LPDWORD lpBytesPerSector
,
174 LPDWORD lpNumberOfFreeClusters
,
175 LPDWORD lpTotalNumberOfClusters
178 FILE_FS_SIZE_INFORMATION FileFsSize
;
179 IO_STATUS_BLOCK IoStatusBlock
;
180 WCHAR RootPathName
[MAX_PATH
];
186 wcsncpy (RootPathName
, lpRootPathName
, 3);
190 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
194 hFile
= CreateFileW(RootPathName
,
195 FILE_READ_ATTRIBUTES
,
199 FILE_ATTRIBUTE_NORMAL
,
202 errCode
= NtQueryVolumeInformationFile(hFile
,
205 sizeof(FILE_FS_SIZE_INFORMATION
),
206 FileFsSizeInformation
);
207 if (!NT_SUCCESS(errCode
))
210 SetLastError(RtlNtStatusToDosError(errCode
));
214 *lpBytesPerSector
= FileFsSize
.BytesPerSector
;
215 *lpSectorsPerCluster
= FileFsSize
.SectorsPerAllocationUnit
;
216 *lpNumberOfFreeClusters
= FileFsSize
.AvailableAllocationUnits
.u
.LowPart
;
217 *lpTotalNumberOfClusters
= FileFsSize
.TotalAllocationUnits
.u
.LowPart
;
225 GetDiskFreeSpaceExA (
226 LPCSTR lpDirectoryName
,
227 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
228 PULARGE_INTEGER lpTotalNumberOfBytes
,
229 PULARGE_INTEGER lpTotalNumberOfFreeBytes
232 UNICODE_STRING DirectoryNameU
;
233 ANSI_STRING DirectoryName
;
236 RtlInitAnsiString (&DirectoryName
,
237 (LPSTR
)lpDirectoryName
);
239 RtlInitUnicodeString (&DirectoryNameU
,
244 /* convert ansi (or oem) string to unicode */
246 RtlAnsiStringToUnicodeString (&DirectoryNameU
,
250 RtlOemStringToUnicodeString (&DirectoryNameU
,
255 Result
= GetDiskFreeSpaceExW (DirectoryNameU
.Buffer
,
256 lpFreeBytesAvailableToCaller
,
257 lpTotalNumberOfBytes
,
258 lpTotalNumberOfFreeBytes
);
262 RtlFreeHeap (RtlGetProcessHeap (),
264 DirectoryNameU
.Buffer
);
274 LPCWSTR lpDirectoryName
,
275 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
276 PULARGE_INTEGER lpTotalNumberOfBytes
,
277 PULARGE_INTEGER lpTotalNumberOfFreeBytes
280 FILE_FS_SIZE_INFORMATION FileFsSize
;
281 IO_STATUS_BLOCK IoStatusBlock
;
282 ULARGE_INTEGER BytesPerCluster
;
283 WCHAR RootPathName
[MAX_PATH
];
289 wcsncpy (RootPathName
, lpDirectoryName
, 3);
293 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
297 hFile
= CreateFileW(RootPathName
,
298 FILE_READ_ATTRIBUTES
,
302 FILE_ATTRIBUTE_NORMAL
,
305 errCode
= NtQueryVolumeInformationFile(hFile
,
308 sizeof(FILE_FS_SIZE_INFORMATION
),
309 FileFsSizeInformation
);
310 if (!NT_SUCCESS(errCode
))
313 SetLastError(RtlNtStatusToDosError(errCode
));
317 BytesPerCluster
.QuadPart
=
318 FileFsSize
.BytesPerSector
* FileFsSize
.SectorsPerAllocationUnit
;
320 // FIXME: Use quota information
321 lpFreeBytesAvailableToCaller
->QuadPart
=
322 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
324 lpTotalNumberOfBytes
->QuadPart
=
325 BytesPerCluster
.QuadPart
* FileFsSize
.TotalAllocationUnits
.QuadPart
;
326 lpTotalNumberOfFreeBytes
->QuadPart
=
327 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
337 LPCSTR lpRootPathName
340 UNICODE_STRING RootPathNameU
;
341 ANSI_STRING RootPathName
;
344 RtlInitAnsiString (&RootPathName
,
345 (LPSTR
)lpRootPathName
);
347 /* convert ansi (or oem) string to unicode */
349 RtlAnsiStringToUnicodeString (&RootPathNameU
,
353 RtlOemStringToUnicodeString (&RootPathNameU
,
357 Result
= GetDriveTypeW (RootPathNameU
.Buffer
);
359 RtlFreeHeap (RtlGetProcessHeap (),
361 RootPathNameU
.Buffer
);
370 LPCWSTR lpRootPathName
373 FILE_FS_DEVICE_INFORMATION FileFsDevice
;
374 IO_STATUS_BLOCK IoStatusBlock
;
379 hFile
= CreateFileW (lpRootPathName
,
381 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
384 FILE_ATTRIBUTE_NORMAL
,
387 errCode
= NtQueryVolumeInformationFile (hFile
,
390 sizeof(FILE_FS_DEVICE_INFORMATION
),
391 FileFsDeviceInformation
);
392 if (!NT_SUCCESS(errCode
))
395 SetLastError(RtlNtStatusToDosError(errCode
));
399 return (UINT
)FileFsDevice
.DeviceType
;
405 GetVolumeInformationA (
406 LPCSTR lpRootPathName
,
407 LPSTR lpVolumeNameBuffer
,
408 DWORD nVolumeNameSize
,
409 LPDWORD lpVolumeSerialNumber
,
410 LPDWORD lpMaximumComponentLength
,
411 LPDWORD lpFileSystemFlags
,
412 LPSTR lpFileSystemNameBuffer
,
413 DWORD nFileSystemNameSize
416 UNICODE_STRING RootPathNameU
;
417 UNICODE_STRING FileSystemNameU
;
418 UNICODE_STRING VolumeNameU
;
419 ANSI_STRING RootPathName
;
420 ANSI_STRING VolumeName
;
421 ANSI_STRING FileSystemName
;
424 RtlInitAnsiString (&RootPathName
,
425 (LPSTR
)lpRootPathName
);
427 /* convert ansi (or oem) string to unicode */
429 RtlAnsiStringToUnicodeString (&RootPathNameU
,
433 RtlOemStringToUnicodeString (&RootPathNameU
,
437 VolumeNameU
.Length
= 0;
438 VolumeNameU
.MaximumLength
= nVolumeNameSize
* sizeof(WCHAR
);
439 VolumeNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
441 VolumeNameU
.MaximumLength
);
443 FileSystemNameU
.Length
= 0;
444 FileSystemNameU
.MaximumLength
= nFileSystemNameSize
* sizeof(WCHAR
);
445 FileSystemNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
447 FileSystemNameU
.MaximumLength
);
449 Result
= GetVolumeInformationW (RootPathNameU
.Buffer
,
452 lpVolumeSerialNumber
,
453 lpMaximumComponentLength
,
455 FileSystemNameU
.Buffer
,
456 nFileSystemNameSize
);
460 VolumeName
.Length
= 0;
461 VolumeName
.MaximumLength
= nVolumeNameSize
;
462 VolumeName
.Buffer
= lpVolumeNameBuffer
;
464 FileSystemName
.Length
= 0;
465 FileSystemName
.MaximumLength
= nFileSystemNameSize
;
466 FileSystemName
.Buffer
= lpFileSystemNameBuffer
;
468 /* convert unicode strings to ansi (or oem) */
471 RtlUnicodeStringToAnsiString (&VolumeName
,
474 RtlUnicodeStringToAnsiString (&FileSystemName
,
480 RtlUnicodeStringToOemString (&VolumeName
,
483 RtlUnicodeStringToOemString (&FileSystemName
,
489 RtlFreeHeap (RtlGetProcessHeap (),
491 RootPathNameU
.Buffer
);
492 RtlFreeHeap (RtlGetProcessHeap (),
495 RtlFreeHeap (RtlGetProcessHeap (),
497 FileSystemNameU
.Buffer
);
505 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
507 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
512 GetVolumeInformationW(
513 LPCWSTR lpRootPathName
,
514 LPWSTR lpVolumeNameBuffer
,
515 DWORD nVolumeNameSize
,
516 LPDWORD lpVolumeSerialNumber
,
517 LPDWORD lpMaximumComponentLength
,
518 LPDWORD lpFileSystemFlags
,
519 LPWSTR lpFileSystemNameBuffer
,
520 DWORD nFileSystemNameSize
523 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
524 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
525 IO_STATUS_BLOCK IoStatusBlock
;
526 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
527 USHORT Buffer2
[FS_ATTRIBUTE_BUFFER_SIZE
];
532 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
533 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer2
;
535 DPRINT("FileFsVolume %p\n", FileFsVolume
);
536 DPRINT("FileFsAttribute %p\n", FileFsAttribute
);
538 hFile
= CreateFileW(lpRootPathName
,
539 FILE_READ_ATTRIBUTES
,
540 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
543 FILE_ATTRIBUTE_NORMAL
,
546 DPRINT("hFile: %x\n", hFile
);
547 errCode
= NtQueryVolumeInformationFile(hFile
,
550 FS_VOLUME_BUFFER_SIZE
,
551 FileFsVolumeInformation
);
552 if ( !NT_SUCCESS(errCode
) ) {
553 DPRINT("Status: %x\n", errCode
);
555 SetLastError(RtlNtStatusToDosError(errCode
));
559 if (lpVolumeSerialNumber
)
560 *lpVolumeSerialNumber
= FileFsVolume
->VolumeSerialNumber
;
562 if (lpVolumeNameBuffer
)
563 wcsncpy (lpVolumeNameBuffer
,
564 FileFsVolume
->VolumeLabel
,
565 min(nVolumeNameSize
,MAX_PATH
));
567 errCode
= NtQueryVolumeInformationFile (hFile
,
570 FS_ATTRIBUTE_BUFFER_SIZE
,
571 FileFsAttributeInformation
);
572 if (!NT_SUCCESS(errCode
))
574 DPRINT("Status: %x\n", errCode
);
576 SetLastError(RtlNtStatusToDosError(errCode
));
580 if (lpFileSystemFlags
)
581 *lpFileSystemFlags
= FileFsAttribute
->FileSystemAttributes
;
582 if (lpMaximumComponentLength
)
583 *lpMaximumComponentLength
= FileFsAttribute
->MaximumComponentNameLength
;
584 if (lpFileSystemNameBuffer
)
585 wcsncpy(lpFileSystemNameBuffer
, FileFsAttribute
->FileSystemName
,min(nFileSystemNameSize
,MAX_PATH
));
595 LPCSTR lpRootPathName
,
599 UNICODE_STRING RootPathNameU
;
600 ANSI_STRING RootPathName
;
601 UNICODE_STRING VolumeNameU
;
602 ANSI_STRING VolumeName
;
605 RtlInitAnsiString (&RootPathName
,
606 (LPSTR
)lpRootPathName
);
607 RtlInitAnsiString (&VolumeName
,
608 (LPSTR
)lpVolumeName
);
610 /* convert ansi (or oem) strings to unicode */
613 RtlAnsiStringToUnicodeString (&RootPathNameU
,
616 RtlAnsiStringToUnicodeString (&VolumeNameU
,
622 RtlOemStringToUnicodeString (&RootPathNameU
,
625 RtlOemStringToUnicodeString (&VolumeNameU
,
630 Result
= SetVolumeLabelW (RootPathNameU
.Buffer
,
633 RtlFreeHeap (RtlGetProcessHeap (),
635 RootPathNameU
.Buffer
);
636 RtlFreeHeap (RtlGetProcessHeap (),
647 LPCWSTR lpRootPathName
,