/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
- * FILE: lib/kernel32/file/volume.c
+ * FILE: dll/win32/kernel32/client/file/volume.c
* PURPOSE: File volume functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
* Erik Bos, Alexandre Julliard :
* GetLogicalDriveStringsA,
* GetLogicalDriveStringsW, GetLogicalDrives
+ * Pierre Schweitzer (pierre@reactos.org)
* UPDATE HISTORY:
* Created 01/11/98
*/
#include <debug.h>
DEBUG_CHANNEL(kernel32file);
-#define MAX_DOS_DRIVES 26
-
-
-static HANDLE
-InternalOpenDirW(LPCWSTR DirName,
- BOOLEAN Write)
+HANDLE
+WINAPI
+InternalOpenDirW(IN LPCWSTR DirName,
+ IN BOOLEAN Write)
{
- UNICODE_STRING NtPathU;
- OBJECT_ATTRIBUTES ObjectAttributes;
- NTSTATUS errCode;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE hFile;
-
- if (!RtlDosPathNameToNtPathName_U(DirName,
- &NtPathU,
- NULL,
- NULL))
+ UNICODE_STRING NtPathU;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS errCode;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE hFile;
+
+ if (!RtlDosPathNameToNtPathName_U(DirName, &NtPathU, NULL, NULL))
{
- WARN("Invalid path\n");
- SetLastError(ERROR_BAD_PATHNAME);
- return INVALID_HANDLE_VALUE;
+ WARN("Invalid path\n");
+ SetLastError(ERROR_BAD_PATHNAME);
+ return INVALID_HANDLE_VALUE;
}
InitializeObjectAttributes(&ObjectAttributes,
- &NtPathU,
- OBJ_CASE_INSENSITIVE,
- 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);
+ &NtPathU,
+ OBJ_CASE_INSENSITIVE,
+ 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))
{
- BaseSetLastNTError (errCode);
- return INVALID_HANDLE_VALUE;
+ BaseSetLastNTError(errCode);
+ return INVALID_HANDLE_VALUE;
}
+
return hFile;
}
-
/*
* @implemented
*/
-/* Synced to Wine-2008/12/28 */
-DWORD WINAPI
-GetLogicalDriveStringsA(DWORD nBufferLength,
- LPSTR lpBuffer)
-{
- DWORD drive, count;
- DWORD dwDriveMap;
- LPSTR p;
-
- dwDriveMap = GetLogicalDrives();
-
- for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
- {
- if (dwDriveMap & (1<<drive))
- count++;
- }
-
-
- if ((count * 4) + 1 > nBufferLength) return ((count * 4) + 1);
-
- p = lpBuffer;
-
- for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
- if (dwDriveMap & (1<<drive))
- {
- *p++ = 'A' + (UCHAR)drive;
- *p++ = ':';
- *p++ = '\\';
- *p++ = '\0';
- }
- *p = '\0';
+BOOL
+WINAPI
+GetVolumeInformationA(IN LPCSTR lpRootPathName,
+ IN LPSTR lpVolumeNameBuffer,
+ IN DWORD nVolumeNameSize,
+ OUT LPDWORD lpVolumeSerialNumber OPTIONAL,
+ OUT LPDWORD lpMaximumComponentLength OPTIONAL,
+ OUT LPDWORD lpFileSystemFlags OPTIONAL,
+ OUT LPSTR lpFileSystemNameBuffer OPTIONAL,
+ IN DWORD nFileSystemNameSize)
+{
+ BOOL Ret;
+ NTSTATUS Status;
+ PUNICODE_STRING RootPathNameU;
+ ANSI_STRING VolumeName, FileSystemName;
+ UNICODE_STRING VolumeNameU, FileSystemNameU;
- return (count * 4);
-}
+ /* If no root path provided, default to \ */
+ if (lpRootPathName == NULL)
+ {
+ lpRootPathName = "\\";
+ }
+ /* Convert root path to unicode */
+ RootPathNameU = Basep8BitStringToStaticUnicodeString(lpRootPathName);
+ if (RootPathNameU == NULL)
+ {
+ return FALSE;
+ }
-/*
- * @implemented
- */
-/* Synced to Wine-2008/12/28 */
-DWORD WINAPI
-GetLogicalDriveStringsW(DWORD nBufferLength,
- LPWSTR lpBuffer)
-{
- DWORD drive, count;
- DWORD dwDriveMap;
- LPWSTR p;
+ /* Init all our STRINGS (U/A) */
+ VolumeNameU.Buffer = NULL;
+ VolumeNameU.MaximumLength = 0;
+ FileSystemNameU.Buffer = NULL;
+ FileSystemNameU.MaximumLength = 0;
- dwDriveMap = GetLogicalDrives();
+ VolumeName.Buffer = lpVolumeNameBuffer;
+ VolumeName.MaximumLength = nVolumeNameSize + 1;
+ FileSystemName.Buffer = lpFileSystemNameBuffer;
+ FileSystemName.MaximumLength = nFileSystemNameSize + 1;
- for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
- {
- if (dwDriveMap & (1<<drive))
- count++;
- }
+ /* Assume failure for now */
+ Ret = FALSE;
- if ((count * 4) + 1 > nBufferLength) return ((count * 4) + 1);
+ /* If caller wants volume name, allocate a buffer to receive it */
+ if (lpVolumeNameBuffer != NULL)
+ {
+ VolumeNameU.MaximumLength = sizeof(WCHAR) * (nVolumeNameSize + 1);
+ VolumeNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+ VolumeNameU.MaximumLength);
+ if (VolumeNameU.Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto CleanAndQuit;
+ }
+ }
- p = lpBuffer;
- for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
- if (dwDriveMap & (1<<drive))
+ /* If caller wants file system name, allocate a buffer to receive it */
+ if (lpFileSystemNameBuffer != NULL)
+ {
+ FileSystemNameU.MaximumLength = sizeof(WCHAR) * (nVolumeNameSize + 1);
+ FileSystemNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+ FileSystemNameU.MaximumLength);
+ if (FileSystemNameU.Buffer == NULL)
{
- *p++ = (WCHAR)('A' + drive);
- *p++ = (WCHAR)':';
- *p++ = (WCHAR)'\\';
- *p++ = (WCHAR)'\0';
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto CleanAndQuit;
}
- *p = (WCHAR)'\0';
+ }
- return (count * 4);
-}
+ /* Call W */
+ Ret = GetVolumeInformationW(RootPathNameU->Buffer, VolumeNameU.Buffer,
+ nVolumeNameSize, lpVolumeSerialNumber,
+ lpMaximumComponentLength, lpFileSystemFlags,
+ FileSystemNameU.Buffer, nFileSystemNameSize);
+ /* If it succeed, convert back to ANSI */
+ if (Ret)
+ {
+ if (lpVolumeNameBuffer != NULL)
+ {
+ RtlInitUnicodeString(&VolumeNameU, VolumeNameU.Buffer);
+ Status = RtlUnicodeStringToAnsiString(&VolumeName, &VolumeNameU, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ Ret = FALSE;
+ goto CleanAndQuit;
+ }
+ }
-/*
- * @implemented
- */
-/* Synced to Wine-? */
-DWORD WINAPI
-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))
- {
- BaseSetLastNTError(Status);
- return 0;
- }
-
- return ProcessDeviceMapInfo.Query.DriveMap;
-}
+ if (lpFileSystemNameBuffer != NULL)
+ {
+ RtlInitUnicodeString(&FileSystemNameU, FileSystemNameU.Buffer);
+ Status = RtlUnicodeStringToAnsiString(&FileSystemName, &FileSystemNameU, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ Ret = FALSE;
+ goto CleanAndQuit;
+ }
+ }
+ }
-/*
- * @implemented
- */
-BOOL WINAPI
-GetDiskFreeSpaceA (
- LPCSTR lpRootPathName,
- LPDWORD lpSectorsPerCluster,
- LPDWORD lpBytesPerSector,
- LPDWORD lpNumberOfFreeClusters,
- LPDWORD lpTotalNumberOfClusters
- )
-{
- PWCHAR RootPathNameW=NULL;
+ /* Clean and quit */
+CleanAndQuit:
+ if (VolumeNameU.Buffer != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameU.Buffer);
+ }
- if (lpRootPathName)
- {
- if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
- return FALSE;
- }
+ if (FileSystemNameU.Buffer != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FileSystemNameU.Buffer);
+ }
- return GetDiskFreeSpaceW (RootPathNameW,
- lpSectorsPerCluster,
- lpBytesPerSector,
- lpNumberOfFreeClusters,
- lpTotalNumberOfClusters);
+ return Ret;
}
-
/*
* @implemented
*/
-BOOL WINAPI
-GetDiskFreeSpaceW(
- LPCWSTR lpRootPathName,
- LPDWORD lpSectorsPerCluster,
- LPDWORD lpBytesPerSector,
- LPDWORD lpNumberOfFreeClusters,
- LPDWORD lpTotalNumberOfClusters
- )
+static BOOL
+IsThisARootDirectory(IN HANDLE VolumeHandle,
+ IN PUNICODE_STRING NtPathName)
{
- FILE_FS_SIZE_INFORMATION FileFsSize;
+ NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
- WCHAR RootPathName[MAX_PATH];
- HANDLE hFile;
- NTSTATUS errCode;
-
- if (lpRootPathName)
- {
- wcsncpy (RootPathName, lpRootPathName, 3);
- }
- else
+ struct
{
- GetCurrentDirectoryW (MAX_PATH, RootPathName);
- }
- RootPathName[3] = 0;
+ FILE_NAME_INFORMATION;
+ WCHAR Buffer[MAX_PATH];
+ } FileNameInfo;
- hFile = InternalOpenDirW(RootPathName, FALSE);
- if (INVALID_HANDLE_VALUE == hFile)
+ /* If we have a handle, query the name */
+ if (VolumeHandle)
{
- SetLastError(ERROR_PATH_NOT_FOUND);
- return FALSE;
+ Status = NtQueryInformationFile(VolumeHandle, &IoStatusBlock, &FileNameInfo, sizeof(FileNameInfo), FileNameInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ return FALSE;
+ }
+
+ /* Check we properly end with a \ */
+ if (FileNameInfo.FileName[FileNameInfo.FileNameLength / sizeof(WCHAR) - 1] != L'\\')
+ {
+ return FALSE;
+ }
}
- errCode = NtQueryVolumeInformationFile(hFile,
- &IoStatusBlock,
- &FileFsSize,
- sizeof(FILE_FS_SIZE_INFORMATION),
- FileFsSizeInformation);
- if (!NT_SUCCESS(errCode))
+ /* If we have a path */
+ if (NtPathName != NULL)
{
- CloseHandle(hFile);
- BaseSetLastNTError (errCode);
- return FALSE;
- }
+ HANDLE LinkHandle;
+ WCHAR Buffer[512];
+ ULONG ReturnedLength;
+ UNICODE_STRING LinkTarget;
+ OBJECT_ATTRIBUTES ObjectAttributes;
- 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);
+ NtPathName->Length -= sizeof(WCHAR);
- return TRUE;
-}
+ InitializeObjectAttributes(&ObjectAttributes, NtPathName,
+ OBJ_CASE_INSENSITIVE,
+ NULL, NULL);
+ /* Try to see whether that's a symbolic name */
+ Status = NtOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes);
+ NtPathName->Length += sizeof(WCHAR);
+ if (!NT_SUCCESS(Status))
+ {
+ return FALSE;
+ }
-/*
- * @implemented
- */
-BOOL WINAPI
-GetDiskFreeSpaceExA (
- LPCSTR lpDirectoryName OPTIONAL,
- PULARGE_INTEGER lpFreeBytesAvailableToCaller,
- PULARGE_INTEGER lpTotalNumberOfBytes,
- PULARGE_INTEGER lpTotalNumberOfFreeBytes
- )
-{
- PWCHAR DirectoryNameW=NULL;
+ /* If so, query the target */
+ LinkTarget.Buffer = Buffer;
+ LinkTarget.Length = 0;
+ LinkTarget.MaximumLength = sizeof(Buffer);
- if (lpDirectoryName)
- {
- if (!(DirectoryNameW = FilenameA2W(lpDirectoryName, FALSE)))
- return FALSE;
- }
+ Status = NtQuerySymbolicLinkObject(LinkHandle, &LinkTarget, &ReturnedLength);
+ NtClose(LinkHandle);
+ /* A root directory (NtName) is a symbolic link */
+ if (!NT_SUCCESS(Status))
+ {
+ return FALSE;
+ }
+ }
- return GetDiskFreeSpaceExW (DirectoryNameW ,
- lpFreeBytesAvailableToCaller,
- lpTotalNumberOfBytes,
- lpTotalNumberOfFreeBytes);
+ return TRUE;
}
-
/*
* @implemented
*/
-BOOL WINAPI
-GetDiskFreeSpaceExW(
- LPCWSTR lpDirectoryName OPTIONAL,
- PULARGE_INTEGER lpFreeBytesAvailableToCaller,
- PULARGE_INTEGER lpTotalNumberOfBytes,
- PULARGE_INTEGER lpTotalNumberOfFreeBytes
- )
-{
- union
- {
- FILE_FS_SIZE_INFORMATION FsSize;
- FILE_FS_FULL_SIZE_INFORMATION FsFullSize;
- } FsInfo;
- IO_STATUS_BLOCK IoStatusBlock;
- ULARGE_INTEGER BytesPerCluster;
- HANDLE hFile;
+BOOL
+WINAPI
+GetVolumeInformationW(IN LPCWSTR lpRootPathName,
+ IN LPWSTR lpVolumeNameBuffer,
+ IN DWORD nVolumeNameSize,
+ OUT LPDWORD lpVolumeSerialNumber OPTIONAL,
+ OUT LPDWORD lpMaximumComponentLength OPTIONAL,
+ OUT LPDWORD lpFileSystemFlags OPTIONAL,
+ OUT LPWSTR lpFileSystemNameBuffer OPTIONAL,
+ IN DWORD nFileSystemNameSize)
+{
+ BOOL Ret;
NTSTATUS Status;
+ HANDLE VolumeHandle;
+ LPCWSTR RootPathName;
+ UNICODE_STRING NtPathName;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PFILE_FS_VOLUME_INFORMATION VolumeInfo;
+ PFILE_FS_ATTRIBUTE_INFORMATION VolumeAttr;
+ ULONG OldMode, VolumeInfoSize, VolumeAttrSize;
- if (lpDirectoryName == NULL)
- lpDirectoryName = L"\\";
+ /* If no root path provided, default to \ */
+ if (lpRootPathName == NULL)
+ {
+ RootPathName = L"\\";
+ }
+ else
+ {
+ RootPathName = lpRootPathName;
+ }
- hFile = InternalOpenDirW(lpDirectoryName, FALSE);
- if (INVALID_HANDLE_VALUE == hFile)
+ /* Convert to NT name */
+ if (!RtlDosPathNameToNtPathName_U(RootPathName, &NtPathName, NULL, NULL))
{
+ SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
- if (lpFreeBytesAvailableToCaller != NULL || lpTotalNumberOfBytes != NULL)
+ /* Check we really end with a backslash */
+ if (NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 1] != L'\\')
{
- /* To get the free space available to the user associated with the
- current thread, try FileFsFullSizeInformation. If this is not
- supported by the file system, fall back to FileFsSize */
-
- Status = NtQueryVolumeInformationFile(hFile,
- &IoStatusBlock,
- &FsInfo.FsFullSize,
- sizeof(FsInfo.FsFullSize),
- FileFsFullSizeInformation);
-
- if (NT_SUCCESS(Status))
- {
- /* Close the handle before returning data
- to avoid a handle leak in case of a fault! */
- CloseHandle(hFile);
-
- BytesPerCluster.QuadPart =
- FsInfo.FsFullSize.BytesPerSector * FsInfo.FsFullSize.SectorsPerAllocationUnit;
-
- if (lpFreeBytesAvailableToCaller != NULL)
- {
- lpFreeBytesAvailableToCaller->QuadPart =
- BytesPerCluster.QuadPart * FsInfo.FsFullSize.CallerAvailableAllocationUnits.QuadPart;
- }
-
- if (lpTotalNumberOfBytes != NULL)
- {
- lpTotalNumberOfBytes->QuadPart =
- BytesPerCluster.QuadPart * FsInfo.FsFullSize.TotalAllocationUnits.QuadPart;
- }
-
- if (lpTotalNumberOfFreeBytes != NULL)
- {
- lpTotalNumberOfFreeBytes->QuadPart =
- BytesPerCluster.QuadPart * FsInfo.FsFullSize.ActualAvailableAllocationUnits.QuadPart;
- }
-
- return TRUE;
- }
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);
+ return FALSE;
}
- Status = NtQueryVolumeInformationFile(hFile,
- &IoStatusBlock,
- &FsInfo.FsSize,
- sizeof(FsInfo.FsSize),
- FileFsSizeInformation);
-
- /* Close the handle before returning data
- to avoid a handle leak in case of a fault! */
- CloseHandle(hFile);
+ /* Try to open the received path */
+ InitializeObjectAttributes(&ObjectAttributes, &NtPathName,
+ OBJ_CASE_INSENSITIVE,
+ NULL, NULL);
+ /* No errors to the user */
+ RtlSetThreadErrorMode(RTL_SEM_FAILCRITICALERRORS, &OldMode);
+ Status = NtOpenFile(&VolumeHandle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, 0, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT);
+ RtlSetThreadErrorMode(OldMode, NULL);
if (!NT_SUCCESS(Status))
{
- BaseSetLastNTError (Status);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ BaseSetLastNTError(Status);
return FALSE;
}
- BytesPerCluster.QuadPart =
- FsInfo.FsSize.BytesPerSector * FsInfo.FsSize.SectorsPerAllocationUnit;
-
- if (lpFreeBytesAvailableToCaller)
+ /* Check whether that's a root directory */
+ if (!IsThisARootDirectory(VolumeHandle, &NtPathName))
{
- lpFreeBytesAvailableToCaller->QuadPart =
- BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart;
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ NtClose(VolumeHandle);
+ SetLastError(ERROR_DIR_NOT_ROOT);
+ return FALSE;
}
- if (lpTotalNumberOfBytes)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+
+ /* Assume we don't need to query FileFsVolumeInformation */
+ VolumeInfo = NULL;
+ /* If user wants volume name, allocate a buffer to query it */
+ if (lpVolumeNameBuffer != NULL)
{
- lpTotalNumberOfBytes->QuadPart =
- BytesPerCluster.QuadPart * FsInfo.FsSize.TotalAllocationUnits.QuadPart;
+ VolumeInfoSize = nVolumeNameSize + sizeof(FILE_FS_VOLUME_INFORMATION);
}
-
- if (lpTotalNumberOfFreeBytes)
+ /* If user just wants the serial number, allocate a dummy buffer */
+ else if (lpVolumeSerialNumber != NULL)
{
- lpTotalNumberOfFreeBytes->QuadPart =
- BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart;
+ VolumeInfoSize = MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION);
+ }
+ /* Otherwise, nothing to query */
+ else
+ {
+ VolumeInfoSize = 0;
}
- return TRUE;
-}
-
-
-/*
- * @implemented
- */
-UINT WINAPI
-GetDriveTypeA(LPCSTR lpRootPathName)
-{
- PWCHAR RootPathNameW;
-
- if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
- return DRIVE_UNKNOWN;
-
- return GetDriveTypeW(RootPathNameW);
-}
-
-
-/*
- * @implemented
- */
-UINT WINAPI
-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);
- BaseSetLastNTError (errCode);
- return 0;
- }
- CloseHandle(hFile);
-
- switch (FileFsDevice.DeviceType)
+ /* If we're to query, allocate a big enough buffer */
+ if (VolumeInfoSize != 0)
+ {
+ VolumeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeInfoSize);
+ if (VolumeInfo == NULL)
{
- 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;
+ NtClose(VolumeHandle);
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ return FALSE;
}
+ }
- ERR("Returning DRIVE_UNKNOWN for device type %d\n", FileFsDevice.DeviceType);
-
- return DRIVE_UNKNOWN;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-GetVolumeInformationA(
- LPCSTR lpRootPathName,
- LPSTR lpVolumeNameBuffer,
- DWORD nVolumeNameSize,
- LPDWORD lpVolumeSerialNumber,
- LPDWORD lpMaximumComponentLength,
- LPDWORD lpFileSystemFlags,
- LPSTR lpFileSystemNameBuffer,
- DWORD nFileSystemNameSize
- )
-{
- UNICODE_STRING FileSystemNameU;
- UNICODE_STRING VolumeNameU = { 0, 0, NULL };
- ANSI_STRING VolumeName;
- ANSI_STRING FileSystemName;
- PWCHAR RootPathNameW;
- BOOL Result;
-
- if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
- return FALSE;
-
- if (lpVolumeNameBuffer)
+ /* Assume we don't need to query FileFsAttributeInformation */
+ VolumeAttr = NULL;
+ /* If user wants filesystem name, allocate a buffer to query it */
+ if (lpFileSystemNameBuffer != NULL)
+ {
+ VolumeAttrSize = nFileSystemNameSize + sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
+ }
+ /* If user just wants max compo len or flags, allocate a dummy buffer */
+ else if (lpMaximumComponentLength != NULL || lpFileSystemFlags != NULL)
+ {
+ VolumeAttrSize = MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
+ }
+ else
{
- VolumeNameU.MaximumLength = (USHORT)nVolumeNameSize * sizeof(WCHAR);
- VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
- 0,
- VolumeNameU.MaximumLength);
- if (VolumeNameU.Buffer == NULL)
- {
- goto FailNoMem;
- }
+ VolumeAttrSize = 0;
}
- if (lpFileSystemNameBuffer)
+ /* If we're to query, allocate a big enough buffer */
+ if (VolumeAttrSize != 0)
{
- FileSystemNameU.Length = 0;
- FileSystemNameU.MaximumLength = (USHORT)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;
- }
+ VolumeAttr = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeAttrSize);
+ if (VolumeAttr == NULL)
+ {
+ if (VolumeInfo != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
+ }
+
+ NtClose(VolumeHandle);
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ return FALSE;
+ }
}
- Result = GetVolumeInformationW (RootPathNameW,
- lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL,
- nVolumeNameSize,
- lpVolumeSerialNumber,
- lpMaximumComponentLength,
- lpFileSystemFlags,
- lpFileSystemNameBuffer ? FileSystemNameU.Buffer : NULL,
- nFileSystemNameSize);
+ /* Assume we'll fail */
+ Ret = FALSE;
- if (Result)
+ /* If we're to query FileFsVolumeInformation, do it now! */
+ if (VolumeInfo != NULL)
{
- if (lpVolumeNameBuffer)
+ Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, VolumeInfo, VolumeInfoSize, FileFsVolumeInformation);
+ if (!NT_SUCCESS(Status))
{
- VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR);
- VolumeName.Length = 0;
- VolumeName.MaximumLength = (USHORT)nVolumeNameSize;
- VolumeName.Buffer = lpVolumeNameBuffer;
- }
-
- if (lpFileSystemNameBuffer)
- {
- FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR);
- FileSystemName.Length = 0;
- FileSystemName.MaximumLength = (USHORT)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);
- }
- }
+ BaseSetLastNTError(Status);
+ goto CleanAndQuit;
+ }
}
- if (lpVolumeNameBuffer)
+ /* If we're to query FileFsAttributeInformation, do it now! */
+ if (VolumeAttr != NULL)
{
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- VolumeNameU.Buffer);
+ Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, VolumeAttr, VolumeAttrSize, FileFsAttributeInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ goto CleanAndQuit;
+ }
}
- if (lpFileSystemNameBuffer)
+
+ /* If user wants volume name */
+ if (lpVolumeNameBuffer != NULL)
{
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- FileSystemNameU.Buffer);
+ /* Check its buffer can hold it (+ 0) */
+ if (VolumeInfo->VolumeLabelLength >= nVolumeNameSize)
+ {
+ SetLastError(ERROR_BAD_LENGTH);
+ goto CleanAndQuit;
+ }
+
+ /* Copy and zero */
+ RtlCopyMemory(lpVolumeNameBuffer, VolumeInfo->VolumeLabel, VolumeInfo->VolumeLabelLength);
+ lpVolumeNameBuffer[VolumeInfo->VolumeLabelLength / sizeof(WCHAR)] = UNICODE_NULL;
}
- return Result;
-}
+ /* If user wants wants serial number, return it */
+ if (lpVolumeSerialNumber != NULL)
+ {
+ *lpVolumeSerialNumber = VolumeInfo->VolumeSerialNumber;
+ }
-#define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION))
+ /* If user wants filesystem name */
+ if (lpFileSystemNameBuffer != NULL)
+ {
+ /* Check its buffer can hold it (+ 0) */
+ if (VolumeAttr->FileSystemNameLength >= nFileSystemNameSize)
+ {
+ SetLastError(ERROR_BAD_LENGTH);
+ goto CleanAndQuit;
+ }
-#define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
+ /* Copy and zero */
+ RtlCopyMemory(lpFileSystemNameBuffer, VolumeAttr->FileSystemName, VolumeAttr->FileSystemNameLength);
+ lpFileSystemNameBuffer[VolumeAttr->FileSystemNameLength / sizeof(WCHAR)] = UNICODE_NULL;
+ }
-/*
- * @implemented
- */
-BOOL WINAPI
-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;
- 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;
-
- TRACE("FileFsVolume %p\n", FileFsVolume);
- TRACE("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)
+ /* If user wants wants max compo len, return it */
+ if (lpMaximumComponentLength != NULL)
{
- return FALSE;
+ *lpMaximumComponentLength = VolumeAttr->MaximumComponentNameLength;
}
- TRACE("hFile: %x\n", hFile);
- errCode = NtQueryVolumeInformationFile(hFile,
- &IoStatusBlock,
- FileFsVolume,
- FS_VOLUME_BUFFER_SIZE,
- FileFsVolumeInformation);
- if ( !NT_SUCCESS(errCode) )
+ /* If user wants wants FS flags, return them */
+ if (lpFileSystemFlags != NULL)
{
- WARN("Status: %x\n", errCode);
- CloseHandle(hFile);
- BaseSetLastNTError (errCode);
- return FALSE;
+ *lpFileSystemFlags = VolumeAttr->FileSystemAttributes;
}
- if (lpVolumeSerialNumber)
- *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
+ /* We did it! */
+ Ret = TRUE;
- 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;
- }
- }
+CleanAndQuit:
+ NtClose(VolumeHandle);
- errCode = NtQueryVolumeInformationFile (hFile,
- &IoStatusBlock,
- FileFsAttribute,
- FS_ATTRIBUTE_BUFFER_SIZE,
- FileFsAttributeInformation);
- CloseHandle(hFile);
- if (!NT_SUCCESS(errCode))
+ if (VolumeInfo != NULL)
{
- WARN("Status: %x\n", errCode);
- BaseSetLastNTError (errCode);
- return FALSE;
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
}
- if (lpFileSystemFlags)
- *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
- if (lpMaximumComponentLength)
- *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
- if (lpFileSystemNameBuffer)
+ if (VolumeAttr != NULL)
{
- 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;
- }
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeAttr);
}
- return TRUE;
-}
+ return Ret;
+}
/*
* @implemented
*/
BOOL
WINAPI
-SetVolumeLabelA (
- LPCSTR lpRootPathName,
- LPCSTR lpVolumeName /* NULL if deleting label */
- )
+SetVolumeLabelA(IN LPCSTR lpRootPathName,
+ IN LPCSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
{
PWCHAR RootPathNameW;
PWCHAR VolumeNameW = NULL;
return Result;
}
-
/*
* @implemented
*/
-BOOL WINAPI
-SetVolumeLabelW(
- LPCWSTR lpRootPathName,
- LPCWSTR lpVolumeName /* NULL if deleting label */
- )
+BOOL
+WINAPI
+SetVolumeLabelW(IN LPCWSTR lpRootPathName,
+ IN LPCWSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
{
PFILE_FS_LABEL_INFORMATION LabelInfo;
IO_STATUS_BLOCK IoStatusBlock;
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;
-
- if (!VolumeMountPoint || !VolumeMountPoint[0])
- {
- SetLastError(ERROR_PATH_NOT_FOUND);
- return FALSE;
- }
-
- /*
- * First step is to convert the passed volume mount point name to
- * an NT acceptable name.
- */
-
- if (!RtlDosPathNameToNtPathName_U(VolumeMountPoint, &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))
- {
- BaseSetLastNTError(Status);
- return FALSE;
- }
-
- BufferLength = sizeof(MOUNTDEV_NAME) + 50 * sizeof(WCHAR);
- do
- {
- MountDevName = RtlAllocateHeap(RtlGetProcessHeap(), 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);
- BaseSetLastNTError(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(RtlGetProcessHeap(), 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))
- {
- BaseSetLastNTError(Status);
- RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
- return FALSE;
- }
-
- BufferLength = sizeof(MOUNTMGR_MOUNT_POINTS);
- do
- {
- MountPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
- if (MountPoints == NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 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))
- {
- if (Status == STATUS_BUFFER_OVERFLOW)
- {
- BufferLength = MountPoints->Size;
- RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
- continue;
- }
- else if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
- RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
- NtClose(FileHandle);
- BaseSetLastNTError(Status);
- return FALSE;
- }
- }
- }
- while (!NT_SUCCESS(Status));
-
- RtlFreeHeap(RtlGetProcessHeap(), 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
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- Result = FALSE;
- }
-
- RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
-
- return Result;
- }
- }
- }
-
- RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
- SetLastError(ERROR_INVALID_PARAMETER);
-
- return FALSE;
-}
-
-/*
- * @implemented (Wine 13 sep 2008)
- */
-BOOL
-WINAPI
-GetVolumeNameForVolumeMountPointA(
- LPCSTR lpszVolumeMountPoint,
- LPSTR lpszVolumeName,
- DWORD cchBufferLength
- )
-{
- BOOL ret;
- WCHAR volumeW[50], *pathW = NULL;
- DWORD len = min( sizeof(volumeW) / sizeof(WCHAR), cchBufferLength );
-
- TRACE("(%s, %p, %x)\n", debugstr_a(lpszVolumeMountPoint), lpszVolumeName, cchBufferLength);
-
- if (!lpszVolumeMountPoint || !(pathW = FilenameA2W( lpszVolumeMountPoint, TRUE )))
- return FALSE;
-
- if ((ret = GetVolumeNameForVolumeMountPointW( pathW, volumeW, len )))
- FilenameW2A_N( lpszVolumeName, len, volumeW, -1 );
-
- RtlFreeHeap( RtlGetProcessHeap(), 0, pathW );
- return ret;
-}
-
/*
* @implemented (Wine 13 sep 2008)
*/
HANDLE
WINAPI
-FindFirstVolumeW(
- LPWSTR volume,
- DWORD len
- )
+FindFirstVolumeW(IN LPWSTR volume,
+ IN DWORD len)
{
DWORD size = 1024;
+ DWORD br;
HANDLE mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE );
if (mgr == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
memset( &input, 0, sizeof(input) );
if (!DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_POINTS, &input, sizeof(input),
- output, size, NULL, NULL ))
+ output, size, &br, NULL ))
{
if (GetLastError() != ERROR_MORE_DATA) break;
size = output->Size;
*/
HANDLE
WINAPI
-FindFirstVolumeA(
- LPSTR volume,
- DWORD len
- )
+FindFirstVolumeA(IN LPSTR volume,
+ IN DWORD len)
{
WCHAR *buffer = NULL;
HANDLE handle;
*/
BOOL
WINAPI
-FindVolumeClose(
- HANDLE hFindVolume
- )
+FindVolumeClose(IN HANDLE hFindVolume)
{
return RtlFreeHeap(RtlGetProcessHeap(), 0, hFindVolume);
}
*/
BOOL
WINAPI
-GetVolumePathNameA(LPCSTR lpszFileName,
- LPSTR lpszVolumePathName,
- DWORD cchBufferLength)
+GetVolumePathNameA(IN LPCSTR lpszFileName,
+ IN LPSTR lpszVolumePathName,
+ IN DWORD cchBufferLength)
{
PWCHAR FileNameW = NULL;
WCHAR VolumePathName[MAX_PATH];
*/
BOOL
WINAPI
-GetVolumePathNameW(LPCWSTR lpszFileName,
- LPWSTR lpszVolumePathName,
- DWORD cchBufferLength)
+GetVolumePathNameW(IN LPCWSTR lpszFileName,
+ IN LPWSTR lpszVolumePathName,
+ IN DWORD cchBufferLength)
{
DWORD PathLength;
UNICODE_STRING UnicodeFilePath;
DWORD ErrorCode;
BOOL Result = FALSE;
+ if (!lpszFileName || !lpszVolumePathName || !cchBufferLength)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
if (!(PathLength = GetFullPathNameW(lpszFileName, 0, NULL, NULL)))
{
return Result;
return Result;
}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-SetVolumeMountPointW(
- LPCWSTR lpszVolumeMountPoint,
- LPCWSTR lpszVolumeName
- )
-{
- STUB;
- return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-DeleteVolumeMountPointA(
- LPCSTR lpszVolumeMountPoint
- )
-{
- STUB;
- return 0;
-}
-
-/*
- * @unimplemented
- */
-HANDLE
-WINAPI
-FindFirstVolumeMountPointA(
- LPCSTR lpszRootPathName,
- LPSTR lpszVolumeMountPoint,
- DWORD cchBufferLength
- )
-{
- STUB;
- return 0;
-}
-
/*
* @implemented
*/
BOOL
WINAPI
-FindNextVolumeA(HANDLE handle,
- LPSTR volume,
- DWORD len)
+FindNextVolumeA(IN HANDLE handle,
+ IN LPSTR volume,
+ IN DWORD len)
{
WCHAR *buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, len * sizeof(WCHAR));
BOOL ret;
if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) ret = FALSE;
}
- HeapFree( GetProcessHeap(), 0, buffer );
+ RtlFreeHeap(RtlGetProcessHeap(), 0, buffer);
return ret;
}
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-FindNextVolumeMountPointA(
- HANDLE hFindVolumeMountPoint,
- LPSTR lpszVolumeMountPoint,
- DWORD cchBufferLength
- )
-{
- STUB;
- return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-GetVolumePathNamesForVolumeNameA(
- LPCSTR lpszVolumeName,
- LPSTR lpszVolumePathNames,
- DWORD cchBufferLength,
- PDWORD lpcchReturnLength
- )
-{
- STUB;
- return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-SetVolumeMountPointA(
- LPCSTR lpszVolumeMountPoint,
- LPCSTR lpszVolumeName
- )
-{
- STUB;
- return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-FindVolumeMountPointClose(
- HANDLE hFindVolumeMountPoint
- )
-{
- STUB;
- return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-DeleteVolumeMountPointW(
- LPCWSTR lpszVolumeMountPoint
- )
-{
- STUB;
- return 0;
-}
-
-/*
- * @unimplemented
- */
-HANDLE
-WINAPI
-FindFirstVolumeMountPointW(
- LPCWSTR lpszRootPathName,
- LPWSTR lpszVolumeMountPoint,
- DWORD cchBufferLength
- )
-{
- STUB;
- return 0;
-}
-
/*
* @implemented
*/
BOOL
WINAPI
-FindNextVolumeW(
- HANDLE handle,
- LPWSTR volume,
- DWORD len
- )
+FindNextVolumeW(IN HANDLE handle,
+ IN LPWSTR volume,
+ IN DWORD len)
{
MOUNTMGR_MOUNT_POINTS *data = handle;
*/
BOOL
WINAPI
-FindNextVolumeMountPointW(
- HANDLE hFindVolumeMountPoint,
- LPWSTR lpszVolumeMountPoint,
- DWORD cchBufferLength
- )
+GetVolumePathNamesForVolumeNameA(IN LPCSTR lpszVolumeName,
+ IN LPSTR lpszVolumePathNames,
+ IN DWORD cchBufferLength,
+ OUT PDWORD lpcchReturnLength)
{
STUB;
return 0;
}
+
/*
* @unimplemented
*/
BOOL
WINAPI
-GetVolumePathNamesForVolumeNameW(
- LPCWSTR lpszVolumeName,
- LPWSTR lpszVolumePathNames,
- DWORD cchBufferLength,
- PDWORD lpcchReturnLength
- )
+GetVolumePathNamesForVolumeNameW(IN LPCWSTR lpszVolumeName,
+ IN LPWSTR lpszVolumePathNames,
+ IN DWORD cchBufferLength,
+ OUT PDWORD lpcchReturnLength)
{
STUB;
return 0;
}
-
/* EOF */