-/* $Id: volume.c,v 1.24 2002/08/27 06:38:23 hbirr Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
*/
//WINE copyright notice:
/*
- * DOS drives handling functions
+ * DOS drives handling functions
*
* Copyright 1993 Erik Bos
* Copyright 1996 Alexandre Julliard
*/
-#include <ddk/ntddk.h>
-#include <windows.h>
-#include <ntos/minmax.h>
+#include <k32.h>
#define NDEBUG
-#include <kernel32/kernel32.h>
-#include <kernel32/error.h>
+#include "../include/debug.h"
#define MAX_DOS_DRIVES 26
-HANDLE InternalOpenDirW(PWCHAR 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))
+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 hFile;
}
+
+/*
+ * @implemented
+ */
DWORD STDCALL
GetLogicalDriveStringsA(DWORD nBufferLength,
LPSTR lpBuffer)
DWORD drive, count;
DWORD dwDriveMap;
- dwDriveMap = SharedUserData->DosDeviceMap;
+ dwDriveMap = GetLogicalDrives();
for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
{
}
+/*
+ * @implemented
+ */
DWORD STDCALL
GetLogicalDriveStringsW(DWORD nBufferLength,
LPWSTR lpBuffer)
DWORD drive, count;
DWORD dwDriveMap;
- dwDriveMap = SharedUserData->DosDeviceMap;
+ dwDriveMap = GetLogicalDrives();
for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
{
}
+/*
+ * @implemented
+ */
DWORD STDCALL
GetLogicalDrives(VOID)
{
- return(SharedUserData->DosDeviceMap);
+ 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;
}
-WINBOOL STDCALL
+/*
+ * @implemented
+ */
+BOOL STDCALL
GetDiskFreeSpaceA (
LPCSTR lpRootPathName,
LPDWORD lpSectorsPerCluster,
LPDWORD lpTotalNumberOfClusters
)
{
- UNICODE_STRING RootPathNameU;
- ANSI_STRING RootPathName;
- WINBOOL Result;
+ PWCHAR RootPathNameW=NULL;
- 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);
- }
+ if (lpRootPathName)
+ {
+ if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
+ return FALSE;
+ }
- Result = GetDiskFreeSpaceW (RootPathNameU.Buffer,
+ return GetDiskFreeSpaceW (RootPathNameW,
lpSectorsPerCluster,
lpBytesPerSector,
lpNumberOfFreeClusters,
lpTotalNumberOfClusters);
-
- if (lpRootPathName)
- {
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- RootPathNameU.Buffer);
- }
-
- return Result;
}
-WINBOOL STDCALL
+/*
+ * @implemented
+ */
+BOOL STDCALL
GetDiskFreeSpaceW(
LPCWSTR lpRootPathName,
LPDWORD lpSectorsPerCluster,
else
{
GetCurrentDirectoryW (MAX_PATH, RootPathName);
- RootPathName[3] = 0;
}
-
- if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW((PWCHAR)lpRootPathName, FALSE)))
+ RootPathName[3] = 0;
+
+ hFile = InternalOpenDirW(RootPathName, FALSE);
+ if (INVALID_HANDLE_VALUE == hFile)
{
- return FALSE;
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
}
-
errCode = NtQueryVolumeInformationFile(hFile,
&IoStatusBlock,
*lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
*lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
CloseHandle(hFile);
+
return TRUE;
}
-WINBOOL STDCALL
+/*
+ * @implemented
+ */
+BOOL STDCALL
GetDiskFreeSpaceExA (
- LPCSTR lpDirectoryName,
+ LPCSTR lpDirectoryName OPTIONAL,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
)
{
- UNICODE_STRING DirectoryNameU;
- ANSI_STRING DirectoryName;
- WINBOOL Result;
-
- RtlInitAnsiString (&DirectoryName,
- (LPSTR)lpDirectoryName);
-
- RtlInitUnicodeString (&DirectoryNameU,
- NULL);
+ PWCHAR DirectoryNameW=NULL;
if (lpDirectoryName)
{
- /* convert ansi (or oem) string to unicode */
- if (bIsFileApiAnsi)
- RtlAnsiStringToUnicodeString (&DirectoryNameU,
- &DirectoryName,
- TRUE);
- else
- RtlOemStringToUnicodeString (&DirectoryNameU,
- &DirectoryName,
- TRUE);
+ if (!(DirectoryNameW = FilenameA2W(lpDirectoryName, FALSE)))
+ return FALSE;
}
- Result = GetDiskFreeSpaceExW (DirectoryNameU.Buffer,
+ return GetDiskFreeSpaceExW (DirectoryNameW ,
lpFreeBytesAvailableToCaller,
lpTotalNumberOfBytes,
lpTotalNumberOfFreeBytes);
-
- if (lpDirectoryName)
- {
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- DirectoryNameU.Buffer);
- }
-
- return Result;
}
-WINBOOL STDCALL
+/*
+ * @implemented
+ */
+BOOL STDCALL
GetDiskFreeSpaceExW(
- LPCWSTR lpDirectoryName,
+ LPCWSTR lpDirectoryName OPTIONAL,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
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;
}
-
- if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW(lpDirectoryName, FALSE)))
+ RootPathName[3] = 0;
+
+ hFile = InternalOpenDirW(RootPathName, FALSE);
+ if (INVALID_HANDLE_VALUE == hFile)
{
return FALSE;
}
-
+
errCode = NtQueryVolumeInformationFile(hFile,
&IoStatusBlock,
&FileFsSize,
if (lpFreeBytesAvailableToCaller)
lpFreeBytesAvailableToCaller->QuadPart =
BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
-
+
if (lpTotalNumberOfBytes)
lpTotalNumberOfBytes->QuadPart =
BytesPerCluster.QuadPart * FileFsSize.TotalAllocationUnits.QuadPart;
BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart;
CloseHandle(hFile);
+
return TRUE;
}
+/*
+ * @implemented
+ */
UINT STDCALL
GetDriveTypeA(LPCSTR lpRootPathName)
{
- UNICODE_STRING RootPathNameU;
- ANSI_STRING RootPathName;
- UINT Result;
+ PWCHAR RootPathNameW;
- RtlInitAnsiString (&RootPathName,
- (LPSTR)lpRootPathName);
+ if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
+ return DRIVE_UNKNOWN;
- /* 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;
+ return GetDriveTypeW(RootPathNameW);
}
+
+/*
+ * @implemented
+ */
UINT STDCALL
GetDriveTypeW(LPCWSTR lpRootPathName)
{
hFile = InternalOpenDirW(lpRootPathName, FALSE);
if (hFile == INVALID_HANDLE_VALUE)
{
- return 0;
+ return DRIVE_NO_ROOT_DIR; /* According to WINE regression tests */
}
errCode = NtQueryVolumeInformationFile (hFile,
return 0;
}
CloseHandle(hFile);
- return (UINT)FileFsDevice.DeviceType;
+
+ 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;
}
-WINBOOL STDCALL
+/*
+ * @implemented
+ */
+BOOL STDCALL
GetVolumeInformationA(
LPCSTR lpRootPathName,
LPSTR lpVolumeNameBuffer,
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);
-
- VolumeNameU.Length = 0;
- VolumeNameU.MaximumLength = nVolumeNameSize * sizeof(WCHAR);
- VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
- 0,
- VolumeNameU.MaximumLength);
-
- FileSystemNameU.Length = 0;
- FileSystemNameU.MaximumLength = nFileSystemNameSize * sizeof(WCHAR);
- FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
- 0,
- FileSystemNameU.MaximumLength);
-
- Result = GetVolumeInformationW (RootPathNameU.Buffer,
- VolumeNameU.Buffer,
- nVolumeNameSize,
- lpVolumeSerialNumber,
- lpMaximumComponentLength,
- lpFileSystemFlags,
- FileSystemNameU.Buffer,
- nFileSystemNameSize);
-
- if (Result)
- {
- VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR);
- VolumeName.Length = 0;
- VolumeName.MaximumLength = nVolumeNameSize;
- VolumeName.Buffer = lpVolumeNameBuffer;
-
- 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)
- {
- RtlUnicodeStringToAnsiString (&VolumeName,
- &VolumeNameU,
- FALSE);
- RtlUnicodeStringToAnsiString (&FileSystemName,
- &FileSystemNameU,
- FALSE);
- }
- else
- {
- RtlUnicodeStringToOemString (&VolumeName,
- &VolumeNameU,
- FALSE);
- RtlUnicodeStringToOemString (&FileSystemName,
- &FileSystemNameU,
- FALSE);
- }
- }
+ UNICODE_STRING FileSystemNameU;
+ UNICODE_STRING VolumeNameU = {0};
+ ANSI_STRING VolumeName;
+ ANSI_STRING FileSystemName;
+ PWCHAR RootPathNameW;
+ BOOL Result;
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- RootPathNameU.Buffer);
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- VolumeNameU.Buffer);
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- FileSystemNameU.Buffer);
+ if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
+ return FALSE;
- return Result;
-}
+ 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)
+ {
+ 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);
+ }
+ }
+ }
+ if (lpVolumeNameBuffer)
+ {
+ RtlFreeHeap (RtlGetProcessHeap (),
+ 0,
+ VolumeNameU.Buffer);
+ }
+ if (lpFileSystemNameBuffer)
+ {
+ RtlFreeHeap (RtlGetProcessHeap (),
+ 0,
+ FileSystemNameU.Buffer);
+ }
-#define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
+ return Result;
+}
-#define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
+#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))
-WINBOOL STDCALL
+/*
+ * @implemented
+ */
+BOOL STDCALL
GetVolumeInformationW(
LPCWSTR lpRootPathName,
LPWSTR lpVolumeNameBuffer,
DWORD nFileSystemNameSize
)
{
- PFILE_FS_VOLUME_INFORMATION FileFsVolume;
- PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
- IO_STATUS_BLOCK IoStatusBlock;
- OBJECT_ATTRIBUTES ObjectAttributes;
- USHORT Buffer[FS_VOLUME_BUFFER_SIZE];
- USHORT Buffer2[FS_ATTRIBUTE_BUFFER_SIZE];
-
- HANDLE hFile;
- NTSTATUS errCode;
+ PFILE_FS_VOLUME_INFORMATION FileFsVolume;
+ PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
+ IO_STATUS_BLOCK IoStatusBlock;
+ WCHAR RootPathName[MAX_PATH];
+ 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);
+
+ if (!lpRootPathName || !wcscmp(lpRootPathName, L""))
+ {
+ GetCurrentDirectoryW (MAX_PATH, RootPathName);
+ }
+ else
+ {
+ wcsncpy (RootPathName, lpRootPathName, 3);
+ }
+ RootPathName[3] = 0;
+
+ hFile = InternalOpenDirW(RootPathName, FALSE);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return FALSE;
+ }
- FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
- FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer2;
+ 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;
+ }
- DPRINT("FileFsVolume %p\n", FileFsVolume);
- DPRINT("FileFsAttribute %p\n", FileFsAttribute);
+ if (lpVolumeSerialNumber)
+ *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
- hFile = InternalOpenDirW(lpRootPathName, FALSE);
- if (hFile == INVALID_HANDLE_VALUE)
- {
- return FALSE;
+ if (lpVolumeNameBuffer)
+ {
+ if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR))
+ {
+ memcpy(lpVolumeNameBuffer,
+ FileFsVolume->VolumeLabel,
+ FileFsVolume->VolumeLabelLength);
+ lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0;
}
-
- 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;
+ else
+ {
+ CloseHandle(hFile);
+ SetLastError(ERROR_MORE_DATA);
+ 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);
+ CloseHandle(hFile);
+ if (!NT_SUCCESS(errCode))
+ {
+ DPRINT("Status: %x\n", errCode);
+ SetLastErrorByStatus (errCode);
+ return FALSE;
+ }
- errCode = NtQueryVolumeInformationFile (hFile,
- &IoStatusBlock,
- FileFsAttribute,
- FS_ATTRIBUTE_BUFFER_SIZE,
- FileFsAttributeInformation);
- if (!NT_SUCCESS(errCode))
- {
- DPRINT("Status: %x\n", errCode);
- CloseHandle(hFile);
- 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;
}
-
- if (lpFileSystemFlags)
- *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
- if (lpMaximumComponentLength)
- *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
- if (lpFileSystemNameBuffer)
- wcsncpy(lpFileSystemNameBuffer, FileFsAttribute->FileSystemName,min(nFileSystemNameSize,MAX_PATH));
-
- CloseHandle(hFile);
- return TRUE;
+ else
+ {
+ SetLastError(ERROR_MORE_DATA);
+ return FALSE;
+ }
+ }
+ return TRUE;
}
-WINBOOL
+/*
+ * @implemented
+ */
+BOOL
STDCALL
SetVolumeLabelA (
LPCSTR lpRootPathName,
- LPCSTR lpVolumeName
+ LPCSTR lpVolumeName /* NULL if deleting label */
)
{
- 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);
- }
+ PWCHAR RootPathNameW;
+ PWCHAR VolumeNameW = NULL;
+ BOOL Result;
- Result = SetVolumeLabelW (RootPathNameU.Buffer,
- VolumeNameU.Buffer);
+ if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
+ return FALSE;
+
+ if (lpVolumeName)
+ {
+ if (!(VolumeNameW = FilenameA2W(lpVolumeName, TRUE)))
+ return FALSE;
+ }
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- RootPathNameU.Buffer);
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- VolumeNameU.Buffer);
+ Result = SetVolumeLabelW (RootPathNameW,
+ VolumeNameW);
+
+ if (VolumeNameW)
+ {
+ RtlFreeHeap (RtlGetProcessHeap (),
+ 0,
+ VolumeNameW );
+ }
return Result;
}
-WINBOOL STDCALL
-SetVolumeLabelW(LPCWSTR lpRootPathName,
- LPCWSTR lpVolumeName)
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetVolumeLabelW(
+ LPCWSTR lpRootPathName,
+ LPCWSTR lpVolumeName /* NULL if deleting label */
+ )
{
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);
+ if (LabelInfo == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
LabelInfo->VolumeLabelLength = LabelLength;
- wcscpy(LabelInfo->VolumeLabel,
- lpVolumeName);
-
- if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW(lpRootPathName, TRUE)))
+ 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,
return TRUE;
}
+/**
+ * @name GetVolumeNameForVolumeMountPointW
+ *
+ * Return an unique volume name for a drive root or mount point.
+ *
+ * @param VolumeMountPoint
+ * Pointer to string that contains either root drive name or
+ * mount point name.
+ * @param VolumeName
+ * Pointer to buffer that is filled with resulting unique
+ * volume name on success.
+ * @param VolumeNameLength
+ * Size of VolumeName buffer in TCHARs.
+ *
+ * @return
+ * TRUE when the function succeeds and the VolumeName buffer is filled,
+ * FALSE otherwise.
+ */
+
+BOOL WINAPI
+GetVolumeNameForVolumeMountPointW(
+ IN LPCWSTR VolumeMountPoint,
+ OUT LPWSTR VolumeName,
+ IN DWORD VolumeNameLength)
+{
+ UNICODE_STRING NtFileName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE FileHandle;
+ IO_STATUS_BLOCK Iosb;
+ ULONG BufferLength;
+ PMOUNTDEV_NAME MountDevName;
+ PMOUNTMGR_MOUNT_POINT MountPoint;
+ ULONG MountPointSize;
+ PMOUNTMGR_MOUNT_POINTS MountPoints;
+ ULONG Index;
+ PUCHAR SymbolicLinkName;
+ BOOL Result;
+ NTSTATUS Status;
+
+ /*
+ * First step is to convert the passed volume mount point name to
+ * an NT acceptable name.
+ */
+
+ if (!RtlDosPathNameToNtPathName_U(VolumeName, &NtFileName, NULL, NULL))
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
+ }
+
+ if (NtFileName.Length > sizeof(WCHAR) &&
+ NtFileName.Buffer[(NtFileName.Length / sizeof(WCHAR)) - 1] == '\\')
+ {
+ NtFileName.Length -= sizeof(WCHAR);
+ }
+
+ /*
+ * Query mount point device name which we will later use for determining
+ * the volume name.
+ */
+
+ InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL);
+ Status = NtOpenFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+ &ObjectAttributes, &Iosb,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ RtlFreeUnicodeString(&NtFileName);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+
+ BufferLength = sizeof(MOUNTDEV_NAME) + 50 * sizeof(WCHAR);
+ do
+ {
+ MountDevName = RtlAllocateHeap(GetProcessHeap(), 0, BufferLength);
+ if (MountDevName == NULL)
+ {
+ NtClose(FileHandle);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb,
+ IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
+ NULL, 0, MountDevName, BufferLength);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
+ if (Status == STATUS_BUFFER_OVERFLOW)
+ {
+ BufferLength = sizeof(MOUNTDEV_NAME) + MountDevName->NameLength;
+ continue;
+ }
+ else
+ {
+ NtClose(FileHandle);
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+ }
+ }
+ while (!NT_SUCCESS(Status));
+
+ NtClose(FileHandle);
+
+ /*
+ * Get the mount point information from mount manager.
+ */
+
+ MountPointSize = MountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT);
+ MountPoint = RtlAllocateHeap(GetProcessHeap(), 0, MountPointSize);
+ if (MountPoint == NULL)
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ RtlZeroMemory(MountPoint, sizeof(MOUNTMGR_MOUNT_POINT));
+ MountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
+ MountPoint->DeviceNameLength = MountDevName->NameLength;
+ RtlCopyMemory(MountPoint + 1, MountDevName->Name, MountDevName->NameLength);
+ RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
+
+ RtlInitUnicodeString(&NtFileName, L"\\??\\MountPointManager");
+ InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL);
+ Status = NtOpenFile(&FileHandle, FILE_GENERIC_READ, &ObjectAttributes,
+ &Iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ RtlFreeHeap(GetProcessHeap(), 0, MountPoint);
+ return FALSE;
+ }
+
+ BufferLength = sizeof(MOUNTMGR_MOUNT_POINTS);
+ do
+ {
+ MountPoints = RtlAllocateHeap(GetProcessHeap(), 0, BufferLength);
+ if (MountPoints == NULL)
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, MountPoint);
+ NtClose(FileHandle);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb,
+ IOCTL_MOUNTMGR_QUERY_POINTS,
+ MountPoint, MountPointSize,
+ MountPoints, BufferLength);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, MountPoints);
+ if (Status == STATUS_BUFFER_OVERFLOW)
+ {
+ BufferLength = MountPoints->Size;
+ continue;
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, MountPoint);
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+ }
+ }
+ while (!NT_SUCCESS(Status));
+
+ RtlFreeHeap(GetProcessHeap(), 0, MountPoint);
+ NtClose(FileHandle);
+
+ /*
+ * Now we've gathered info about all mount points mapped to our device, so
+ * select the correct one and copy it into the output buffer.
+ */
+
+ for (Index = 0; Index < MountPoints->NumberOfMountPoints; Index++)
+ {
+ MountPoint = MountPoints->MountPoints + Index;
+ SymbolicLinkName = (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset;
+
+ /*
+ * Check for "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\"
+ * (with the last slash being optional) style symbolic links.
+ */
+
+ if (MountPoint->SymbolicLinkNameLength == 48 * sizeof(WCHAR) ||
+ (MountPoint->SymbolicLinkNameLength == 49 * sizeof(WCHAR) &&
+ SymbolicLinkName[48] == L'\\'))
+ {
+ if (RtlCompareMemory(SymbolicLinkName, L"\\??\\Volume{",
+ 11 * sizeof(WCHAR)) == 11 * sizeof(WCHAR) &&
+ SymbolicLinkName[19] == L'-' && SymbolicLinkName[24] == L'-' &&
+ SymbolicLinkName[29] == L'-' && SymbolicLinkName[34] == L'-' &&
+ SymbolicLinkName[47] == L'}')
+ {
+ if (VolumeNameLength >= MountPoint->SymbolicLinkNameLength / sizeof(WCHAR))
+ {
+ RtlCopyMemory(VolumeName,
+ (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset,
+ MountPoint->SymbolicLinkNameLength);
+ VolumeName[1] = L'\\';
+ Result = TRUE;
+ }
+ else
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, MountPoints);
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ Result = FALSE;
+ }
+
+ return Result;
+ }
+ }
+ }
+
+ RtlFreeHeap(GetProcessHeap(), 0, MountPoints);
+ SetLastError(ERROR_INVALID_PARAMETER);
+
+ return FALSE;
+}
+
/* EOF */