Author: pschweitzer
Date: Sun Oct 1 16:36:37 2017
New Revision: 76025
URL:
http://svn.reactos.org/svn/reactos?rev=76025&view=rev
Log:
[KERNEL32]
- Implement the internal functions: GetVolumeNameForRoot(),
BasepGetVolumeNameFromReparsePoint(), BasepGetVolumeNameForVolumeMountPoint() that allow
querying the volume name (GUID form) given a volume root
- Reimplement GetVolumeNameForVolumeMountPointW() with the new internal function
BasepGetVolumeNameForVolumeMountPoint() this fixes a few bugs and adds supports for
reparse points
- Reimplement GetVolumeNameForVolumeMountPointA() to make it w2k3 compliant
Note that I dropped copyrights in the header, as everything got reimplemented
Modified:
trunk/reactos/dll/win32/kernel32/client/file/mntpoint.c
Modified: trunk/reactos/dll/win32/kernel32/client/file/mntpoint.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/file/mntpoint.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/file/mntpoint.c [iso-8859-1] Sun Oct 1
16:36:37 2017
@@ -3,25 +3,468 @@
* PROJECT: ReactOS system libraries
* FILE: dll/win32/kernel32/client/file/mntpoint.c
* PURPOSE: File volume mount point functions
- * PROGRAMMER: Ariadne ( ariadne(a)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
+ * PROGRAMMER: Pierre Schweitzer (pierre(a)reactos.org)
*/
#include <k32.h>
#define NDEBUG
#include <debug.h>
-DEBUG_CHANNEL(kernel32file);
+
+/*
+ * @implemented
+ */
+static BOOL
+GetVolumeNameForRoot(IN LPCWSTR lpszRootPath,
+ OUT LPWSTR lpszVolumeName,
+ IN DWORD cchBufferLength)
+{
+ BOOL Ret;
+ NTSTATUS Status;
+ PWSTR FoundVolume;
+ DWORD BytesReturned;
+ UNICODE_STRING NtPathName;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PMOUNTMGR_MOUNT_POINT MountPoint;
+ ULONG CurrentMntPt, FoundVolumeLen;
+ PMOUNTMGR_MOUNT_POINTS MountPoints;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE VolumeHandle, MountMgrHandle;
+ struct
+ {
+ MOUNTDEV_NAME;
+ WCHAR Buffer[MAX_PATH];
+ } MountDevName;
+
+ /* It makes no sense on a non-local drive */
+ if (GetDriveTypeW(lpszRootPath) == DRIVE_REMOTE)
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
+ }
+
+ /* Get the NT path */
+ if (!RtlDosPathNameToNtPathName_U(lpszRootPath, &NtPathName, NULL, NULL))
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
+ }
+
+ /* If it's a root path - likely - drop backslash to open volume */
+ if (NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 1] == L'\\')
+ {
+ NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 1] = UNICODE_NULL;
+ NtPathName.Length -= sizeof(WCHAR);
+ }
+
+ /* If that's a DOS volume, upper case the letter */
+ if (NtPathName.Length >= 2 * sizeof(WCHAR))
+ {
+ if (NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 1] == L':')
+ {
+ NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 2] =
_toupper(NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 2]);
+ }
+ }
+
+ /* Attempt to open the volume */
+ InitializeObjectAttributes(&ObjectAttributes, &NtPathName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ Status = NtOpenFile(&VolumeHandle, SYNCHRONIZE | FILE_READ_ATTRIBUTES,
+ &ObjectAttributes, &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ BaseSetLastNTError(Status);
+ return FALSE;
+ }
+
+ /* Query the device name - that's what we'll translate */
+ if (!DeviceIoControl(VolumeHandle, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL,
+ 0, &MountDevName, sizeof(MountDevName), &BytesReturned,
+ NULL))
+ {
+ NtClose(VolumeHandle);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ return FALSE;
+ }
+
+ /* No longer need the volume */
+ NtClose(VolumeHandle);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+
+ /* We'll keep the device name for later usage */
+ NtPathName.Length = MountDevName.NameLength;
+ NtPathName.MaximumLength = MountDevName.NameLength + sizeof(UNICODE_NULL);
+ NtPathName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
NtPathName.MaximumLength);
+ if (NtPathName.Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ RtlCopyMemory(NtPathName.Buffer, MountDevName.Name, NtPathName.Length);
+ NtPathName.Buffer[NtPathName.Length / sizeof(WCHAR)] = UNICODE_NULL;
+
+ /* Allocate the structure for querying the mount mgr */
+ MountPoint = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+ NtPathName.Length + sizeof(MOUNTMGR_MOUNT_POINT));
+ if (MountPoint == NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ /* 0 everything, we provide a device name */
+ RtlZeroMemory(MountPoint, sizeof(MOUNTMGR_MOUNT_POINT));
+ MountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
+ MountPoint->DeviceNameLength = NtPathName.Length;
+ RtlCopyMemory((PVOID)((ULONG_PTR)MountPoint + sizeof(MOUNTMGR_MOUNT_POINT)),
NtPathName.Buffer, NtPathName.Length);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+
+ /* Allocate a dummy output buffer to probe for size */
+ MountPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0,
sizeof(MOUNTMGR_MOUNT_POINTS));
+ if (MountPoints == NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ /* Open a handle to the mount manager */
+ MountMgrHandle = CreateFileW(MOUNTMGR_DOS_DEVICE_NAME, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ INVALID_HANDLE_VALUE);
+ if (MountMgrHandle == INVALID_HANDLE_VALUE)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
+ return FALSE;
+ }
+
+ /* Query the names associated to our device name */
+ Ret = DeviceIoControl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
+ MountPoint, NtPathName.Length + sizeof(MOUNTMGR_MOUNT_POINT),
+ MountPoints, sizeof(MOUNTMGR_MOUNT_POINTS),
&BytesReturned,
+ NULL);
+ /* As long as the buffer is too small, keep looping */
+ while (!Ret && GetLastError() == ERROR_MORE_DATA)
+ {
+ ULONG BufferSize;
+
+ /* Get the size we've to allocate */
+ BufferSize = MountPoints->Size;
+ /* Reallocate the buffer with enough room */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
+ MountPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
+ if (MountPoints == NULL)
+ {
+ CloseHandle(MountMgrHandle);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ /* Reissue the request, it should work now! */
+ Ret = DeviceIoControl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
+ MountPoint, NtPathName.Length +
sizeof(MOUNTMGR_MOUNT_POINT),
+ MountPoints, BufferSize, &BytesReturned, NULL);
+ }
+
+ /* We're done, no longer need the mount manager */
+ CloseHandle(MountMgrHandle);
+ /* Nor our input buffer */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
+
+ /* If the mount manager failed, just quit */
+ if (!Ret)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ CurrentMntPt = 0;
+ /* If there were no associated mount points, we'll return the device name */
+ if (MountPoints->NumberOfMountPoints == 0)
+ {
+ FoundVolume = NtPathName.Buffer;
+ FoundVolumeLen = NtPathName.Length;
+ }
+ /* Otherwise, find one which is matching */
+ else
+ {
+ for (; CurrentMntPt < MountPoints->NumberOfMountPoints; ++CurrentMntPt)
+ {
+ UNICODE_STRING SymbolicLink;
+
+ /* Make a string of it, to easy the checks */
+ SymbolicLink.Length =
MountPoints->MountPoints[CurrentMntPt].SymbolicLinkNameLength;
+ SymbolicLink.MaximumLength = SymbolicLink.Length;
+ SymbolicLink.Buffer =
(PVOID)((ULONG_PTR)&MountPoints->MountPoints[CurrentMntPt] +
MountPoints->MountPoints[CurrentMntPt].SymbolicLinkNameOffset);
+ /* If that's a NT volume name (GUID form), keep it! */
+ if (MOUNTMGR_IS_NT_VOLUME_NAME(&SymbolicLink))
+ {
+ FoundVolume = SymbolicLink.Buffer;
+ FoundVolumeLen = SymbolicLink.Length;
+
+ break;
+ }
+ }
+ }
+
+ /* We couldn't find anything matching, return an error */
+ if (CurrentMntPt == MountPoints->NumberOfMountPoints)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* We found a matching volume, have we enough memory to return it? */
+ if (cchBufferLength * sizeof(WCHAR) < FoundVolumeLen + 2 * sizeof(WCHAR))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ return FALSE;
+ }
+
+ /* Copy it back! */
+ RtlCopyMemory(lpszVolumeName, FoundVolume, FoundVolumeLen);
+ /* Make it compliant */
+ lpszVolumeName[1] = L'\\';
+ /* And transform it as root path */
+ lpszVolumeName[FoundVolumeLen / sizeof(WCHAR)] = L'\\';
+ lpszVolumeName[FoundVolumeLen / sizeof(WCHAR) + 1] = UNICODE_NULL;
+
+ /* We're done! */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
+ return TRUE;
+}
+
+/*
+ * @implemented
+ */
+static BOOL
+BasepGetVolumeNameFromReparsePoint(IN LPCWSTR lpszMountPoint,
+ OUT LPWSTR lpszVolumeName,
+ IN DWORD cchBufferLength,
+ OUT LPBOOL IsAMountPoint)
+{
+ WCHAR Old;
+ DWORD BytesReturned;
+ HANDLE ReparseHandle;
+ UNICODE_STRING SubstituteName;
+ PREPARSE_DATA_BUFFER ReparseBuffer;
+
+ /* Try to open the reparse point */
+ ReparseHandle = CreateFileW(lpszMountPoint, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS
| FILE_ATTRIBUTE_NORMAL,
+ INVALID_HANDLE_VALUE);
+ /* It failed! */
+ if (ReparseHandle == INVALID_HANDLE_VALUE)
+ {
+ /* Report it's not a mount point (it's not a reparse point) */
+ if (IsAMountPoint != NULL)
+ {
+ *IsAMountPoint = FALSE;
+ }
+
+ /* And zero output */
+ if (lpszVolumeName != NULL && cchBufferLength >= 1)
+ {
+ lpszVolumeName[0] = UNICODE_NULL;
+ }
+
+ return FALSE;
+ }
+
+ /* This is a mount point! */
+ if (IsAMountPoint != NULL)
+ {
+ *IsAMountPoint = TRUE;
+ }
+
+ /* Prepare a buffer big enough to read its data */
+ ReparseBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+ if (ReparseBuffer == NULL)
+ {
+ CloseHandle(ReparseHandle);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+ /* Zero output */
+ if (lpszVolumeName != NULL && cchBufferLength >= 1)
+ {
+ lpszVolumeName[0] = UNICODE_NULL;
+ }
+
+ return FALSE;
+ }
+
+ /* Dump the reparse point data */
+ if (!DeviceIoControl(ReparseHandle, FSCTL_GET_REPARSE_POINT, NULL, 0,
+ ReparseBuffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
&BytesReturned,
+ NULL))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseBuffer);
+ CloseHandle(ReparseHandle);
+
+ /* Zero output */
+ if (lpszVolumeName != NULL && cchBufferLength >= 1)
+ {
+ lpszVolumeName[0] = UNICODE_NULL;
+ }
+
+ return FALSE;
+ }
+
+ /* We no longer need the reparse point */
+ CloseHandle(ReparseHandle);
+
+ /* We only handle mount points */
+ if (ReparseBuffer->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseBuffer);
+
+ /* Zero output */
+ if (lpszVolumeName != NULL && cchBufferLength >= 1)
+ {
+ lpszVolumeName[0] = UNICODE_NULL;
+ }
+
+ return FALSE;
+ }
+
+ /* Do we have enough room for copying substitue name? */
+ if ((ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength +
sizeof(UNICODE_NULL)) > cchBufferLength * sizeof(WCHAR))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseBuffer);
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+
+ /* Zero output */
+ if (lpszVolumeName != NULL && cchBufferLength >= 1)
+ {
+ lpszVolumeName[0] = UNICODE_NULL;
+ }
+
+ return FALSE;
+ }
+
+ /* Copy the link target */
+ RtlCopyMemory(lpszVolumeName,
+
&ReparseBuffer->MountPointReparseBuffer.PathBuffer[ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset
/ sizeof(WCHAR)],
+ ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength);
+ /* Make it DOS valid */
+ Old = lpszVolumeName[1];
+ /* We want a root path */
+ lpszVolumeName[1] = L'\\';
+ /* And null terminate obviously */
+ lpszVolumeName[ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength /
sizeof(WCHAR)] = UNICODE_NULL;
+
+ /* Make it a string to easily check it */
+ SubstituteName.Length =
ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength;
+ SubstituteName.MaximumLength = SubstituteName.Length;
+ SubstituteName.Buffer = lpszVolumeName;
+
+ /* No longer need the data? */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseBuffer);
+
+ /* Is that a dos volume name with backslash? */
+ if (MOUNTMGR_IS_DOS_VOLUME_NAME_WB(&SubstituteName))
+ {
+ return TRUE;
+ }
+
+ /* No, so restore previous name and return to the caller */
+ lpszVolumeName[1] = Old;
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+BasepGetVolumeNameForVolumeMountPoint(IN LPCWSTR lpszMountPoint,
+ OUT LPWSTR lpszVolumeName,
+ IN DWORD cchBufferLength,
+ OUT LPBOOL IsAMountPoint)
+{
+ BOOL Ret;
+ UNICODE_STRING MountPoint;
+
+ /* Assume it's a mount point (likely for non reparse points) */
+ if (IsAMountPoint != NULL)
+ {
+ *IsAMountPoint = 1;
+ }
+
+ /* Make a string with the mount point name */
+ RtlInitUnicodeString(&MountPoint, lpszMountPoint);
+ /* Not a root path? */
+ if (MountPoint.Buffer[(MountPoint.Length / sizeof(WCHAR)) - 1] != L'\\')
+ {
+ BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);
+ /* Zero output */
+ if (lpszVolumeName != NULL && cchBufferLength >= 1)
+ {
+ lpszVolumeName[0] = UNICODE_NULL;
+ }
+
+ return FALSE;
+ }
+
+ /* Does it look like <letter>:\? */
+ if (MountPoint.Length == 3 * sizeof(WCHAR))
+ {
+ /* Try to get volume name for root path */
+ Ret = GetVolumeNameForRoot(lpszMountPoint, lpszVolumeName, cchBufferLength);
+ /* It failed? */
+ if (!Ret)
+ {
+ /* If wasn't a drive letter, so maybe a reparse point? */
+ if (MountPoint.Buffer[1] != ':')
+ {
+ Ret = BasepGetVolumeNameFromReparsePoint(lpszMountPoint, lpszVolumeName,
cchBufferLength, IsAMountPoint);
+ }
+ /* It was, so zero output */
+ else if (lpszVolumeName != NULL && cchBufferLength >= 1)
+ {
+ lpszVolumeName[0] = UNICODE_NULL;
+ }
+ }
+ }
+ else
+ {
+ /* Try to get volume name for root path */
+ Ret = GetVolumeNameForRoot(lpszMountPoint, lpszVolumeName, cchBufferLength);
+ /* It failed? */
+ if (!Ret)
+ {
+ /* It was a DOS volume as UNC name, so fail and zero output */
+ if (MountPoint.Length == 14 && MountPoint.Buffer[0] == '\\'
&& MountPoint.Buffer[1] == '\\' &&
+ (MountPoint.Buffer[2] == '.' || MountPoint.Buffer[2] ==
'?') && MountPoint.Buffer[3] == L'\\' &&
+ MountPoint.Buffer[5] == ':')
+ {
+ if (lpszVolumeName != NULL && cchBufferLength >= 1)
+ {
+ lpszVolumeName[0] = UNICODE_NULL;
+ }
+ }
+ /* Maybe it's a reparse point? */
+ else
+ {
+ Ret = BasepGetVolumeNameFromReparsePoint(lpszMountPoint, lpszVolumeName,
cchBufferLength, IsAMountPoint);
+ }
+ }
+ }
+
+ return Ret;
+}
/**
* @name GetVolumeNameForVolumeMountPointW
@@ -48,218 +491,21 @@
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))
- {
- if (Status == STATUS_BUFFER_OVERFLOW)
- {
- BufferLength = sizeof(MOUNTDEV_NAME) + MountDevName->NameLength;
- RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
- continue;
- }
- else
- {
- RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
- 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 Ret;
+
+ /* Just query our internal function */
+ Ret = BasepGetVolumeNameForVolumeMountPoint(VolumeMountPoint, VolumeName,
+ VolumeNameLength, NULL);
+ if (!Ret && VolumeName != NULL && VolumeNameLength >= 1)
+ {
+ VolumeName[0] = UNICODE_NULL;
+ }
+
+ return Ret;
+}
+
+/*
+ * @implemented
*/
BOOL
WINAPI
@@ -267,20 +513,60 @@
IN LPSTR lpszVolumeName,
IN 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;
+ BOOL Ret;
+ ANSI_STRING VolumeName;
+ UNICODE_STRING VolumeNameU;
+ PUNICODE_STRING VolumeMountPointU;
+
+ /* Convert mount point to unicode */
+ VolumeMountPointU = Basep8BitStringToStaticUnicodeString(lpszVolumeMountPoint);
+ if (VolumeMountPointU == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Initialize the strings we'll use for convention */
+ VolumeName.Buffer = lpszVolumeName;
+ VolumeName.Length = 0;
+ VolumeName.MaximumLength = cchBufferLength - 1;
+
+ VolumeNameU.Length = 0;
+ VolumeNameU.MaximumLength = (cchBufferLength - 1) * sizeof(WCHAR) +
sizeof(UNICODE_NULL);
+ /* Allocate a buffer big enough to contain the returned name */
+ VolumeNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
VolumeNameU.MaximumLength);
+ if (VolumeNameU.Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ /* Query -W */
+ Ret = GetVolumeNameForVolumeMountPointW(VolumeMountPointU->Buffer,
VolumeNameU.Buffer, cchBufferLength);
+ /* If it succeed, perform -A conversion */
+ if (Ret)
+ {
+ NTSTATUS Status;
+
+ /* Reinit our string for length */
+ RtlInitUnicodeString(&VolumeNameU, VolumeNameU.Buffer);
+ /* Convert to ANSI */
+ Status = RtlUnicodeStringToAnsiString(&VolumeName, &VolumeNameU, FALSE);
+ /* If conversion failed, force failure, otherwise, just null terminate */
+ if (!NT_SUCCESS(Status))
+ {
+ Ret = FALSE;
+ BaseSetLastNTError(Status);
+ }
+ else
+ {
+ VolumeName.Buffer[VolumeName.Length] = ANSI_NULL;
+ }
+ }
+
+ /* Internal buffer no longer needed */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameU.Buffer);
+
+ return Ret;
}
/*