mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 23:12:56 +00:00
805 lines
19 KiB
C
805 lines
19 KiB
C
/* $Id: volume.c,v 1.31 2003/07/20 18:05:46 royce Exp $
|
|
*
|
|
* 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 <kernel32/kernel32.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((LPWSTR)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);
|
|
|
|
RtlFreeUnicodeString(&NtPathU);
|
|
|
|
if (!NT_SUCCESS(errCode))
|
|
{
|
|
SetLastErrorByStatus (errCode);
|
|
return INVALID_HANDLE_VALUE;
|
|
}
|
|
return hFile;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD STDCALL
|
|
GetLogicalDriveStringsA(DWORD nBufferLength,
|
|
LPSTR lpBuffer)
|
|
{
|
|
DWORD drive, count;
|
|
DWORD dwDriveMap;
|
|
|
|
dwDriveMap = SharedUserData->DosDeviceMap;
|
|
|
|
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
|
|
*/
|
|
DWORD STDCALL
|
|
GetLogicalDriveStringsW(DWORD nBufferLength,
|
|
LPWSTR lpBuffer)
|
|
{
|
|
DWORD drive, count;
|
|
DWORD dwDriveMap;
|
|
|
|
dwDriveMap = SharedUserData->DosDeviceMap;
|
|
|
|
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
|
|
*/
|
|
DWORD STDCALL
|
|
GetLogicalDrives(VOID)
|
|
{
|
|
return(SharedUserData->DosDeviceMap);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
GetDiskFreeSpaceA (
|
|
LPCSTR lpRootPathName,
|
|
LPDWORD lpSectorsPerCluster,
|
|
LPDWORD lpBytesPerSector,
|
|
LPDWORD lpNumberOfFreeClusters,
|
|
LPDWORD lpTotalNumberOfClusters
|
|
)
|
|
{
|
|
UNICODE_STRING RootPathNameU;
|
|
ANSI_STRING RootPathName;
|
|
WINBOOL Result;
|
|
|
|
RtlInitAnsiString (&RootPathName,
|
|
(LPSTR)lpRootPathName);
|
|
|
|
RtlInitUnicodeString (&RootPathNameU,
|
|
NULL);
|
|
|
|
if (lpRootPathName)
|
|
{
|
|
/* convert ansi (or oem) string to unicode */
|
|
if (bIsFileApiAnsi)
|
|
RtlAnsiStringToUnicodeString (&RootPathNameU,
|
|
&RootPathName,
|
|
TRUE);
|
|
else
|
|
RtlOemStringToUnicodeString (&RootPathNameU,
|
|
&RootPathName,
|
|
TRUE);
|
|
}
|
|
|
|
Result = GetDiskFreeSpaceW (RootPathNameU.Buffer,
|
|
lpSectorsPerCluster,
|
|
lpBytesPerSector,
|
|
lpNumberOfFreeClusters,
|
|
lpTotalNumberOfClusters);
|
|
|
|
if (lpRootPathName)
|
|
{
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
RootPathNameU.Buffer);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
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 = InternalOpenDirW(lpRootPathName, 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;
|
|
}
|
|
|
|
*lpBytesPerSector = FileFsSize.BytesPerSector;
|
|
*lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
|
|
*lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
|
|
*lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
|
|
CloseHandle(hFile);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
GetDiskFreeSpaceExA (
|
|
LPCSTR lpDirectoryName,
|
|
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
|
|
PULARGE_INTEGER lpTotalNumberOfBytes,
|
|
PULARGE_INTEGER lpTotalNumberOfFreeBytes
|
|
)
|
|
{
|
|
UNICODE_STRING DirectoryNameU;
|
|
ANSI_STRING DirectoryName;
|
|
WINBOOL Result;
|
|
|
|
RtlInitAnsiString (&DirectoryName,
|
|
(LPSTR)lpDirectoryName);
|
|
|
|
RtlInitUnicodeString (&DirectoryNameU,
|
|
NULL);
|
|
|
|
if (lpDirectoryName)
|
|
{
|
|
/* convert ansi (or oem) string to unicode */
|
|
if (bIsFileApiAnsi)
|
|
RtlAnsiStringToUnicodeString (&DirectoryNameU,
|
|
&DirectoryName,
|
|
TRUE);
|
|
else
|
|
RtlOemStringToUnicodeString (&DirectoryNameU,
|
|
&DirectoryName,
|
|
TRUE);
|
|
}
|
|
|
|
Result = GetDiskFreeSpaceExW (DirectoryNameU.Buffer,
|
|
lpFreeBytesAvailableToCaller,
|
|
lpTotalNumberOfBytes,
|
|
lpTotalNumberOfFreeBytes);
|
|
|
|
if (lpDirectoryName)
|
|
{
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
DirectoryNameU.Buffer);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
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 = InternalOpenDirW(lpDirectoryName, 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)
|
|
{
|
|
UNICODE_STRING RootPathNameU;
|
|
ANSI_STRING RootPathName;
|
|
UINT Result;
|
|
|
|
RtlInitAnsiString (&RootPathName,
|
|
(LPSTR)lpRootPathName);
|
|
|
|
/* convert ansi (or oem) string to unicode */
|
|
if (bIsFileApiAnsi)
|
|
RtlAnsiStringToUnicodeString (&RootPathNameU,
|
|
&RootPathName,
|
|
TRUE);
|
|
else
|
|
RtlOemStringToUnicodeString (&RootPathNameU,
|
|
&RootPathName,
|
|
TRUE);
|
|
|
|
Result = GetDriveTypeW (RootPathNameU.Buffer);
|
|
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
RootPathNameU.Buffer);
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
/*
|
|
* @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 0;
|
|
}
|
|
|
|
errCode = NtQueryVolumeInformationFile (hFile,
|
|
&IoStatusBlock,
|
|
&FileFsDevice,
|
|
sizeof(FILE_FS_DEVICE_INFORMATION),
|
|
FileFsDeviceInformation);
|
|
if (!NT_SUCCESS(errCode))
|
|
{
|
|
CloseHandle(hFile);
|
|
SetLastErrorByStatus (errCode);
|
|
return 0;
|
|
}
|
|
CloseHandle(hFile);
|
|
return (UINT)FileFsDevice.DeviceType;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
GetVolumeInformationA(
|
|
LPCSTR lpRootPathName,
|
|
LPSTR lpVolumeNameBuffer,
|
|
DWORD nVolumeNameSize,
|
|
LPDWORD lpVolumeSerialNumber,
|
|
LPDWORD lpMaximumComponentLength,
|
|
LPDWORD lpFileSystemFlags,
|
|
LPSTR lpFileSystemNameBuffer,
|
|
DWORD nFileSystemNameSize
|
|
)
|
|
{
|
|
UNICODE_STRING RootPathNameU;
|
|
UNICODE_STRING FileSystemNameU;
|
|
UNICODE_STRING VolumeNameU;
|
|
ANSI_STRING RootPathName;
|
|
ANSI_STRING VolumeName;
|
|
ANSI_STRING FileSystemName;
|
|
WINBOOL Result;
|
|
|
|
RtlInitAnsiString (&RootPathName,
|
|
(LPSTR)lpRootPathName);
|
|
|
|
/* convert ansi (or oem) string to unicode */
|
|
if (bIsFileApiAnsi)
|
|
RtlAnsiStringToUnicodeString (&RootPathNameU,
|
|
&RootPathName,
|
|
TRUE);
|
|
else
|
|
RtlOemStringToUnicodeString (&RootPathNameU,
|
|
&RootPathName,
|
|
TRUE);
|
|
|
|
if (lpVolumeNameBuffer)
|
|
{
|
|
VolumeNameU.Length = 0;
|
|
VolumeNameU.MaximumLength = nVolumeNameSize * sizeof(WCHAR);
|
|
VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
|
|
0,
|
|
VolumeNameU.MaximumLength);
|
|
}
|
|
|
|
if (lpFileSystemNameBuffer)
|
|
{
|
|
FileSystemNameU.Length = 0;
|
|
FileSystemNameU.MaximumLength = nFileSystemNameSize * sizeof(WCHAR);
|
|
FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
|
|
0,
|
|
FileSystemNameU.MaximumLength);
|
|
}
|
|
|
|
Result = GetVolumeInformationW (RootPathNameU.Buffer,
|
|
lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL,
|
|
nVolumeNameSize,
|
|
lpVolumeSerialNumber,
|
|
lpMaximumComponentLength,
|
|
lpFileSystemFlags,
|
|
lpFileSystemNameBuffer ? FileSystemNameU.Buffer : NULL,
|
|
nFileSystemNameSize);
|
|
|
|
if (Result)
|
|
{
|
|
if (lpVolumeNameBuffer)
|
|
{
|
|
VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR);
|
|
VolumeName.Length = 0;
|
|
VolumeName.MaximumLength = nVolumeNameSize;
|
|
VolumeName.Buffer = lpVolumeNameBuffer;
|
|
}
|
|
|
|
if (lpFileSystemNameBuffer)
|
|
{
|
|
FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR);
|
|
FileSystemName.Length = 0;
|
|
FileSystemName.MaximumLength = nFileSystemNameSize;
|
|
FileSystemName.Buffer = lpFileSystemNameBuffer;
|
|
}
|
|
|
|
/* convert unicode strings to ansi (or oem) */
|
|
if (bIsFileApiAnsi)
|
|
{
|
|
if (lpVolumeNameBuffer)
|
|
{
|
|
RtlUnicodeStringToAnsiString (&VolumeName,
|
|
&VolumeNameU,
|
|
FALSE);
|
|
}
|
|
if (lpFileSystemNameBuffer)
|
|
{
|
|
RtlUnicodeStringToAnsiString (&FileSystemName,
|
|
&FileSystemNameU,
|
|
FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (lpVolumeNameBuffer)
|
|
{
|
|
RtlUnicodeStringToOemString (&VolumeName,
|
|
&VolumeNameU,
|
|
FALSE);
|
|
}
|
|
if (lpFileSystemNameBuffer)
|
|
{
|
|
RtlUnicodeStringToOemString (&FileSystemName,
|
|
&FileSystemNameU,
|
|
FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
RootPathNameU.Buffer);
|
|
if (lpVolumeNameBuffer)
|
|
{
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
VolumeNameU.Buffer);
|
|
}
|
|
if (lpFileSystemNameBuffer)
|
|
{
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
FileSystemNameU.Buffer);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
#define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION))
|
|
|
|
#define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
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;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UCHAR Buffer[max(FS_VOLUME_BUFFER_SIZE, FS_ATTRIBUTE_BUFFER_SIZE)];
|
|
|
|
HANDLE hFile;
|
|
NTSTATUS errCode;
|
|
|
|
FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
|
|
FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
|
|
|
|
DPRINT("FileFsVolume %p\n", FileFsVolume);
|
|
DPRINT("FileFsAttribute %p\n", FileFsAttribute);
|
|
|
|
hFile = InternalOpenDirW(lpRootPathName, FALSE);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
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);
|
|
SetLastErrorByStatus (errCode);
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpVolumeSerialNumber)
|
|
*lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
|
|
|
|
if (lpVolumeNameBuffer)
|
|
{
|
|
if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR))
|
|
{
|
|
memcpy(lpVolumeNameBuffer,
|
|
FileFsVolume->VolumeLabel,
|
|
FileFsVolume->VolumeLabelLength);
|
|
lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0;
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(hFile);
|
|
SetLastError(ERROR_MORE_DATA);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
errCode = NtQueryVolumeInformationFile (hFile,
|
|
&IoStatusBlock,
|
|
FileFsAttribute,
|
|
FS_ATTRIBUTE_BUFFER_SIZE,
|
|
FileFsAttributeInformation);
|
|
CloseHandle(hFile);
|
|
if (!NT_SUCCESS(errCode))
|
|
{
|
|
DPRINT("Status: %x\n", errCode);
|
|
SetLastErrorByStatus (errCode);
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpFileSystemFlags)
|
|
*lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
|
|
if (lpMaximumComponentLength)
|
|
*lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
|
|
if (lpFileSystemNameBuffer)
|
|
{
|
|
if (nFileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
|
|
{
|
|
memcpy(lpFileSystemNameBuffer,
|
|
FileFsAttribute->FileSystemName,
|
|
FileFsAttribute->FileSystemNameLength);
|
|
lpFileSystemNameBuffer[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0;
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_MORE_DATA);
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
SetVolumeLabelA (
|
|
LPCSTR lpRootPathName,
|
|
LPCSTR lpVolumeName
|
|
)
|
|
{
|
|
UNICODE_STRING RootPathNameU;
|
|
ANSI_STRING RootPathName;
|
|
UNICODE_STRING VolumeNameU;
|
|
ANSI_STRING VolumeName;
|
|
WINBOOL Result;
|
|
|
|
RtlInitAnsiString (&RootPathName,
|
|
(LPSTR)lpRootPathName);
|
|
RtlInitAnsiString (&VolumeName,
|
|
(LPSTR)lpVolumeName);
|
|
|
|
/* convert ansi (or oem) strings to unicode */
|
|
if (bIsFileApiAnsi)
|
|
{
|
|
RtlAnsiStringToUnicodeString (&RootPathNameU,
|
|
&RootPathName,
|
|
TRUE);
|
|
RtlAnsiStringToUnicodeString (&VolumeNameU,
|
|
&VolumeName,
|
|
TRUE);
|
|
}
|
|
else
|
|
{
|
|
RtlOemStringToUnicodeString (&RootPathNameU,
|
|
&RootPathName,
|
|
TRUE);
|
|
RtlOemStringToUnicodeString (&VolumeNameU,
|
|
&VolumeName,
|
|
TRUE);
|
|
}
|
|
|
|
Result = SetVolumeLabelW (RootPathNameU.Buffer,
|
|
VolumeNameU.Buffer);
|
|
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
RootPathNameU.Buffer);
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
VolumeNameU.Buffer);
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
SetVolumeLabelW(LPCWSTR lpRootPathName,
|
|
LPCWSTR lpVolumeName)
|
|
{
|
|
PFILE_FS_LABEL_INFORMATION LabelInfo;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
ULONG LabelLength;
|
|
HANDLE hFile;
|
|
NTSTATUS Status;
|
|
|
|
LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR);
|
|
LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
0,
|
|
sizeof(FILE_FS_LABEL_INFORMATION) +
|
|
LabelLength);
|
|
LabelInfo->VolumeLabelLength = LabelLength;
|
|
memcpy(LabelInfo->VolumeLabel,
|
|
lpVolumeName,
|
|
LabelLength);
|
|
|
|
hFile = InternalOpenDirW(lpRootPathName, TRUE);
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
0,
|
|
LabelInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
Status = NtSetVolumeInformationFile(hFile,
|
|
&IoStatusBlock,
|
|
LabelInfo,
|
|
sizeof(FILE_FS_LABEL_INFORMATION) +
|
|
LabelLength,
|
|
FileFsLabelInformation);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
0,
|
|
LabelInfo);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("Status: %x\n", Status);
|
|
CloseHandle(hFile);
|
|
SetLastErrorByStatus(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
return TRUE;
|
|
}
|
|
|
|
/* EOF */
|