1 /* $Id: volume.c,v 1.27 2002/12/06 17:33:16 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>
24 #include <ntos/minmax.h>
27 #include <kernel32/kernel32.h>
28 #include <kernel32/error.h>
31 #define MAX_DOS_DRIVES 26
35 InternalOpenDirW(LPCWSTR DirName
,
38 UNICODE_STRING NtPathU
;
39 OBJECT_ATTRIBUTES ObjectAttributes
;
41 IO_STATUS_BLOCK IoStatusBlock
;
44 if (!RtlDosPathNameToNtPathName_U((LPWSTR
)DirName
,
49 DPRINT("Invalid path\n");
50 SetLastError(ERROR_BAD_PATHNAME
);
51 return INVALID_HANDLE_VALUE
;
54 InitializeObjectAttributes(&ObjectAttributes
,
56 Write
? FILE_WRITE_ATTRIBUTES
: FILE_READ_ATTRIBUTES
,
60 errCode
= NtCreateFile (&hFile
,
61 Write
? FILE_GENERIC_WRITE
: FILE_GENERIC_READ
,
66 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
72 RtlFreeUnicodeString(&NtPathU
);
74 if (!NT_SUCCESS(errCode
))
76 SetLastErrorByStatus (errCode
);
77 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));
118 GetLogicalDriveStringsW(DWORD nBufferLength
,
124 dwDriveMap
= SharedUserData
->DosDeviceMap
;
126 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
128 if (dwDriveMap
& (1<<drive
))
132 if (count
* 4 * sizeof(WCHAR
) <= nBufferLength
)
135 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
136 if (dwDriveMap
& (1<<drive
))
138 *p
++ = (WCHAR
)('A' + drive
);
145 return (count
* 4 * sizeof(WCHAR
));
150 GetLogicalDrives(VOID
)
152 return(SharedUserData
->DosDeviceMap
);
158 LPCSTR lpRootPathName
,
159 LPDWORD lpSectorsPerCluster
,
160 LPDWORD lpBytesPerSector
,
161 LPDWORD lpNumberOfFreeClusters
,
162 LPDWORD lpTotalNumberOfClusters
165 UNICODE_STRING RootPathNameU
;
166 ANSI_STRING RootPathName
;
169 RtlInitAnsiString (&RootPathName
,
170 (LPSTR
)lpRootPathName
);
172 RtlInitUnicodeString (&RootPathNameU
,
177 /* convert ansi (or oem) string to unicode */
179 RtlAnsiStringToUnicodeString (&RootPathNameU
,
183 RtlOemStringToUnicodeString (&RootPathNameU
,
188 Result
= GetDiskFreeSpaceW (RootPathNameU
.Buffer
,
191 lpNumberOfFreeClusters
,
192 lpTotalNumberOfClusters
);
196 RtlFreeHeap (RtlGetProcessHeap (),
198 RootPathNameU
.Buffer
);
207 LPCWSTR lpRootPathName
,
208 LPDWORD lpSectorsPerCluster
,
209 LPDWORD lpBytesPerSector
,
210 LPDWORD lpNumberOfFreeClusters
,
211 LPDWORD lpTotalNumberOfClusters
214 FILE_FS_SIZE_INFORMATION FileFsSize
;
215 IO_STATUS_BLOCK IoStatusBlock
;
216 WCHAR RootPathName
[MAX_PATH
];
222 wcsncpy (RootPathName
, lpRootPathName
, 3);
226 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
230 hFile
= InternalOpenDirW(lpRootPathName
, FALSE
);
231 if (INVALID_HANDLE_VALUE
== hFile
)
236 errCode
= NtQueryVolumeInformationFile(hFile
,
239 sizeof(FILE_FS_SIZE_INFORMATION
),
240 FileFsSizeInformation
);
241 if (!NT_SUCCESS(errCode
))
244 SetLastErrorByStatus (errCode
);
248 *lpBytesPerSector
= FileFsSize
.BytesPerSector
;
249 *lpSectorsPerCluster
= FileFsSize
.SectorsPerAllocationUnit
;
250 *lpNumberOfFreeClusters
= FileFsSize
.AvailableAllocationUnits
.u
.LowPart
;
251 *lpTotalNumberOfClusters
= FileFsSize
.TotalAllocationUnits
.u
.LowPart
;
258 GetDiskFreeSpaceExA (
259 LPCSTR lpDirectoryName
,
260 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
261 PULARGE_INTEGER lpTotalNumberOfBytes
,
262 PULARGE_INTEGER lpTotalNumberOfFreeBytes
265 UNICODE_STRING DirectoryNameU
;
266 ANSI_STRING DirectoryName
;
269 RtlInitAnsiString (&DirectoryName
,
270 (LPSTR
)lpDirectoryName
);
272 RtlInitUnicodeString (&DirectoryNameU
,
277 /* convert ansi (or oem) string to unicode */
279 RtlAnsiStringToUnicodeString (&DirectoryNameU
,
283 RtlOemStringToUnicodeString (&DirectoryNameU
,
288 Result
= GetDiskFreeSpaceExW (DirectoryNameU
.Buffer
,
289 lpFreeBytesAvailableToCaller
,
290 lpTotalNumberOfBytes
,
291 lpTotalNumberOfFreeBytes
);
295 RtlFreeHeap (RtlGetProcessHeap (),
297 DirectoryNameU
.Buffer
);
306 LPCWSTR lpDirectoryName
,
307 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
308 PULARGE_INTEGER lpTotalNumberOfBytes
,
309 PULARGE_INTEGER lpTotalNumberOfFreeBytes
312 FILE_FS_SIZE_INFORMATION FileFsSize
;
313 IO_STATUS_BLOCK IoStatusBlock
;
314 ULARGE_INTEGER BytesPerCluster
;
315 WCHAR RootPathName
[MAX_PATH
];
321 wcsncpy (RootPathName
, lpDirectoryName
, 3);
325 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
329 hFile
= InternalOpenDirW(lpDirectoryName
, FALSE
);
330 if (INVALID_HANDLE_VALUE
== hFile
)
335 errCode
= NtQueryVolumeInformationFile(hFile
,
338 sizeof(FILE_FS_SIZE_INFORMATION
),
339 FileFsSizeInformation
);
340 if (!NT_SUCCESS(errCode
))
343 SetLastErrorByStatus (errCode
);
347 BytesPerCluster
.QuadPart
=
348 FileFsSize
.BytesPerSector
* FileFsSize
.SectorsPerAllocationUnit
;
350 // FIXME: Use quota information
351 if (lpFreeBytesAvailableToCaller
)
352 lpFreeBytesAvailableToCaller
->QuadPart
=
353 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
355 if (lpTotalNumberOfBytes
)
356 lpTotalNumberOfBytes
->QuadPart
=
357 BytesPerCluster
.QuadPart
* FileFsSize
.TotalAllocationUnits
.QuadPart
;
358 if (lpTotalNumberOfFreeBytes
)
359 lpTotalNumberOfFreeBytes
->QuadPart
=
360 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
368 GetDriveTypeA(LPCSTR lpRootPathName
)
370 UNICODE_STRING RootPathNameU
;
371 ANSI_STRING RootPathName
;
374 RtlInitAnsiString (&RootPathName
,
375 (LPSTR
)lpRootPathName
);
377 /* convert ansi (or oem) string to unicode */
379 RtlAnsiStringToUnicodeString (&RootPathNameU
,
383 RtlOemStringToUnicodeString (&RootPathNameU
,
387 Result
= GetDriveTypeW (RootPathNameU
.Buffer
);
389 RtlFreeHeap (RtlGetProcessHeap (),
391 RootPathNameU
.Buffer
);
397 GetDriveTypeW(LPCWSTR lpRootPathName
)
399 FILE_FS_DEVICE_INFORMATION FileFsDevice
;
400 IO_STATUS_BLOCK IoStatusBlock
;
405 hFile
= InternalOpenDirW(lpRootPathName
, FALSE
);
406 if (hFile
== INVALID_HANDLE_VALUE
)
411 errCode
= NtQueryVolumeInformationFile (hFile
,
414 sizeof(FILE_FS_DEVICE_INFORMATION
),
415 FileFsDeviceInformation
);
416 if (!NT_SUCCESS(errCode
))
419 SetLastErrorByStatus (errCode
);
423 return (UINT
)FileFsDevice
.DeviceType
;
428 GetVolumeInformationA(
429 LPCSTR lpRootPathName
,
430 LPSTR lpVolumeNameBuffer
,
431 DWORD nVolumeNameSize
,
432 LPDWORD lpVolumeSerialNumber
,
433 LPDWORD lpMaximumComponentLength
,
434 LPDWORD lpFileSystemFlags
,
435 LPSTR lpFileSystemNameBuffer
,
436 DWORD nFileSystemNameSize
439 UNICODE_STRING RootPathNameU
;
440 UNICODE_STRING FileSystemNameU
;
441 UNICODE_STRING VolumeNameU
;
442 ANSI_STRING RootPathName
;
443 ANSI_STRING VolumeName
;
444 ANSI_STRING FileSystemName
;
447 RtlInitAnsiString (&RootPathName
,
448 (LPSTR
)lpRootPathName
);
450 /* convert ansi (or oem) string to unicode */
452 RtlAnsiStringToUnicodeString (&RootPathNameU
,
456 RtlOemStringToUnicodeString (&RootPathNameU
,
460 VolumeNameU
.Length
= 0;
461 VolumeNameU
.MaximumLength
= nVolumeNameSize
* sizeof(WCHAR
);
462 VolumeNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
464 VolumeNameU
.MaximumLength
);
466 FileSystemNameU
.Length
= 0;
467 FileSystemNameU
.MaximumLength
= nFileSystemNameSize
* sizeof(WCHAR
);
468 FileSystemNameU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
470 FileSystemNameU
.MaximumLength
);
472 Result
= GetVolumeInformationW (RootPathNameU
.Buffer
,
475 lpVolumeSerialNumber
,
476 lpMaximumComponentLength
,
478 FileSystemNameU
.Buffer
,
479 nFileSystemNameSize
);
483 VolumeNameU
.Length
= wcslen(VolumeNameU
.Buffer
) * sizeof(WCHAR
);
484 VolumeName
.Length
= 0;
485 VolumeName
.MaximumLength
= nVolumeNameSize
;
486 VolumeName
.Buffer
= lpVolumeNameBuffer
;
488 FileSystemNameU
.Length
= wcslen(FileSystemNameU
.Buffer
) * sizeof(WCHAR
);
489 FileSystemName
.Length
= 0;
490 FileSystemName
.MaximumLength
= nFileSystemNameSize
;
491 FileSystemName
.Buffer
= lpFileSystemNameBuffer
;
493 /* convert unicode strings to ansi (or oem) */
496 RtlUnicodeStringToAnsiString (&VolumeName
,
499 RtlUnicodeStringToAnsiString (&FileSystemName
,
505 RtlUnicodeStringToOemString (&VolumeName
,
508 RtlUnicodeStringToOemString (&FileSystemName
,
514 RtlFreeHeap (RtlGetProcessHeap (),
516 RootPathNameU
.Buffer
);
517 RtlFreeHeap (RtlGetProcessHeap (),
520 RtlFreeHeap (RtlGetProcessHeap (),
522 FileSystemNameU
.Buffer
);
530 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
532 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
536 GetVolumeInformationW(
537 LPCWSTR lpRootPathName
,
538 LPWSTR lpVolumeNameBuffer
,
539 DWORD nVolumeNameSize
,
540 LPDWORD lpVolumeSerialNumber
,
541 LPDWORD lpMaximumComponentLength
,
542 LPDWORD lpFileSystemFlags
,
543 LPWSTR lpFileSystemNameBuffer
,
544 DWORD nFileSystemNameSize
547 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
548 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
549 IO_STATUS_BLOCK IoStatusBlock
;
550 OBJECT_ATTRIBUTES ObjectAttributes
;
551 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
552 USHORT Buffer2
[FS_ATTRIBUTE_BUFFER_SIZE
];
557 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
558 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer2
;
560 DPRINT("FileFsVolume %p\n", FileFsVolume
);
561 DPRINT("FileFsAttribute %p\n", FileFsAttribute
);
563 hFile
= InternalOpenDirW(lpRootPathName
, FALSE
);
564 if (hFile
== INVALID_HANDLE_VALUE
)
569 DPRINT("hFile: %x\n", hFile
);
570 errCode
= NtQueryVolumeInformationFile(hFile
,
573 FS_VOLUME_BUFFER_SIZE
,
574 FileFsVolumeInformation
);
575 if ( !NT_SUCCESS(errCode
) ) {
576 DPRINT("Status: %x\n", errCode
);
578 SetLastErrorByStatus (errCode
);
582 if (lpVolumeSerialNumber
)
583 *lpVolumeSerialNumber
= FileFsVolume
->VolumeSerialNumber
;
585 if (lpVolumeNameBuffer
)
586 wcsncpy (lpVolumeNameBuffer
,
587 FileFsVolume
->VolumeLabel
,
588 min(nVolumeNameSize
,MAX_PATH
));
590 errCode
= NtQueryVolumeInformationFile (hFile
,
593 FS_ATTRIBUTE_BUFFER_SIZE
,
594 FileFsAttributeInformation
);
595 if (!NT_SUCCESS(errCode
))
597 DPRINT("Status: %x\n", errCode
);
599 SetLastErrorByStatus (errCode
);
603 if (lpFileSystemFlags
)
604 *lpFileSystemFlags
= FileFsAttribute
->FileSystemAttributes
;
605 if (lpMaximumComponentLength
)
606 *lpMaximumComponentLength
= FileFsAttribute
->MaximumComponentNameLength
;
607 if (lpFileSystemNameBuffer
)
608 wcsncpy(lpFileSystemNameBuffer
, FileFsAttribute
->FileSystemName
,min(nFileSystemNameSize
,MAX_PATH
));
618 LPCSTR lpRootPathName
,
622 UNICODE_STRING RootPathNameU
;
623 ANSI_STRING RootPathName
;
624 UNICODE_STRING VolumeNameU
;
625 ANSI_STRING VolumeName
;
628 RtlInitAnsiString (&RootPathName
,
629 (LPSTR
)lpRootPathName
);
630 RtlInitAnsiString (&VolumeName
,
631 (LPSTR
)lpVolumeName
);
633 /* convert ansi (or oem) strings to unicode */
636 RtlAnsiStringToUnicodeString (&RootPathNameU
,
639 RtlAnsiStringToUnicodeString (&VolumeNameU
,
645 RtlOemStringToUnicodeString (&RootPathNameU
,
648 RtlOemStringToUnicodeString (&VolumeNameU
,
653 Result
= SetVolumeLabelW (RootPathNameU
.Buffer
,
656 RtlFreeHeap (RtlGetProcessHeap (),
658 RootPathNameU
.Buffer
);
659 RtlFreeHeap (RtlGetProcessHeap (),
668 SetVolumeLabelW(LPCWSTR lpRootPathName
,
669 LPCWSTR lpVolumeName
)
671 PFILE_FS_LABEL_INFORMATION LabelInfo
;
672 IO_STATUS_BLOCK IoStatusBlock
;
677 LabelLength
= wcslen(lpVolumeName
) * sizeof(WCHAR
);
678 LabelInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
680 sizeof(FILE_FS_LABEL_INFORMATION
) +
682 LabelInfo
->VolumeLabelLength
= LabelLength
;
683 wcscpy(LabelInfo
->VolumeLabel
,
686 hFile
= InternalOpenDirW(lpRootPathName
, TRUE
);
687 if (INVALID_HANDLE_VALUE
== hFile
)
692 Status
= NtSetVolumeInformationFile(hFile
,
695 sizeof(FILE_FS_LABEL_INFORMATION
) +
697 FileFsLabelInformation
);
699 RtlFreeHeap(RtlGetProcessHeap(),
703 if (!NT_SUCCESS(Status
))
705 DPRINT("Status: %x\n", Status
);
707 SetLastErrorByStatus(Status
);