Author: pschweitzer
Date: Wed Sep 27 17:43:52 2017
New Revision: 75978
URL:
http://svn.reactos.org/svn/reactos?rev=75978&view=rev
Log:
[KERNEL32]
- Move InternalOpenDirW() to disk.c; that's the last place where it's used
- Implement GetVolumePathNamesForVolumeNameA(); its -W implementation is still to be
implemented
- W2K3ify SetVolumeLabelW() and SetVolumeLabelA()
Modified:
trunk/reactos/dll/win32/kernel32/client/file/disk.c
trunk/reactos/dll/win32/kernel32/client/file/volume.c
Modified: trunk/reactos/dll/win32/kernel32/client/file/disk.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/file/disk.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/file/disk.c [iso-8859-1] Wed Sep 27 17:43:52
2017
@@ -26,7 +26,53 @@
DEBUG_CHANNEL(kernel32file);
#define MAX_DOS_DRIVES 26
-HANDLE WINAPI InternalOpenDirW(IN LPCWSTR DirName, IN 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))
+ {
+ 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);
+
+ if (!NT_SUCCESS(errCode))
+ {
+ BaseSetLastNTError(errCode);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ return hFile;
+}
/*
* @implemented
Modified: trunk/reactos/dll/win32/kernel32/client/file/volume.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/file/volume.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/file/volume.c [iso-8859-1] Wed Sep 27 17:43:52
2017
@@ -22,54 +22,7 @@
#include <k32.h>
#define NDEBUG
#include <debug.h>
-DEBUG_CHANNEL(kernel32file);
-
-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))
- {
- 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);
-
- if (!NT_SUCCESS(errCode))
- {
- BaseSetLastNTError(errCode);
- return INVALID_HANDLE_VALUE;
- }
-
- return hFile;
-}
+
/*
* @implemented
@@ -506,30 +459,36 @@
SetVolumeLabelA(IN LPCSTR lpRootPathName,
IN LPCSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
{
- PWCHAR RootPathNameW;
- PWCHAR VolumeNameW = NULL;
- BOOL Result;
-
- if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
- return FALSE;
-
- if (lpVolumeName)
- {
- if (!(VolumeNameW = FilenameA2W(lpVolumeName, TRUE)))
- return FALSE;
- }
-
- Result = SetVolumeLabelW (RootPathNameW,
- VolumeNameW);
-
- if (VolumeNameW)
- {
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- VolumeNameW );
- }
-
- return Result;
+ BOOL Ret;
+ UNICODE_STRING VolumeNameU;
+ PUNICODE_STRING RootPathNameU;
+
+ if (lpRootPathName == NULL)
+ {
+ lpRootPathName = "\\";
+ }
+
+ RootPathNameU = Basep8BitStringToStaticUnicodeString(lpRootPathName);
+ if (RootPathNameU == NULL)
+ {
+ return FALSE;
+ }
+
+ if (lpVolumeName != NULL)
+ {
+ if (!Basep8BitStringToDynamicUnicodeString(&VolumeNameU, lpVolumeName))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ VolumeNameU.Buffer = NULL;
+ }
+
+ Ret = SetVolumeLabelW(RootPathNameU->Buffer, VolumeNameU.Buffer);
+ RtlFreeUnicodeString(&VolumeNameU);
+ return Ret;
}
/*
@@ -540,57 +499,153 @@
SetVolumeLabelW(IN LPCWSTR lpRootPathName,
IN LPCWSTR lpVolumeName OPTIONAL) /* 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;
- 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))
- {
- WARN("Status: %x\n", Status);
- CloseHandle(hFile);
- BaseSetLastNTError(Status);
- return FALSE;
- }
-
- CloseHandle(hFile);
- return TRUE;
+ BOOL Ret;
+ NTSTATUS Status;
+ PWSTR VolumeRoot;
+ HANDLE VolumeHandle;
+ WCHAR VolumeGuid[MAX_PATH];
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PFILE_FS_LABEL_INFORMATION FsLabelInfo;
+ UNICODE_STRING VolumeName, NtVolumeName;
+
+ /* If no root path provided, default to \ */
+ VolumeRoot = L"\\";
+
+ /* If user wants to set a label, make it a string */
+ if (lpVolumeName != NULL)
+ {
+ RtlInitUnicodeString(&VolumeName, lpVolumeName);
+ }
+ else
+ {
+ VolumeName.Length = 0;
+ VolumeName.MaximumLength = 0;
+ VolumeName.Buffer = NULL;
+ }
+
+ /* If we received a volume, try to get its GUID name */
+ if (lpRootPathName != NULL)
+ {
+ Ret = GetVolumeNameForVolumeMountPointW(lpRootPathName, VolumeGuid, MAX_PATH);
+ }
+ else
+ {
+ Ret = FALSE;
+ }
+
+ /* If we got the GUID name, use it */
+ if (Ret)
+ {
+ VolumeRoot = VolumeGuid;
+ }
+ else
+ {
+ /* Otherwise, use the name provided by the caller */
+ if (lpRootPathName != NULL)
+ {
+ VolumeRoot = (PWSTR)lpRootPathName;
+ }
+ }
+
+ /* Convert to a NT path */
+ if (!RtlDosPathNameToNtPathName_U(VolumeRoot, &NtVolumeName, NULL, NULL))
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
+ }
+
+
+ /* Check we really end with a backslash */
+ if (NtVolumeName.Buffer[(NtVolumeName.Length / sizeof(WCHAR)) - 1] != L'\\')
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
+ BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);
+ return FALSE;
+ }
+
+ /* Try to open the root directory */
+ InitializeObjectAttributes(&ObjectAttributes, &NtVolumeName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ Status = NtOpenFile(&VolumeHandle, SYNCHRONIZE | FILE_WRITE_DATA,
+ &ObjectAttributes, &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
+ BaseSetLastNTError(Status);
+ return FALSE;
+ }
+
+ /* Validate it's really a root path */
+ if (!IsThisARootDirectory(VolumeHandle, NULL))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
+ NtClose(VolumeHandle);
+ SetLastError(ERROR_DIR_NOT_ROOT);
+ return FALSE;
+ }
+
+ /* Done */
+ NtClose(VolumeHandle);
+
+ /* Now, open the volume to perform the label change */
+ NtVolumeName.Length -= sizeof(WCHAR);
+ InitializeObjectAttributes(&ObjectAttributes, &NtVolumeName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ Status = NtOpenFile(&VolumeHandle, SYNCHRONIZE | FILE_WRITE_DATA,
+ &ObjectAttributes, &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
+
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ return FALSE;
+ }
+
+ /* Assume success */
+ Ret = TRUE;
+
+ /* Allocate a buffer that can hold new label and its size */
+ FsLabelInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0,
sizeof(FILE_FS_LABEL_INFORMATION) + VolumeName.Length);
+ if (FsLabelInfo != NULL)
+ {
+ /* Copy name and set its size */
+ RtlCopyMemory(FsLabelInfo->VolumeLabel, VolumeName.Buffer,
VolumeName.Length);
+ FsLabelInfo->VolumeLabelLength = VolumeName.Length;
+
+ /* And finally, set new label */
+ Status = NtSetVolumeInformationFile(VolumeHandle, &IoStatusBlock,
FsLabelInfo, sizeof(FILE_FS_LABEL_INFORMATION) + VolumeName.Length,
FileFsLabelInformation);
+ }
+ else
+ {
+ /* Allocation failed */
+ Status = STATUS_NO_MEMORY;
+ }
+
+ /* In case of failure, set status and mark failure */
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ Ret = FALSE;
+ }
+
+ /* We're done */
+ NtClose(VolumeHandle);
+
+ /* Free buffer if required */
+ if (FsLabelInfo != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FsLabelInfo);
+ }
+
+ return Ret;
}
/*
@@ -891,7 +946,7 @@
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
WINAPI
@@ -900,8 +955,103 @@
IN DWORD cchBufferLength,
OUT PDWORD lpcchReturnLength)
{
- STUB;
- return 0;
+ BOOL Ret;
+ NTSTATUS Status;
+ DWORD cchReturnLength;
+ ANSI_STRING VolumePathName;
+ PUNICODE_STRING VolumeNameU;
+ UNICODE_STRING VolumePathNamesU;
+
+ /* Convert volume name to unicode */
+ VolumeNameU = Basep8BitStringToStaticUnicodeString(lpszVolumeName);
+ if (VolumeNameU == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Initialize the strings we'll use later on */
+ VolumePathName.Length = 0;
+ VolumePathName.MaximumLength = cchBufferLength;
+ VolumePathName.Buffer = lpszVolumePathNames;
+
+ VolumePathNamesU.Length = 0;
+ VolumePathNamesU.MaximumLength = sizeof(WCHAR) * cchBufferLength;
+ /* If caller provided a non 0 sized string, allocate a buffer for our unicode string
*/
+ if (VolumePathNamesU.MaximumLength != 0)
+ {
+ VolumePathNamesU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
VolumePathNamesU.MaximumLength);
+ if (VolumePathNamesU.Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ }
+ else
+ {
+ VolumePathNamesU.Buffer = NULL;
+ }
+
+ /* Call the -W implementation */
+ Ret = GetVolumePathNamesForVolumeNameW(VolumeNameU->Buffer,
VolumePathNamesU.Buffer,
+ cchBufferLength, &cchReturnLength);
+ /* Call succeed, we'll return the total length */
+ if (Ret)
+ {
+ VolumePathNamesU.Length = sizeof(WCHAR) * cchReturnLength;
+ }
+ else
+ {
+ /* Else, if we fail for anything else than too small buffer, quit */
+ if (GetLastError() != ERROR_MORE_DATA)
+ {
+ if (VolumePathNamesU.Buffer != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
+ }
+
+ return FALSE;
+ }
+
+ /* Otherwise, we'll just copy as much as we can */
+ VolumePathNamesU.Length = sizeof(WCHAR) * cchBufferLength;
+ }
+
+ /* Convert our output string back to ANSI */
+ Status = RtlUnicodeStringToAnsiString(&VolumePathName, &VolumePathNamesU,
FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+
+ if (VolumePathNamesU.Buffer != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
+ }
+
+ return FALSE;
+ }
+
+ /* If caller wants return length, two cases... */
+ if (lpcchReturnLength != NULL)
+ {
+ /* We succeed: return the copied length */
+ if (Ret)
+ {
+ *lpcchReturnLength = VolumePathName.Length;
+ }
+ /* We failed, return the size we would have loved having! */
+ else
+ {
+ *lpcchReturnLength = sizeof(WCHAR) * cchReturnLength;
+ }
+ }
+
+ /* Release our buffer if allocated */
+ if (VolumePathNamesU.Buffer != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
+ }
+
+ return Ret;
}