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
132 WCHAR RootPathNameW
[MAX_PATH
];
134 while ((*lpRootPathName
)!=0 && i
< MAX_PATH
)
136 RootPathNameW
[i
] = *lpRootPathName
;
140 RootPathNameW
[i
] = 0;
141 return GetDiskFreeSpaceW(RootPathNameW
,lpSectorsPerCluster
, lpBytesPerSector
, lpNumberOfFreeClusters
, lpTotalNumberOfClusters
);
147 LPCWSTR lpRootPathName
,
148 LPDWORD lpSectorsPerCluster
,
149 LPDWORD lpBytesPerSector
,
150 LPDWORD lpNumberOfFreeClusters
,
151 LPDWORD lpTotalNumberOfClusters
154 FILE_FS_SIZE_INFORMATION FileFsSize
;
155 IO_STATUS_BLOCK IoStatusBlock
;
159 hFile
= CreateFileW(lpRootPathName
,
160 FILE_READ_ATTRIBUTES
,
164 FILE_ATTRIBUTE_NORMAL
,
167 errCode
= NtQueryVolumeInformationFile(hFile
,
170 sizeof(FILE_FS_SIZE_INFORMATION
),
171 FileFsSizeInformation
);
172 if (!NT_SUCCESS(errCode
))
175 SetLastError(RtlNtStatusToDosError(errCode
));
179 *lpBytesPerSector
= FileFsSize
.BytesPerSector
;
180 *lpSectorsPerCluster
= FileFsSize
.SectorsPerAllocationUnit
;
181 *lpNumberOfFreeClusters
= FileFsSize
.AvailableAllocationUnits
.LowPart
;
182 *lpTotalNumberOfClusters
= FileFsSize
.TotalAllocationUnits
.LowPart
;
190 LPCSTR lpDirectoryName
,
191 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
192 PULARGE_INTEGER lpTotalNumberOfBytes
,
193 PULARGE_INTEGER lpTotalNumberOfFreeBytes
196 WCHAR DirectoryNameW
[MAX_PATH
];
200 while ((*lpDirectoryName
)!=0 && i
< MAX_PATH
)
202 DirectoryNameW
[i
] = *lpDirectoryName
;
206 DirectoryNameW
[i
] = 0;
207 return GetDiskFreeSpaceExW(DirectoryNameW
,
208 lpFreeBytesAvailableToCaller
,
209 lpTotalNumberOfBytes
,
210 lpTotalNumberOfFreeBytes
);
217 LPCWSTR lpDirectoryName
,
218 PULARGE_INTEGER lpFreeBytesAvailableToCaller
,
219 PULARGE_INTEGER lpTotalNumberOfBytes
,
220 PULARGE_INTEGER lpTotalNumberOfFreeBytes
223 FILE_FS_SIZE_INFORMATION FileFsSize
;
224 IO_STATUS_BLOCK IoStatusBlock
;
228 ULARGE_INTEGER BytesPerCluster
;
230 wcsncpy (RootPath
, lpDirectoryName
, 3);
232 hFile
= CreateFileW(RootPath
,
233 FILE_READ_ATTRIBUTES
,
237 FILE_ATTRIBUTE_NORMAL
,
240 errCode
= NtQueryVolumeInformationFile(hFile
,
243 sizeof(FILE_FS_SIZE_INFORMATION
),
244 FileFsSizeInformation
);
245 if (!NT_SUCCESS(errCode
))
248 SetLastError(RtlNtStatusToDosError(errCode
));
252 BytesPerCluster
.QuadPart
=
253 FileFsSize
.BytesPerSector
* FileFsSize
.SectorsPerAllocationUnit
;
255 // FIXME: Use quota information
256 lpFreeBytesAvailableToCaller
->QuadPart
=
257 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
259 lpTotalNumberOfBytes
->QuadPart
=
260 BytesPerCluster
.QuadPart
* FileFsSize
.TotalAllocationUnits
.LowPart
;
261 lpTotalNumberOfFreeBytes
->QuadPart
=
262 BytesPerCluster
.QuadPart
* FileFsSize
.AvailableAllocationUnits
.QuadPart
;
272 LPCSTR lpRootPathName
276 WCHAR RootPathNameW
[MAX_PATH
];
278 while ((*lpRootPathName
)!=0 && i
< MAX_PATH
)
280 RootPathNameW
[i
] = *lpRootPathName
;
284 RootPathNameW
[i
] = 0;
285 return GetDriveTypeW(RootPathNameW
);
291 LPCWSTR lpRootPathName
294 FILE_FS_DEVICE_INFORMATION FileFsDevice
;
295 IO_STATUS_BLOCK IoStatusBlock
;
303 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
306 FILE_ATTRIBUTE_NORMAL
,
310 errCode
= NtQueryVolumeInformationFile(hFile
,&IoStatusBlock
,&FileFsDevice
, sizeof(FILE_FS_DEVICE_INFORMATION
),FileFsDeviceInformation
);
311 if ( !NT_SUCCESS(errCode
) ) {
313 SetLastError(RtlNtStatusToDosError(errCode
));
317 return (UINT
)FileFsDevice
.DeviceType
;
325 GetVolumeInformationA(
326 LPCSTR lpRootPathName
,
327 LPSTR lpVolumeNameBuffer
,
328 DWORD nVolumeNameSize
,
329 LPDWORD lpVolumeSerialNumber
,
330 LPDWORD lpMaximumComponentLength
,
331 LPDWORD lpFileSystemFlags
,
332 LPSTR lpFileSystemNameBuffer
,
333 DWORD nFileSystemNameSize
337 WCHAR RootPathNameW
[MAX_PATH
];
338 WCHAR VolumeNameBufferW
[MAX_PATH
];
339 WCHAR FileSystemNameBufferW
[MAX_PATH
];
343 while ((*lpRootPathName
)!=0 && i
< MAX_PATH
)
345 RootPathNameW
[i
] = *lpRootPathName
;
349 RootPathNameW
[i
] = 0;
351 if ( GetVolumeInformationW(RootPathNameW
,
354 lpVolumeSerialNumber
,
355 lpMaximumComponentLength
,
357 FileSystemNameBufferW
,
358 nFileSystemNameSize
) ) {
359 for(i
=0;i
<nVolumeNameSize
;i
++)
360 lpVolumeNameBuffer
[i
] = (CHAR
)VolumeNameBufferW
[i
];
362 for(i
=0;i
<nFileSystemNameSize
;i
++)
363 lpFileSystemNameBuffer
[i
] = (CHAR
)FileSystemNameBufferW
[i
];
374 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
376 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
381 GetVolumeInformationW(
382 LPCWSTR lpRootPathName
,
383 LPWSTR lpVolumeNameBuffer
,
384 DWORD nVolumeNameSize
,
385 LPDWORD lpVolumeSerialNumber
,
386 LPDWORD lpMaximumComponentLength
,
387 LPDWORD lpFileSystemFlags
,
388 LPWSTR lpFileSystemNameBuffer
,
389 DWORD nFileSystemNameSize
392 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
393 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
394 IO_STATUS_BLOCK IoStatusBlock
;
395 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
396 USHORT Buffer2
[FS_ATTRIBUTE_BUFFER_SIZE
];
401 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
402 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer2
;
404 DPRINT("FileFsVolume %p\n", FileFsVolume
);
405 DPRINT("FileFsAttribute %p\n", FileFsAttribute
);
407 hFile
= CreateFileW(lpRootPathName
,
408 FILE_READ_ATTRIBUTES
,
409 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
412 FILE_ATTRIBUTE_NORMAL
,
415 DPRINT("hFile: %x\n", hFile
);
416 errCode
= NtQueryVolumeInformationFile(hFile
,
419 FS_VOLUME_BUFFER_SIZE
,
420 FileFsVolumeInformation
);
421 if ( !NT_SUCCESS(errCode
) ) {
422 DPRINT("Status: %x\n", errCode
);
424 SetLastError(RtlNtStatusToDosError(errCode
));
428 if (lpVolumeSerialNumber
)
429 *lpVolumeSerialNumber
= FileFsVolume
->VolumeSerialNumber
;
431 if (lpVolumeNameBuffer
)
432 wcsncpy(lpVolumeNameBuffer
, FileFsVolume
->VolumeLabel
,min(nVolumeNameSize
,MAX_PATH
));
434 errCode
= NtQueryVolumeInformationFile(hFile
,&IoStatusBlock
,FileFsAttribute
, FS_ATTRIBUTE_BUFFER_SIZE
,FileFsAttributeInformation
);
435 if ( !NT_SUCCESS(errCode
) ) {
436 DPRINT("Status: %x\n", errCode
);
438 SetLastError(RtlNtStatusToDosError(errCode
));
442 if (lpFileSystemFlags
)
443 *lpFileSystemFlags
= FileFsAttribute
->FileSystemAttributes
;
444 if (lpMaximumComponentLength
)
445 *lpMaximumComponentLength
= FileFsAttribute
->MaximumComponentNameLength
;
446 if (lpFileSystemNameBuffer
)
447 wcsncpy(lpFileSystemNameBuffer
, FileFsAttribute
->FileSystemName
,min(nFileSystemNameSize
,MAX_PATH
));
456 LPCSTR lpRootPathName
,
460 WCHAR RootPathNameW
[MAX_PATH
];
461 WCHAR VolumeNameW
[MAX_PATH
];
465 while ((*lpRootPathName
)!=0 && i
< MAX_PATH
)
467 RootPathNameW
[i
] = *lpRootPathName
;
471 RootPathNameW
[i
] = 0;
474 while ((*lpVolumeName
)!=0 && i
< MAX_PATH
)
476 VolumeNameW
[i
] = *lpVolumeName
;
481 return SetVolumeLabelW(RootPathNameW
,VolumeNameW
);
487 LPCWSTR lpRootPathName
,