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
22 #include <ddk/ntddk.h>
27 #include <kernel32/kernel32.h>
30 #define MAX_DOS_DRIVES 26
33 int DRIVE_IsValid( int drive
)
41 Drives
[0] = 'A' + drive
-1;
42 if ((drive
< 0) || (drive
>= MAX_DOS_DRIVES
)) return 0;
43 if ( CreateFileA(Drives
,GENERIC_READ
,FILE_SHARE_READ
,NULL
,OPEN_EXISTING
,FILE_FLAG_BACKUP_SEMANTICS
|FILE_ATTRIBUTE_DIRECTORY
,NULL
) == INVALID_HANDLE_VALUE
) {
53 GetLogicalDriveStringsA(
60 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
61 if (DRIVE_IsValid(drive
)) count
++;
62 if (count
* 4 * sizeof(char) <= nBufferLength
)
65 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
66 if (DRIVE_IsValid(drive
))
75 return count
* 4 * sizeof(char);
81 GetLogicalDriveStringsW(
88 for (drive
= count
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
89 if (DRIVE_IsValid(drive
)) count
++;
90 if (count
* 4 * sizeof(WCHAR
) <= nBufferLength
)
93 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
94 if (DRIVE_IsValid(drive
))
96 *p
++ = (WCHAR
)('A' + drive
);
103 return count
* 4 * sizeof(WCHAR
);
109 GetLogicalDrives(VOID
)
114 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
115 if (DRIVE_IsValid(drive
)) ret
|= (1 << drive
);
124 LPCSTR lpRootPathName
,
125 LPDWORD lpSectorsPerCluster
,
126 LPDWORD lpBytesPerSector
,
127 LPDWORD lpNumberOfFreeClusters
,
128 LPDWORD lpTotalNumberOfClusters
131 WCHAR RootPathNameW
[MAX_PATH
];
136 while ((*lpRootPathName
)!=0 && i
< MAX_PATH
)
138 RootPathNameW
[i
] = *lpRootPathName
;
142 RootPathNameW
[i
] = 0;
145 return GetDiskFreeSpaceW(lpRootPathName
?RootPathNameW
:NULL
,
148 lpNumberOfFreeClusters
,
149 lpTotalNumberOfClusters
);
155 LPCWSTR lpRootPathName
,
156 LPDWORD lpSectorsPerCluster
,
157 LPDWORD lpBytesPerSector
,
158 LPDWORD lpNumberOfFreeClusters
,
159 LPDWORD lpTotalNumberOfClusters
162 FILE_FS_SIZE_INFORMATION FileFsSize
;
163 IO_STATUS_BLOCK IoStatusBlock
;
164 WCHAR RootPathName
[MAX_PATH
];
170 wcsncpy (RootPathName
, lpRootPathName
, 3);
174 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
178 hFile
= CreateFileW(RootPathName
,
179 FILE_READ_ATTRIBUTES
,
183 FILE_ATTRIBUTE_NORMAL
,
186 errCode
= NtQueryVolumeInformationFile(hFile
,
189 sizeof(FILE_FS_SIZE_INFORMATION
),
190 FileFsSizeInformation
);
191 if (!NT_SUCCESS(errCode
))
194 SetLastError(RtlNtStatusToDosError(errCode
));
198 *lpBytesPerSector
= FileFsSize
.BytesPerSector
;
199 *lpSectorsPerCluster
= FileFsSize
.SectorsPerAllocationUnit
;
200 *lpNumberOfFreeClusters
= FileFsSize
.AvailableAllocationUnits
.u
.LowPart
;
201 *lpTotalNumberOfClusters
= FileFsSize
.TotalAllocationUnits
.u
.LowPart
;
209 LPCSTR lpDirectoryName
,
210 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
211 PULARGE_INTEGER lpTotalNumberOfBytes
,
212 PULARGE_INTEGER lpTotalNumberOfFreeBytes
215 WCHAR DirectoryNameW
[MAX_PATH
];
220 while ((*lpDirectoryName
)!=0 && i
< MAX_PATH
)
222 DirectoryNameW
[i
] = *lpDirectoryName
;
226 DirectoryNameW
[i
] = 0;
229 return GetDiskFreeSpaceExW(lpDirectoryName
?DirectoryNameW
:NULL
,
230 lpFreeBytesAvailableToCaller
,
231 lpTotalNumberOfBytes
,
232 lpTotalNumberOfFreeBytes
);
239 LPCWSTR lpDirectoryName
,
240 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
241 PULARGE_INTEGER lpTotalNumberOfBytes
,
242 PULARGE_INTEGER lpTotalNumberOfFreeBytes
245 FILE_FS_SIZE_INFORMATION FileFsSize
;
246 IO_STATUS_BLOCK IoStatusBlock
;
247 ULARGE_INTEGER BytesPerCluster
;
248 WCHAR RootPathName
[MAX_PATH
];
254 wcsncpy (RootPathName
, lpDirectoryName
, 3);
258 GetCurrentDirectoryW (MAX_PATH
, RootPathName
);
262 hFile
= CreateFileW(RootPathName
,
263 FILE_READ_ATTRIBUTES
,
267 FILE_ATTRIBUTE_NORMAL
,
270 errCode
= NtQueryVolumeInformationFile(hFile
,
273 sizeof(FILE_FS_SIZE_INFORMATION
),
274 FileFsSizeInformation
);
275 if (!NT_SUCCESS(errCode
))
278 SetLastError(RtlNtStatusToDosError(errCode
));
282 BytesPerCluster
.QuadPart
=
283 FileFsSize
.BytesPerSector
* FileFsSize
.SectorsPerAllocationUnit
;
285 // FIXME: Use quota information
286 lpFreeBytesAvailableToCaller
->QuadPart
=
287 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
289 lpTotalNumberOfBytes
->QuadPart
=
290 BytesPerCluster
.QuadPart
* FileFsSize
.TotalAllocationUnits
.QuadPart
;
291 lpTotalNumberOfFreeBytes
->QuadPart
=
292 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
302 LPCSTR lpRootPathName
306 WCHAR RootPathNameW
[MAX_PATH
];
308 while ((*lpRootPathName
)!=0 && i
< MAX_PATH
)
310 RootPathNameW
[i
] = *lpRootPathName
;
314 RootPathNameW
[i
] = 0;
315 return GetDriveTypeW(RootPathNameW
);
321 LPCWSTR lpRootPathName
324 FILE_FS_DEVICE_INFORMATION FileFsDevice
;
325 IO_STATUS_BLOCK IoStatusBlock
;
333 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
336 FILE_ATTRIBUTE_NORMAL
,
340 errCode
= NtQueryVolumeInformationFile(hFile
,&IoStatusBlock
,&FileFsDevice
, sizeof(FILE_FS_DEVICE_INFORMATION
),FileFsDeviceInformation
);
341 if ( !NT_SUCCESS(errCode
) ) {
343 SetLastError(RtlNtStatusToDosError(errCode
));
347 return (UINT
)FileFsDevice
.DeviceType
;
355 GetVolumeInformationA(
356 LPCSTR lpRootPathName
,
357 LPSTR lpVolumeNameBuffer
,
358 DWORD nVolumeNameSize
,
359 LPDWORD lpVolumeSerialNumber
,
360 LPDWORD lpMaximumComponentLength
,
361 LPDWORD lpFileSystemFlags
,
362 LPSTR lpFileSystemNameBuffer
,
363 DWORD nFileSystemNameSize
367 WCHAR RootPathNameW
[MAX_PATH
];
368 WCHAR VolumeNameBufferW
[MAX_PATH
];
369 WCHAR FileSystemNameBufferW
[MAX_PATH
];
373 while ((*lpRootPathName
)!=0 && i
< MAX_PATH
)
375 RootPathNameW
[i
] = *lpRootPathName
;
379 RootPathNameW
[i
] = 0;
381 if ( GetVolumeInformationW(RootPathNameW
,
384 lpVolumeSerialNumber
,
385 lpMaximumComponentLength
,
387 FileSystemNameBufferW
,
388 nFileSystemNameSize
) ) {
389 for(i
=0;i
<nVolumeNameSize
;i
++)
390 lpVolumeNameBuffer
[i
] = (CHAR
)VolumeNameBufferW
[i
];
392 for(i
=0;i
<nFileSystemNameSize
;i
++)
393 lpFileSystemNameBuffer
[i
] = (CHAR
)FileSystemNameBufferW
[i
];
404 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
406 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
411 GetVolumeInformationW(
412 LPCWSTR lpRootPathName
,
413 LPWSTR lpVolumeNameBuffer
,
414 DWORD nVolumeNameSize
,
415 LPDWORD lpVolumeSerialNumber
,
416 LPDWORD lpMaximumComponentLength
,
417 LPDWORD lpFileSystemFlags
,
418 LPWSTR lpFileSystemNameBuffer
,
419 DWORD nFileSystemNameSize
422 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
423 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
424 IO_STATUS_BLOCK IoStatusBlock
;
425 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
426 USHORT Buffer2
[FS_ATTRIBUTE_BUFFER_SIZE
];
431 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
432 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer2
;
434 DPRINT("FileFsVolume %p\n", FileFsVolume
);
435 DPRINT("FileFsAttribute %p\n", FileFsAttribute
);
437 hFile
= CreateFileW(lpRootPathName
,
438 FILE_READ_ATTRIBUTES
,
439 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
442 FILE_ATTRIBUTE_NORMAL
,
445 DPRINT("hFile: %x\n", hFile
);
446 errCode
= NtQueryVolumeInformationFile(hFile
,
449 FS_VOLUME_BUFFER_SIZE
,
450 FileFsVolumeInformation
);
451 if ( !NT_SUCCESS(errCode
) ) {
452 DPRINT("Status: %x\n", errCode
);
454 SetLastError(RtlNtStatusToDosError(errCode
));
458 if (lpVolumeSerialNumber
)
459 *lpVolumeSerialNumber
= FileFsVolume
->VolumeSerialNumber
;
461 if (lpVolumeNameBuffer
)
462 wcsncpy(lpVolumeNameBuffer
, FileFsVolume
->VolumeLabel
,min(nVolumeNameSize
,MAX_PATH
));
464 errCode
= NtQueryVolumeInformationFile(hFile
,&IoStatusBlock
,FileFsAttribute
, FS_ATTRIBUTE_BUFFER_SIZE
,FileFsAttributeInformation
);
465 if ( !NT_SUCCESS(errCode
) ) {
466 DPRINT("Status: %x\n", errCode
);
468 SetLastError(RtlNtStatusToDosError(errCode
));
472 if (lpFileSystemFlags
)
473 *lpFileSystemFlags
= FileFsAttribute
->FileSystemAttributes
;
474 if (lpMaximumComponentLength
)
475 *lpMaximumComponentLength
= FileFsAttribute
->MaximumComponentNameLength
;
476 if (lpFileSystemNameBuffer
)
477 wcsncpy(lpFileSystemNameBuffer
, FileFsAttribute
->FileSystemName
,min(nFileSystemNameSize
,MAX_PATH
));
486 LPCSTR lpRootPathName
,
490 WCHAR RootPathNameW
[MAX_PATH
];
491 WCHAR VolumeNameW
[MAX_PATH
];
495 while ((*lpRootPathName
)!=0 && i
< MAX_PATH
)
497 RootPathNameW
[i
] = *lpRootPathName
;
501 RootPathNameW
[i
] = 0;
504 while ((*lpVolumeName
)!=0 && i
< MAX_PATH
)
506 VolumeNameW
[i
] = *lpVolumeName
;
511 return SetVolumeLabelW(RootPathNameW
,VolumeNameW
);
517 LPCWSTR lpRootPathName
,