1 /* $Id: volume.c,v 1.23 2002/08/18 21:07:59 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
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
35 GetLogicalDriveStringsA(DWORD nBufferLength
,
41 dwDriveMap
= SharedUserData
->DosDeviceMap
;
43 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
45 if (dwDriveMap
& (1<<drive
))
50 if (count
* 4 * sizeof(char) <= nBufferLength
)
54 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
55 if (dwDriveMap
& (1<<drive
))
64 return (count
* 4 * sizeof(char));
69 GetLogicalDriveStringsW(DWORD nBufferLength
,
75 dwDriveMap
= SharedUserData
->DosDeviceMap
;
77 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
79 if (dwDriveMap
& (1<<drive
))
83 if (count
* 4 * sizeof(WCHAR
) <= nBufferLength
)
86 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
87 if (dwDriveMap
& (1<<drive
))
89 *p
++ = (WCHAR
)('A' + drive
);
96 return (count
* 4 * sizeof(WCHAR
));
101 GetLogicalDrives(VOID
)
103 return(SharedUserData
->DosDeviceMap
);
109 LPCSTR lpRootPathName
,
110 LPDWORD lpSectorsPerCluster
,
111 LPDWORD lpBytesPerSector
,
112 LPDWORD lpNumberOfFreeClusters
,
113 LPDWORD lpTotalNumberOfClusters
116 UNICODE_STRING RootPathNameU
;
117 ANSI_STRING RootPathName
;
120 RtlInitAnsiString (&RootPathName
,
121 (LPSTR
)lpRootPathName
);
123 RtlInitUnicodeString (&RootPathNameU
,
128 /* convert ansi (or oem) string to unicode */
130 RtlAnsiStringToUnicodeString (&RootPathNameU
,
134 RtlOemStringToUnicodeString (&RootPathNameU
,
139 Result
= GetDiskFreeSpaceW (RootPathNameU
.Buffer
,
142 lpNumberOfFreeClusters
,
143 lpTotalNumberOfClusters
);
147 RtlFreeHeap (RtlGetProcessHeap (),
149 RootPathNameU
.Buffer
);
158 LPCWSTR lpRootPathName
,
159 LPDWORD lpSectorsPerCluster
,
160 LPDWORD lpBytesPerSector
,
161 LPDWORD lpNumberOfFreeClusters
,
162 LPDWORD lpTotalNumberOfClusters
165 FILE_FS_SIZE_INFORMATION FileFsSize
;
166 IO_STATUS_BLOCK IoStatusBlock
;
167 WCHAR RootPathName
[MAX_PATH
];
173 wcsncpy (RootPathName
, lpRootPathName
, 3);
177 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
181 hFile
= CreateFileW(RootPathName
,
182 FILE_READ_ATTRIBUTES
,
186 FILE_ATTRIBUTE_NORMAL
,
189 errCode
= NtQueryVolumeInformationFile(hFile
,
192 sizeof(FILE_FS_SIZE_INFORMATION
),
193 FileFsSizeInformation
);
194 if (!NT_SUCCESS(errCode
))
197 SetLastErrorByStatus (errCode
);
201 *lpBytesPerSector
= FileFsSize
.BytesPerSector
;
202 *lpSectorsPerCluster
= FileFsSize
.SectorsPerAllocationUnit
;
203 *lpNumberOfFreeClusters
= FileFsSize
.AvailableAllocationUnits
.u
.LowPart
;
204 *lpTotalNumberOfClusters
= FileFsSize
.TotalAllocationUnits
.u
.LowPart
;
211 GetDiskFreeSpaceExA (
212 LPCSTR lpDirectoryName
,
213 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
214 PULARGE_INTEGER lpTotalNumberOfBytes
,
215 PULARGE_INTEGER lpTotalNumberOfFreeBytes
218 UNICODE_STRING DirectoryNameU
;
219 ANSI_STRING DirectoryName
;
222 RtlInitAnsiString (&DirectoryName
,
223 (LPSTR
)lpDirectoryName
);
225 RtlInitUnicodeString (&DirectoryNameU
,
230 /* convert ansi (or oem) string to unicode */
232 RtlAnsiStringToUnicodeString (&DirectoryNameU
,
236 RtlOemStringToUnicodeString (&DirectoryNameU
,
241 Result
= GetDiskFreeSpaceExW (DirectoryNameU
.Buffer
,
242 lpFreeBytesAvailableToCaller
,
243 lpTotalNumberOfBytes
,
244 lpTotalNumberOfFreeBytes
);
248 RtlFreeHeap (RtlGetProcessHeap (),
250 DirectoryNameU
.Buffer
);
259 LPCWSTR lpDirectoryName
,
260 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
261 PULARGE_INTEGER lpTotalNumberOfBytes
,
262 PULARGE_INTEGER lpTotalNumberOfFreeBytes
265 FILE_FS_SIZE_INFORMATION FileFsSize
;
266 IO_STATUS_BLOCK IoStatusBlock
;
267 ULARGE_INTEGER BytesPerCluster
;
268 WCHAR RootPathName
[MAX_PATH
];
274 wcsncpy (RootPathName
, lpDirectoryName
, 3);
278 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
282 hFile
= CreateFileW(RootPathName
,
283 FILE_READ_ATTRIBUTES
,
287 FILE_ATTRIBUTE_NORMAL
,
290 errCode
= NtQueryVolumeInformationFile(hFile
,
293 sizeof(FILE_FS_SIZE_INFORMATION
),
294 FileFsSizeInformation
);
295 if (!NT_SUCCESS(errCode
))
298 SetLastErrorByStatus (errCode
);
302 BytesPerCluster
.QuadPart
=
303 FileFsSize
.BytesPerSector
* FileFsSize
.SectorsPerAllocationUnit
;
305 // FIXME: Use quota information
306 if (lpFreeBytesAvailableToCaller
)
307 lpFreeBytesAvailableToCaller
->QuadPart
=
308 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
310 if (lpTotalNumberOfBytes
)
311 lpTotalNumberOfBytes
->QuadPart
=
312 BytesPerCluster
.QuadPart
* FileFsSize
.TotalAllocationUnits
.QuadPart
;
313 if (lpTotalNumberOfFreeBytes
)
314 lpTotalNumberOfFreeBytes
->QuadPart
=
315 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
323 GetDriveTypeA(LPCSTR lpRootPathName
)
325 UNICODE_STRING RootPathNameU
;
326 ANSI_STRING RootPathName
;
329 RtlInitAnsiString (&RootPathName
,
330 (LPSTR
)lpRootPathName
);
332 /* convert ansi (or oem) string to unicode */
334 RtlAnsiStringToUnicodeString (&RootPathNameU
,
338 RtlOemStringToUnicodeString (&RootPathNameU
,
342 Result
= GetDriveTypeW (RootPathNameU
.Buffer
);
344 RtlFreeHeap (RtlGetProcessHeap (),
346 RootPathNameU
.Buffer
);
353 GetDriveTypeW(LPCWSTR lpRootPathName
)
355 FILE_FS_DEVICE_INFORMATION FileFsDevice
;
356 IO_STATUS_BLOCK IoStatusBlock
;
361 hFile
= CreateFileW (lpRootPathName
,
363 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
366 FILE_ATTRIBUTE_NORMAL
,
369 errCode
= NtQueryVolumeInformationFile (hFile
,
372 sizeof(FILE_FS_DEVICE_INFORMATION
),
373 FileFsDeviceInformation
);
374 if (!NT_SUCCESS(errCode
))
377 SetLastErrorByStatus (errCode
);
381 return (UINT
)FileFsDevice
.DeviceType
;
386 GetVolumeInformationA(
387 LPCSTR lpRootPathName
,
388 LPSTR lpVolumeNameBuffer
,
389 DWORD nVolumeNameSize
,
390 LPDWORD lpVolumeSerialNumber
,
391 LPDWORD lpMaximumComponentLength
,
392 LPDWORD lpFileSystemFlags
,
393 LPSTR lpFileSystemNameBuffer
,
394 DWORD nFileSystemNameSize
397 UNICODE_STRING RootPathNameU
;
398 UNICODE_STRING FileSystemNameU
;
399 UNICODE_STRING VolumeNameU
;
400 ANSI_STRING RootPathName
;
401 ANSI_STRING VolumeName
;
402 ANSI_STRING FileSystemName
;
405 RtlInitAnsiString (&RootPathName
,
406 (LPSTR
)lpRootPathName
);
408 /* convert ansi (or oem) string to unicode */
410 RtlAnsiStringToUnicodeString (&RootPathNameU
,
414 RtlOemStringToUnicodeString (&RootPathNameU
,
418 VolumeNameU
.Length
= 0;
419 VolumeNameU
.MaximumLength
= nVolumeNameSize
* sizeof(WCHAR
);
420 VolumeNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
422 VolumeNameU
.MaximumLength
);
424 FileSystemNameU
.Length
= 0;
425 FileSystemNameU
.MaximumLength
= nFileSystemNameSize
* sizeof(WCHAR
);
426 FileSystemNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
428 FileSystemNameU
.MaximumLength
);
430 Result
= GetVolumeInformationW (RootPathNameU
.Buffer
,
433 lpVolumeSerialNumber
,
434 lpMaximumComponentLength
,
436 FileSystemNameU
.Buffer
,
437 nFileSystemNameSize
);
441 VolumeNameU
.Length
= wcslen(VolumeNameU
.Buffer
) * sizeof(WCHAR
);
442 VolumeName
.Length
= 0;
443 VolumeName
.MaximumLength
= nVolumeNameSize
;
444 VolumeName
.Buffer
= lpVolumeNameBuffer
;
446 FileSystemNameU
.Length
= wcslen(FileSystemNameU
.Buffer
) * sizeof(WCHAR
);
447 FileSystemName
.Length
= 0;
448 FileSystemName
.MaximumLength
= nFileSystemNameSize
;
449 FileSystemName
.Buffer
= lpFileSystemNameBuffer
;
451 /* convert unicode strings to ansi (or oem) */
454 RtlUnicodeStringToAnsiString (&VolumeName
,
457 RtlUnicodeStringToAnsiString (&FileSystemName
,
463 RtlUnicodeStringToOemString (&VolumeName
,
466 RtlUnicodeStringToOemString (&FileSystemName
,
472 RtlFreeHeap (RtlGetProcessHeap (),
474 RootPathNameU
.Buffer
);
475 RtlFreeHeap (RtlGetProcessHeap (),
478 RtlFreeHeap (RtlGetProcessHeap (),
480 FileSystemNameU
.Buffer
);
488 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
490 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
494 GetVolumeInformationW(
495 LPCWSTR lpRootPathName
,
496 LPWSTR lpVolumeNameBuffer
,
497 DWORD nVolumeNameSize
,
498 LPDWORD lpVolumeSerialNumber
,
499 LPDWORD lpMaximumComponentLength
,
500 LPDWORD lpFileSystemFlags
,
501 LPWSTR lpFileSystemNameBuffer
,
502 DWORD nFileSystemNameSize
505 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
506 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
507 IO_STATUS_BLOCK IoStatusBlock
;
508 OBJECT_ATTRIBUTES ObjectAttributes
;
509 UNICODE_STRING NtPathU
;
510 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
511 USHORT Buffer2
[FS_ATTRIBUTE_BUFFER_SIZE
];
516 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
517 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer2
;
519 DPRINT("FileFsVolume %p\n", FileFsVolume
);
520 DPRINT("FileFsAttribute %p\n", FileFsAttribute
);
522 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpRootPathName
,
527 DPRINT("Invalid path\n");
528 SetLastError(ERROR_BAD_PATHNAME
);
532 InitializeObjectAttributes(&ObjectAttributes
,
534 FILE_READ_ATTRIBUTES
,
538 errCode
= NtCreateFile (&hFile
,
544 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
550 RtlFreeUnicodeString(&NtPathU
);
552 if (!NT_SUCCESS(errCode
))
554 SetLastErrorByStatus (errCode
);
558 DPRINT("hFile: %x\n", hFile
);
559 errCode
= NtQueryVolumeInformationFile(hFile
,
562 FS_VOLUME_BUFFER_SIZE
,
563 FileFsVolumeInformation
);
564 if ( !NT_SUCCESS(errCode
) ) {
565 DPRINT("Status: %x\n", errCode
);
567 SetLastErrorByStatus (errCode
);
571 if (lpVolumeSerialNumber
)
572 *lpVolumeSerialNumber
= FileFsVolume
->VolumeSerialNumber
;
574 if (lpVolumeNameBuffer
)
575 wcsncpy (lpVolumeNameBuffer
,
576 FileFsVolume
->VolumeLabel
,
577 min(nVolumeNameSize
,MAX_PATH
));
579 errCode
= NtQueryVolumeInformationFile (hFile
,
582 FS_ATTRIBUTE_BUFFER_SIZE
,
583 FileFsAttributeInformation
);
584 if (!NT_SUCCESS(errCode
))
586 DPRINT("Status: %x\n", errCode
);
588 SetLastErrorByStatus (errCode
);
592 if (lpFileSystemFlags
)
593 *lpFileSystemFlags
= FileFsAttribute
->FileSystemAttributes
;
594 if (lpMaximumComponentLength
)
595 *lpMaximumComponentLength
= FileFsAttribute
->MaximumComponentNameLength
;
596 if (lpFileSystemNameBuffer
)
597 wcsncpy(lpFileSystemNameBuffer
, FileFsAttribute
->FileSystemName
,min(nFileSystemNameSize
,MAX_PATH
));
607 LPCSTR lpRootPathName
,
611 UNICODE_STRING RootPathNameU
;
612 ANSI_STRING RootPathName
;
613 UNICODE_STRING VolumeNameU
;
614 ANSI_STRING VolumeName
;
617 RtlInitAnsiString (&RootPathName
,
618 (LPSTR
)lpRootPathName
);
619 RtlInitAnsiString (&VolumeName
,
620 (LPSTR
)lpVolumeName
);
622 /* convert ansi (or oem) strings to unicode */
625 RtlAnsiStringToUnicodeString (&RootPathNameU
,
628 RtlAnsiStringToUnicodeString (&VolumeNameU
,
634 RtlOemStringToUnicodeString (&RootPathNameU
,
637 RtlOemStringToUnicodeString (&VolumeNameU
,
642 Result
= SetVolumeLabelW (RootPathNameU
.Buffer
,
645 RtlFreeHeap (RtlGetProcessHeap (),
647 RootPathNameU
.Buffer
);
648 RtlFreeHeap (RtlGetProcessHeap (),
657 SetVolumeLabelW(LPCWSTR lpRootPathName
,
658 LPCWSTR lpVolumeName
)
660 PFILE_FS_LABEL_INFORMATION LabelInfo
;
661 IO_STATUS_BLOCK IoStatusBlock
;
666 LabelLength
= wcslen(lpVolumeName
) * sizeof(WCHAR
);
667 LabelInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
669 sizeof(FILE_FS_LABEL_INFORMATION
) +
671 LabelInfo
->VolumeLabelLength
= LabelLength
;
672 wcscpy(LabelInfo
->VolumeLabel
,
675 hFile
= CreateFileW(lpRootPathName
,
676 FILE_WRITE_ATTRIBUTES
,
677 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
680 FILE_ATTRIBUTE_NORMAL
,
682 DPRINT("hFile: %x\n", hFile
);
684 Status
= NtSetVolumeInformationFile(hFile
,
687 sizeof(FILE_FS_LABEL_INFORMATION
) +
689 FileFsLabelInformation
);
691 RtlFreeHeap(RtlGetProcessHeap(),
695 if (!NT_SUCCESS(Status
))
697 DPRINT("Status: %x\n", Status
);
699 SetLastErrorByStatus(Status
);