1 /* $Id: volume.c,v 1.18 2000/08/25 15:52:56 ekohl 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
22 #include <ddk/ntddk.h>
23 #include <napi/shared_data.h>
25 #include <ntos/minmax.h>
28 #include <kernel32/kernel32.h>
29 #include <kernel32/error.h>
32 #define MAX_DOS_DRIVES 26
37 GetLogicalDriveStringsA(DWORD nBufferLength
,
43 dwDriveMap
= ((PKUSER_SHARED_DATA
)USER_SHARED_DATA_BASE
)->DosDeviceMap
;
45 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
47 if (dwDriveMap
& (1<<drive
))
52 if (count
* 4 * sizeof(char) <= nBufferLength
)
56 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
57 if (dwDriveMap
& (1<<drive
))
66 return (count
* 4 * sizeof(char));
72 GetLogicalDriveStringsW(DWORD nBufferLength
,
78 dwDriveMap
= ((PKUSER_SHARED_DATA
)USER_SHARED_DATA_BASE
)->DosDeviceMap
;
80 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
82 if (dwDriveMap
& (1<<drive
))
86 if (count
* 4 * sizeof(WCHAR
) <= nBufferLength
)
89 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
90 if (dwDriveMap
& (1<<drive
))
92 *p
++ = (WCHAR
)('A' + drive
);
99 return (count
* 4 * sizeof(WCHAR
));
105 GetLogicalDrives(VOID
)
107 return (((PKUSER_SHARED_DATA
)USER_SHARED_DATA_BASE
)->DosDeviceMap
);
114 LPCSTR lpRootPathName
,
115 LPDWORD lpSectorsPerCluster
,
116 LPDWORD lpBytesPerSector
,
117 LPDWORD lpNumberOfFreeClusters
,
118 LPDWORD lpTotalNumberOfClusters
121 UNICODE_STRING RootPathNameU
;
122 ANSI_STRING RootPathName
;
125 RtlInitAnsiString (&RootPathName
,
126 (LPSTR
)lpRootPathName
);
128 RtlInitUnicodeString (&RootPathNameU
,
133 /* convert ansi (or oem) string to unicode */
135 RtlAnsiStringToUnicodeString (&RootPathNameU
,
139 RtlOemStringToUnicodeString (&RootPathNameU
,
144 Result
= GetDiskFreeSpaceW (RootPathNameU
.Buffer
,
147 lpNumberOfFreeClusters
,
148 lpTotalNumberOfClusters
);
152 RtlFreeHeap (RtlGetProcessHeap (),
154 RootPathNameU
.Buffer
);
164 LPCWSTR lpRootPathName
,
165 LPDWORD lpSectorsPerCluster
,
166 LPDWORD lpBytesPerSector
,
167 LPDWORD lpNumberOfFreeClusters
,
168 LPDWORD lpTotalNumberOfClusters
171 FILE_FS_SIZE_INFORMATION FileFsSize
;
172 IO_STATUS_BLOCK IoStatusBlock
;
173 WCHAR RootPathName
[MAX_PATH
];
179 wcsncpy (RootPathName
, lpRootPathName
, 3);
183 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
187 hFile
= CreateFileW(RootPathName
,
188 FILE_READ_ATTRIBUTES
,
192 FILE_ATTRIBUTE_NORMAL
,
195 errCode
= NtQueryVolumeInformationFile(hFile
,
198 sizeof(FILE_FS_SIZE_INFORMATION
),
199 FileFsSizeInformation
);
200 if (!NT_SUCCESS(errCode
))
203 SetLastErrorByStatus (errCode
);
207 *lpBytesPerSector
= FileFsSize
.BytesPerSector
;
208 *lpSectorsPerCluster
= FileFsSize
.SectorsPerAllocationUnit
;
209 *lpNumberOfFreeClusters
= FileFsSize
.AvailableAllocationUnits
.u
.LowPart
;
210 *lpTotalNumberOfClusters
= FileFsSize
.TotalAllocationUnits
.u
.LowPart
;
218 GetDiskFreeSpaceExA (
219 LPCSTR lpDirectoryName
,
220 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
221 PULARGE_INTEGER lpTotalNumberOfBytes
,
222 PULARGE_INTEGER lpTotalNumberOfFreeBytes
225 UNICODE_STRING DirectoryNameU
;
226 ANSI_STRING DirectoryName
;
229 RtlInitAnsiString (&DirectoryName
,
230 (LPSTR
)lpDirectoryName
);
232 RtlInitUnicodeString (&DirectoryNameU
,
237 /* convert ansi (or oem) string to unicode */
239 RtlAnsiStringToUnicodeString (&DirectoryNameU
,
243 RtlOemStringToUnicodeString (&DirectoryNameU
,
248 Result
= GetDiskFreeSpaceExW (DirectoryNameU
.Buffer
,
249 lpFreeBytesAvailableToCaller
,
250 lpTotalNumberOfBytes
,
251 lpTotalNumberOfFreeBytes
);
255 RtlFreeHeap (RtlGetProcessHeap (),
257 DirectoryNameU
.Buffer
);
267 LPCWSTR lpDirectoryName
,
268 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
269 PULARGE_INTEGER lpTotalNumberOfBytes
,
270 PULARGE_INTEGER lpTotalNumberOfFreeBytes
273 FILE_FS_SIZE_INFORMATION FileFsSize
;
274 IO_STATUS_BLOCK IoStatusBlock
;
275 ULARGE_INTEGER BytesPerCluster
;
276 WCHAR RootPathName
[MAX_PATH
];
282 wcsncpy (RootPathName
, lpDirectoryName
, 3);
286 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
290 hFile
= CreateFileW(RootPathName
,
291 FILE_READ_ATTRIBUTES
,
295 FILE_ATTRIBUTE_NORMAL
,
298 errCode
= NtQueryVolumeInformationFile(hFile
,
301 sizeof(FILE_FS_SIZE_INFORMATION
),
302 FileFsSizeInformation
);
303 if (!NT_SUCCESS(errCode
))
306 SetLastErrorByStatus (errCode
);
310 BytesPerCluster
.QuadPart
=
311 FileFsSize
.BytesPerSector
* FileFsSize
.SectorsPerAllocationUnit
;
313 // FIXME: Use quota information
314 lpFreeBytesAvailableToCaller
->QuadPart
=
315 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
317 lpTotalNumberOfBytes
->QuadPart
=
318 BytesPerCluster
.QuadPart
* FileFsSize
.TotalAllocationUnits
.QuadPart
;
319 lpTotalNumberOfFreeBytes
->QuadPart
=
320 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
330 LPCSTR lpRootPathName
333 UNICODE_STRING RootPathNameU
;
334 ANSI_STRING RootPathName
;
337 RtlInitAnsiString (&RootPathName
,
338 (LPSTR
)lpRootPathName
);
340 /* convert ansi (or oem) string to unicode */
342 RtlAnsiStringToUnicodeString (&RootPathNameU
,
346 RtlOemStringToUnicodeString (&RootPathNameU
,
350 Result
= GetDriveTypeW (RootPathNameU
.Buffer
);
352 RtlFreeHeap (RtlGetProcessHeap (),
354 RootPathNameU
.Buffer
);
363 LPCWSTR lpRootPathName
366 FILE_FS_DEVICE_INFORMATION FileFsDevice
;
367 IO_STATUS_BLOCK IoStatusBlock
;
372 hFile
= CreateFileW (lpRootPathName
,
374 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
377 FILE_ATTRIBUTE_NORMAL
,
380 errCode
= NtQueryVolumeInformationFile (hFile
,
383 sizeof(FILE_FS_DEVICE_INFORMATION
),
384 FileFsDeviceInformation
);
385 if (!NT_SUCCESS(errCode
))
388 SetLastErrorByStatus (errCode
);
392 return (UINT
)FileFsDevice
.DeviceType
;
398 GetVolumeInformationA (
399 LPCSTR lpRootPathName
,
400 LPSTR lpVolumeNameBuffer
,
401 DWORD nVolumeNameSize
,
402 LPDWORD lpVolumeSerialNumber
,
403 LPDWORD lpMaximumComponentLength
,
404 LPDWORD lpFileSystemFlags
,
405 LPSTR lpFileSystemNameBuffer
,
406 DWORD nFileSystemNameSize
409 UNICODE_STRING RootPathNameU
;
410 UNICODE_STRING FileSystemNameU
;
411 UNICODE_STRING VolumeNameU
;
412 ANSI_STRING RootPathName
;
413 ANSI_STRING VolumeName
;
414 ANSI_STRING FileSystemName
;
417 RtlInitAnsiString (&RootPathName
,
418 (LPSTR
)lpRootPathName
);
420 /* convert ansi (or oem) string to unicode */
422 RtlAnsiStringToUnicodeString (&RootPathNameU
,
426 RtlOemStringToUnicodeString (&RootPathNameU
,
430 VolumeNameU
.Length
= 0;
431 VolumeNameU
.MaximumLength
= nVolumeNameSize
* sizeof(WCHAR
);
432 VolumeNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
434 VolumeNameU
.MaximumLength
);
436 FileSystemNameU
.Length
= 0;
437 FileSystemNameU
.MaximumLength
= nFileSystemNameSize
* sizeof(WCHAR
);
438 FileSystemNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
440 FileSystemNameU
.MaximumLength
);
442 Result
= GetVolumeInformationW (RootPathNameU
.Buffer
,
445 lpVolumeSerialNumber
,
446 lpMaximumComponentLength
,
448 FileSystemNameU
.Buffer
,
449 nFileSystemNameSize
);
453 VolumeName
.Length
= 0;
454 VolumeName
.MaximumLength
= nVolumeNameSize
;
455 VolumeName
.Buffer
= lpVolumeNameBuffer
;
457 FileSystemName
.Length
= 0;
458 FileSystemName
.MaximumLength
= nFileSystemNameSize
;
459 FileSystemName
.Buffer
= lpFileSystemNameBuffer
;
461 /* convert unicode strings to ansi (or oem) */
464 RtlUnicodeStringToAnsiString (&VolumeName
,
467 RtlUnicodeStringToAnsiString (&FileSystemName
,
473 RtlUnicodeStringToOemString (&VolumeName
,
476 RtlUnicodeStringToOemString (&FileSystemName
,
482 RtlFreeHeap (RtlGetProcessHeap (),
484 RootPathNameU
.Buffer
);
485 RtlFreeHeap (RtlGetProcessHeap (),
488 RtlFreeHeap (RtlGetProcessHeap (),
490 FileSystemNameU
.Buffer
);
498 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
500 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
505 GetVolumeInformationW(
506 LPCWSTR lpRootPathName
,
507 LPWSTR lpVolumeNameBuffer
,
508 DWORD nVolumeNameSize
,
509 LPDWORD lpVolumeSerialNumber
,
510 LPDWORD lpMaximumComponentLength
,
511 LPDWORD lpFileSystemFlags
,
512 LPWSTR lpFileSystemNameBuffer
,
513 DWORD nFileSystemNameSize
516 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
517 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
518 IO_STATUS_BLOCK IoStatusBlock
;
519 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
520 USHORT Buffer2
[FS_ATTRIBUTE_BUFFER_SIZE
];
525 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
526 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer2
;
528 DPRINT("FileFsVolume %p\n", FileFsVolume
);
529 DPRINT("FileFsAttribute %p\n", FileFsAttribute
);
531 hFile
= CreateFileW(lpRootPathName
,
532 FILE_READ_ATTRIBUTES
,
533 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
536 FILE_ATTRIBUTE_NORMAL
,
539 DPRINT("hFile: %x\n", hFile
);
540 errCode
= NtQueryVolumeInformationFile(hFile
,
543 FS_VOLUME_BUFFER_SIZE
,
544 FileFsVolumeInformation
);
545 if ( !NT_SUCCESS(errCode
) ) {
546 DPRINT("Status: %x\n", errCode
);
548 SetLastErrorByStatus (errCode
);
552 if (lpVolumeSerialNumber
)
553 *lpVolumeSerialNumber
= FileFsVolume
->VolumeSerialNumber
;
555 if (lpVolumeNameBuffer
)
556 wcsncpy (lpVolumeNameBuffer
,
557 FileFsVolume
->VolumeLabel
,
558 min(nVolumeNameSize
,MAX_PATH
));
560 errCode
= NtQueryVolumeInformationFile (hFile
,
563 FS_ATTRIBUTE_BUFFER_SIZE
,
564 FileFsAttributeInformation
);
565 if (!NT_SUCCESS(errCode
))
567 DPRINT("Status: %x\n", errCode
);
569 SetLastErrorByStatus (errCode
);
573 if (lpFileSystemFlags
)
574 *lpFileSystemFlags
= FileFsAttribute
->FileSystemAttributes
;
575 if (lpMaximumComponentLength
)
576 *lpMaximumComponentLength
= FileFsAttribute
->MaximumComponentNameLength
;
577 if (lpFileSystemNameBuffer
)
578 wcsncpy(lpFileSystemNameBuffer
, FileFsAttribute
->FileSystemName
,min(nFileSystemNameSize
,MAX_PATH
));
588 LPCSTR lpRootPathName
,
592 UNICODE_STRING RootPathNameU
;
593 ANSI_STRING RootPathName
;
594 UNICODE_STRING VolumeNameU
;
595 ANSI_STRING VolumeName
;
598 RtlInitAnsiString (&RootPathName
,
599 (LPSTR
)lpRootPathName
);
600 RtlInitAnsiString (&VolumeName
,
601 (LPSTR
)lpVolumeName
);
603 /* convert ansi (or oem) strings to unicode */
606 RtlAnsiStringToUnicodeString (&RootPathNameU
,
609 RtlAnsiStringToUnicodeString (&VolumeNameU
,
615 RtlOemStringToUnicodeString (&RootPathNameU
,
618 RtlOemStringToUnicodeString (&VolumeNameU
,
623 Result
= SetVolumeLabelW (RootPathNameU
.Buffer
,
626 RtlFreeHeap (RtlGetProcessHeap (),
628 RootPathNameU
.Buffer
);
629 RtlFreeHeap (RtlGetProcessHeap (),
640 LPCWSTR lpRootPathName
,