From 92bc7bdab5ae49a045ed73799bfa41dc23f83997 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Wed, 27 Sep 2017 17:43:52 +0000 Subject: [PATCH] [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() svn path=/trunk/; revision=75978 --- reactos/dll/win32/kernel32/client/file/disk.c | 48 ++- .../dll/win32/kernel32/client/file/volume.c | 398 ++++++++++++------ 2 files changed, 321 insertions(+), 125 deletions(-) diff --git a/reactos/dll/win32/kernel32/client/file/disk.c b/reactos/dll/win32/kernel32/client/file/disk.c index 2c5e4f77f37..fd97a0e3a8c 100644 --- a/reactos/dll/win32/kernel32/client/file/disk.c +++ b/reactos/dll/win32/kernel32/client/file/disk.c @@ -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 diff --git a/reactos/dll/win32/kernel32/client/file/volume.c b/reactos/dll/win32/kernel32/client/file/volume.c index 847caf1d237..7157f0fcf69 100644 --- a/reactos/dll/win32/kernel32/client/file/volume.c +++ b/reactos/dll/win32/kernel32/client/file/volume.c @@ -22,54 +22,7 @@ #include #define NDEBUG #include -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 @@ WINAPI 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 @@ WINAPI 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); + 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; - } - - 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; + } + + /* 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 @@ FindNextVolumeW(IN HANDLE handle, } /* - * @unimplemented + * @implemented */ BOOL WINAPI @@ -900,8 +955,103 @@ GetVolumePathNamesForVolumeNameA(IN LPCSTR lpszVolumeName, 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; } -- 2.17.1