📄 volume.c
字号:
/* $Id: volume.c 22509 2006-06-22 20:50:53Z hpoussin $
*
* 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 :
* 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 <k32.h>
#define NDEBUG
#include "../include/debug.h"
#define MAX_DOS_DRIVES 26
static HANDLE
InternalOpenDirW(LPCWSTR DirName,
BOOLEAN Write)
{
UNICODE_STRING NtPathU;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS errCode;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE hFile;
if (!RtlDosPathNameToNtPathName_U(DirName,
&NtPathU,
NULL,
NULL))
{
DPRINT("Invalid path\n");
SetLastError(ERROR_BAD_PATHNAME);
return INVALID_HANDLE_VALUE;
}
InitializeObjectAttributes(&ObjectAttributes,
&NtPathU,
Write ? FILE_WRITE_ATTRIBUTES : FILE_READ_ATTRIBUTES,
NULL,
NULL);
errCode = NtCreateFile (&hFile,
Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0);
RtlFreeHeap(RtlGetProcessHeap(),
0,
NtPathU.Buffer);
if (!NT_SUCCESS(errCode))
{
SetLastErrorByStatus (errCode);
return INVALID_HANDLE_VALUE;
}
return hFile;
}
/*
* @implemented
*/
/* Synced to Wine-? */
DWORD STDCALL
GetLogicalDriveStringsA(DWORD nBufferLength,
LPSTR lpBuffer)
{
DWORD drive, count;
DWORD dwDriveMap;
dwDriveMap = GetLogicalDrives();
for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
{
if (dwDriveMap & (1<<drive))
count++;
}
if (count * 4 * sizeof(char) <= nBufferLength)
{
LPSTR p = lpBuffer;
for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
if (dwDriveMap & (1<<drive))
{
*p++ = 'A' + drive;
*p++ = ':';
*p++ = '\\';
*p++ = '\0';
}
*p = '\0';
}
return (count * 4 * sizeof(char));
}
/*
* @implemented
*/
/* Synced to Wine-? */
DWORD STDCALL
GetLogicalDriveStringsW(DWORD nBufferLength,
LPWSTR lpBuffer)
{
DWORD drive, count;
DWORD dwDriveMap;
dwDriveMap = GetLogicalDrives();
for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
{
if (dwDriveMap & (1<<drive))
count++;
}
if (count * 4 * sizeof(WCHAR) <= nBufferLength)
{
LPWSTR p = lpBuffer;
for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
if (dwDriveMap & (1<<drive))
{
*p++ = (WCHAR)('A' + drive);
*p++ = (WCHAR)':';
*p++ = (WCHAR)'\\';
*p++ = (WCHAR)'\0';
}
*p = (WCHAR)'\0';
}
return (count * 4 * sizeof(WCHAR));
}
/*
* @implemented
*/
/* Synced to Wine-? */
DWORD STDCALL
GetLogicalDrives(VOID)
{
NTSTATUS Status;
PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo;
/* Get the Device Map for this Process */
Status = NtQueryInformationProcess(NtCurrentProcess(),
ProcessDeviceMap,
&ProcessDeviceMapInfo,
sizeof(ProcessDeviceMapInfo),
NULL);
/* Return the Drive Map */
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return 0;
}
return ProcessDeviceMapInfo.Query.DriveMap;
}
/*
* @implemented
*/
BOOL STDCALL
GetDiskFreeSpaceA (
LPCSTR lpRootPathName,
LPDWORD lpSectorsPerCluster,
LPDWORD lpBytesPerSector,
LPDWORD lpNumberOfFreeClusters,
LPDWORD lpTotalNumberOfClusters
)
{
PWCHAR RootPathNameW=NULL;
if (lpRootPathName)
{
if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
return FALSE;
}
return GetDiskFreeSpaceW (RootPathNameW,
lpSectorsPerCluster,
lpBytesPerSector,
lpNumberOfFreeClusters,
lpTotalNumberOfClusters);
}
/*
* @implemented
*/
BOOL 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 = InternalOpenDirW(RootPathName, FALSE);
if (INVALID_HANDLE_VALUE == hFile)
{
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
errCode = NtQueryVolumeInformationFile(hFile,
&IoStatusBlock,
&FileFsSize,
sizeof(FILE_FS_SIZE_INFORMATION),
FileFsSizeInformation);
if (!NT_SUCCESS(errCode))
{
CloseHandle(hFile);
SetLastErrorByStatus (errCode);
return FALSE;
}
if (lpSectorsPerCluster)
*lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
if (lpBytesPerSector)
*lpBytesPerSector = FileFsSize.BytesPerSector;
if (lpNumberOfFreeClusters)
*lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
if (lpTotalNumberOfClusters)
*lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
CloseHandle(hFile);
return TRUE;
}
/*
* @implemented
*/
BOOL STDCALL
GetDiskFreeSpaceExA (
LPCSTR lpDirectoryName OPTIONAL,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
)
{
PWCHAR DirectoryNameW=NULL;
if (lpDirectoryName)
{
if (!(DirectoryNameW = FilenameA2W(lpDirectoryName, FALSE)))
return FALSE;
}
return GetDiskFreeSpaceExW (DirectoryNameW ,
lpFreeBytesAvailableToCaller,
lpTotalNumberOfBytes,
lpTotalNumberOfFreeBytes);
}
/*
* @implemented
*/
BOOL STDCALL
GetDiskFreeSpaceExW(
LPCWSTR lpDirectoryName OPTIONAL,
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;
/*
FIXME: this is obviously wrong for UNC paths, symbolic directories etc.
-Gunnar
*/
if (lpDirectoryName)
{
wcsncpy (RootPathName, lpDirectoryName, 3);
}
else
{
GetCurrentDirectoryW (MAX_PATH, RootPathName);
}
RootPathName[3] = 0;
hFile = InternalOpenDirW(RootPathName, FALSE);
if (INVALID_HANDLE_VALUE == hFile)
{
return FALSE;
}
errCode = NtQueryVolumeInformationFile(hFile,
&IoStatusBlock,
&FileFsSize,
sizeof(FILE_FS_SIZE_INFORMATION),
FileFsSizeInformation);
if (!NT_SUCCESS(errCode))
{
CloseHandle(hFile);
SetLastErrorByStatus (errCode);
return FALSE;
}
BytesPerCluster.QuadPart =
FileFsSize.BytesPerSector * FileFsSize.SectorsPerAllocationUnit;
// FIXME: Use quota information
if (lpFreeBytesAvailableToCaller)
lpFreeBytesAvailableToCaller->QuadPart =
BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
if (lpTotalNumberOfBytes)
lpTotalNumberOfBytes->QuadPart =
BytesPerCluster.QuadPart * FileFsSize.TotalAllocationUnits.QuadPart;
if (lpTotalNumberOfFreeBytes)
lpTotalNumberOfFreeBytes->QuadPart =
BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
CloseHandle(hFile);
return TRUE;
}
/*
* @implemented
*/
UINT STDCALL
GetDriveTypeA(LPCSTR lpRootPathName)
{
PWCHAR RootPathNameW;
if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
return DRIVE_UNKNOWN;
return GetDriveTypeW(RootPathNameW);
}
/*
* @implemented
*/
UINT STDCALL
GetDriveTypeW(LPCWSTR lpRootPathName)
{
FILE_FS_DEVICE_INFORMATION FileFsDevice;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE hFile;
NTSTATUS errCode;
hFile = InternalOpenDirW(lpRootPathName, FALSE);
if (hFile == INVALID_HANDLE_VALUE)
{
return DRIVE_NO_ROOT_DIR; /* According to WINE regression tests */
}
errCode = NtQueryVolumeInformationFile (hFile,
&IoStatusBlock,
&FileFsDevice,
sizeof(FILE_FS_DEVICE_INFORMATION),
FileFsDeviceInformation);
if (!NT_SUCCESS(errCode))
{
CloseHandle(hFile);
SetLastErrorByStatus (errCode);
return 0;
}
CloseHandle(hFile);
switch (FileFsDevice.DeviceType)
{
case FILE_DEVICE_CD_ROM:
case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
return DRIVE_CDROM;
case FILE_DEVICE_VIRTUAL_DISK:
return DRIVE_RAMDISK;
case FILE_DEVICE_NETWORK_FILE_SYSTEM:
return DRIVE_REMOTE;
case FILE_DEVICE_DISK:
case FILE_DEVICE_DISK_FILE_SYSTEM:
if (FileFsDevice.Characteristics & FILE_REMOTE_DEVICE)
return DRIVE_REMOTE;
if (FileFsDevice.Characteristics & FILE_REMOVABLE_MEDIA)
return DRIVE_REMOVABLE;
return DRIVE_FIXED;
}
DPRINT1("Returning DRIVE_UNKNOWN for device type %d\n", FileFsDevice.DeviceType);
return DRIVE_UNKNOWN;
}
/*
* @implemented
*/
BOOL STDCALL
GetVolumeInformationA(
LPCSTR lpRootPathName,
LPSTR lpVolumeNameBuffer,
DWORD nVolumeNameSize,
LPDWORD lpVolumeSerialNumber,
LPDWORD lpMaximumComponentLength,
LPDWORD lpFileSystemFlags,
LPSTR lpFileSystemNameBuffer,
DWORD nFileSystemNameSize
)
{
UNICODE_STRING FileSystemNameU;
UNICODE_STRING VolumeNameU = {0};
ANSI_STRING VolumeName;
ANSI_STRING FileSystemName;
PWCHAR RootPathNameW;
BOOL Result;
if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
return FALSE;
if (lpVolumeNameBuffer)
{
VolumeNameU.MaximumLength = nVolumeNameSize * sizeof(WCHAR);
VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
0,
VolumeNameU.MaximumLength);
if (VolumeNameU.Buffer == NULL)
{
goto FailNoMem;
}
}
if (lpFileSystemNameBuffer)
{
FileSystemNameU.Length = 0;
FileSystemNameU.MaximumLength = nFileSystemNameSize * sizeof(WCHAR);
FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
0,
FileSystemNameU.MaximumLength);
if (FileSystemNameU.Buffer == NULL)
{
if (VolumeNameU.Buffer != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
VolumeNameU.Buffer);
}
FailNoMem:
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
}
Result = GetVolumeInformationW (RootPathNameW,
lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL,
nVolumeNameSize,
lpVolumeSerialNumber,
lpMaximumComponentLength,
lpFileSystemFlags,
lpFileSystemNameBuffer ? FileSystemNameU.Buffer : NULL,
nFileSystemNameSize);
if (Result)
{
if (lpVolumeNameBuffer)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -