reactos/reactos/lib/kernel32/file/volume.c
David Welch 126768af64 Lots of changes to the kernel
svn path=/trunk/; revision=527
1999-05-29 00:15:17 +00:00

523 lines
13 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/file/volume.c
* PURPOSE: File volume functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
* Erik Bos, Alexandre Julliard :
* DRIVE_IsValid, GetLogicalDriveStringsA,
* GetLogicalDriveStringsW, GetLogicalDrives
* UPDATE HISTORY:
* Created 01/11/98
*/
//WINE copyright notice:
/*
* DOS drives handling functions
*
* Copyright 1993 Erik Bos
* Copyright 1996 Alexandre Julliard
*/
#include <windows.h>
#include <ddk/ntddk.h>
#include <wchar.h>
#include <string.h>
#define NDEBUG
#include <kernel32/kernel32.h>
#define MAX_DOS_DRIVES 26
int DRIVE_IsValid( int drive )
{
char Drives[4];
Drives[0] = 'A';
Drives[1] = ':';
Drives[2] = '\\';
Drives[3] = 0;
Drives[0] = 'A' + drive -1;
if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0;
if ( CreateFileA(Drives,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_ATTRIBUTE_DIRECTORY,NULL) == INVALID_HANDLE_VALUE ) {
return 0;
}
return drive;
}
DWORD
STDCALL
GetLogicalDriveStringsA(
DWORD nBufferLength,
LPSTR lpBuffer
)
{
int drive, count;
for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
if (DRIVE_IsValid(drive)) count++;
if (count * 4 * sizeof(char) <= nBufferLength)
{
LPSTR p = lpBuffer;
for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
if (DRIVE_IsValid(drive))
{
*p++ = 'A' + drive;
*p++ = ':';
*p++ = '\\';
*p++ = '\0';
}
*p = '\0';
}
return count * 4 * sizeof(char);
}
DWORD
STDCALL
GetLogicalDriveStringsW(
DWORD nBufferLength,
LPWSTR lpBuffer
)
{
int drive, count;
for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
if (DRIVE_IsValid(drive)) count++;
if (count * 4 * sizeof(WCHAR) <= nBufferLength)
{
LPWSTR p = lpBuffer;
for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
if (DRIVE_IsValid(drive))
{
*p++ = (WCHAR)('A' + drive);
*p++ = (WCHAR)':';
*p++ = (WCHAR)'\\';
*p++ = (WCHAR)'\0';
}
*p = (WCHAR)'\0';
}
return count * 4 * sizeof(WCHAR);
}
DWORD
STDCALL
GetLogicalDrives(VOID)
{
DWORD ret = 0;
int drive;
for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
if (DRIVE_IsValid(drive)) ret |= (1 << drive);
return ret;
}
WINBOOL
STDCALL
GetDiskFreeSpaceA(
LPCSTR lpRootPathName,
LPDWORD lpSectorsPerCluster,
LPDWORD lpBytesPerSector,
LPDWORD lpNumberOfFreeClusters,
LPDWORD lpTotalNumberOfClusters
)
{
WCHAR RootPathNameW[MAX_PATH];
if (lpRootPathName)
{
ULONG i = 0;
while ((*lpRootPathName)!=0 && i < MAX_PATH)
{
RootPathNameW[i] = *lpRootPathName;
lpRootPathName++;
i++;
}
RootPathNameW[i] = 0;
}
return GetDiskFreeSpaceW(lpRootPathName?RootPathNameW:NULL,
lpSectorsPerCluster,
lpBytesPerSector,
lpNumberOfFreeClusters,
lpTotalNumberOfClusters);
}
WINBOOL
STDCALL
GetDiskFreeSpaceW(
LPCWSTR lpRootPathName,
LPDWORD lpSectorsPerCluster,
LPDWORD lpBytesPerSector,
LPDWORD lpNumberOfFreeClusters,
LPDWORD lpTotalNumberOfClusters
)
{
FILE_FS_SIZE_INFORMATION FileFsSize;
IO_STATUS_BLOCK IoStatusBlock;
WCHAR RootPathName[MAX_PATH];
HANDLE hFile;
NTSTATUS errCode;
if (lpRootPathName)
{
wcsncpy (RootPathName, lpRootPathName, 3);
}
else
{
GetCurrentDirectoryW (MAX_PATH, RootPathName);
RootPathName[3] = 0;
}
hFile = CreateFileW(RootPathName,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
errCode = NtQueryVolumeInformationFile(hFile,
&IoStatusBlock,
&FileFsSize,
sizeof(FILE_FS_SIZE_INFORMATION),
FileFsSizeInformation);
if (!NT_SUCCESS(errCode))
{
CloseHandle(hFile);
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
*lpBytesPerSector = FileFsSize.BytesPerSector;
*lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
*lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
*lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
CloseHandle(hFile);
return TRUE;
}
WINBOOL
STDCALL
GetDiskFreeSpaceExA(
LPCSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
)
{
WCHAR DirectoryNameW[MAX_PATH];
if (lpDirectoryName)
{
ULONG i = 0;
while ((*lpDirectoryName)!=0 && i < MAX_PATH)
{
DirectoryNameW[i] = *lpDirectoryName;
lpDirectoryName++;
i++;
}
DirectoryNameW[i] = 0;
}
return GetDiskFreeSpaceExW(lpDirectoryName?DirectoryNameW:NULL,
lpFreeBytesAvailableToCaller,
lpTotalNumberOfBytes,
lpTotalNumberOfFreeBytes);
}
WINBOOL
STDCALL
GetDiskFreeSpaceExW(
LPCWSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
)
{
FILE_FS_SIZE_INFORMATION FileFsSize;
IO_STATUS_BLOCK IoStatusBlock;
ULARGE_INTEGER BytesPerCluster;
WCHAR RootPathName[MAX_PATH];
HANDLE hFile;
NTSTATUS errCode;
if (lpDirectoryName)
{
wcsncpy (RootPathName, lpDirectoryName, 3);
}
else
{
GetCurrentDirectoryW (MAX_PATH, RootPathName);
RootPathName[3] = 0;
}
hFile = CreateFileW(RootPathName,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
errCode = NtQueryVolumeInformationFile(hFile,
&IoStatusBlock,
&FileFsSize,
sizeof(FILE_FS_SIZE_INFORMATION),
FileFsSizeInformation);
if (!NT_SUCCESS(errCode))
{
CloseHandle(hFile);
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
BytesPerCluster.QuadPart =
FileFsSize.BytesPerSector * FileFsSize.SectorsPerAllocationUnit;
// FIXME: Use quota information
lpFreeBytesAvailableToCaller->QuadPart =
BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
lpTotalNumberOfBytes->QuadPart =
BytesPerCluster.QuadPart * FileFsSize.TotalAllocationUnits.QuadPart;
lpTotalNumberOfFreeBytes->QuadPart =
BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
CloseHandle(hFile);
return TRUE;
}
UINT
STDCALL
GetDriveTypeA(
LPCSTR lpRootPathName
)
{
ULONG i;
WCHAR RootPathNameW[MAX_PATH];
i = 0;
while ((*lpRootPathName)!=0 && i < MAX_PATH)
{
RootPathNameW[i] = *lpRootPathName;
lpRootPathName++;
i++;
}
RootPathNameW[i] = 0;
return GetDriveTypeW(RootPathNameW);
}
UINT
STDCALL
GetDriveTypeW(
LPCWSTR lpRootPathName
)
{
FILE_FS_DEVICE_INFORMATION FileFsDevice;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE hFile;
NTSTATUS errCode;
hFile = CreateFileW(
lpRootPathName,
GENERIC_ALL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
errCode = NtQueryVolumeInformationFile(hFile,&IoStatusBlock,&FileFsDevice, sizeof(FILE_FS_DEVICE_INFORMATION),FileFsDeviceInformation);
if ( !NT_SUCCESS(errCode) ) {
CloseHandle(hFile);
SetLastError(RtlNtStatusToDosError(errCode));
return 0;
}
CloseHandle(hFile);
return (UINT)FileFsDevice.DeviceType;
}
WINBOOL
STDCALL
GetVolumeInformationA(
LPCSTR lpRootPathName,
LPSTR lpVolumeNameBuffer,
DWORD nVolumeNameSize,
LPDWORD lpVolumeSerialNumber,
LPDWORD lpMaximumComponentLength,
LPDWORD lpFileSystemFlags,
LPSTR lpFileSystemNameBuffer,
DWORD nFileSystemNameSize
)
{
ULONG i;
WCHAR RootPathNameW[MAX_PATH];
WCHAR VolumeNameBufferW[MAX_PATH];
WCHAR FileSystemNameBufferW[MAX_PATH];
i = 0;
while ((*lpRootPathName)!=0 && i < MAX_PATH)
{
RootPathNameW[i] = *lpRootPathName;
lpRootPathName++;
i++;
}
RootPathNameW[i] = 0;
if ( GetVolumeInformationW(RootPathNameW,
VolumeNameBufferW,
nVolumeNameSize,
lpVolumeSerialNumber,
lpMaximumComponentLength,
lpFileSystemFlags,
FileSystemNameBufferW,
nFileSystemNameSize ) ) {
for(i=0;i<nVolumeNameSize;i++)
lpVolumeNameBuffer[i] = (CHAR)VolumeNameBufferW[i];
for(i=0;i<nFileSystemNameSize;i++)
lpFileSystemNameBuffer[i] = (CHAR)FileSystemNameBufferW[i];
return TRUE;
}
return FALSE;
}
#define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
#define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
WINBOOL
STDCALL
GetVolumeInformationW(
LPCWSTR lpRootPathName,
LPWSTR lpVolumeNameBuffer,
DWORD nVolumeNameSize,
LPDWORD lpVolumeSerialNumber,
LPDWORD lpMaximumComponentLength,
LPDWORD lpFileSystemFlags,
LPWSTR lpFileSystemNameBuffer,
DWORD nFileSystemNameSize
)
{
PFILE_FS_VOLUME_INFORMATION FileFsVolume;
PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
IO_STATUS_BLOCK IoStatusBlock;
USHORT Buffer[FS_VOLUME_BUFFER_SIZE];
USHORT Buffer2[FS_ATTRIBUTE_BUFFER_SIZE];
HANDLE hFile;
NTSTATUS errCode;
FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer2;
DPRINT("FileFsVolume %p\n", FileFsVolume);
DPRINT("FileFsAttribute %p\n", FileFsAttribute);
hFile = CreateFileW(lpRootPathName,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
DPRINT("hFile: %x\n", hFile);
errCode = NtQueryVolumeInformationFile(hFile,
&IoStatusBlock,
FileFsVolume,
FS_VOLUME_BUFFER_SIZE,
FileFsVolumeInformation);
if ( !NT_SUCCESS(errCode) ) {
DPRINT("Status: %x\n", errCode);
CloseHandle(hFile);
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
if (lpVolumeSerialNumber)
*lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
if (lpVolumeNameBuffer)
wcsncpy(lpVolumeNameBuffer, FileFsVolume->VolumeLabel,min(nVolumeNameSize,MAX_PATH));
errCode = NtQueryVolumeInformationFile(hFile,&IoStatusBlock,FileFsAttribute, FS_ATTRIBUTE_BUFFER_SIZE,FileFsAttributeInformation);
if ( !NT_SUCCESS(errCode) ) {
DPRINT("Status: %x\n", errCode);
CloseHandle(hFile);
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
if (lpFileSystemFlags)
*lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
if (lpMaximumComponentLength)
*lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
if (lpFileSystemNameBuffer)
wcsncpy(lpFileSystemNameBuffer, FileFsAttribute->FileSystemName,min(nFileSystemNameSize,MAX_PATH));
CloseHandle(hFile);
return TRUE;
}
WINBOOL
STDCALL
SetVolumeLabelA(
LPCSTR lpRootPathName,
LPCSTR lpVolumeName
)
{
WCHAR RootPathNameW[MAX_PATH];
WCHAR VolumeNameW[MAX_PATH];
UINT i;
i = 0;
while ((*lpRootPathName)!=0 && i < MAX_PATH)
{
RootPathNameW[i] = *lpRootPathName;
lpRootPathName++;
i++;
}
RootPathNameW[i] = 0;
i = 0;
while ((*lpVolumeName)!=0 && i < MAX_PATH)
{
VolumeNameW[i] = *lpVolumeName;
lpVolumeName++;
i++;
}
VolumeNameW[i] = 0;
return SetVolumeLabelW(RootPathNameW,VolumeNameW);
}
WINBOOL
STDCALL
SetVolumeLabelW(
LPCWSTR lpRootPathName,
LPCWSTR lpVolumeName
)
{
return FALSE;
}