Author: pschweitzer
Date: Mon Sep 25 21:33:56 2017
New Revision: 75967
URL:
http://svn.reactos.org/svn/reactos?rev=75967&view=rev
Log:
[KERNEL32]
- Implement IsThisARootDirectory()
- Reimplement GetVolumeInformationW() to make it w2k3 compliant.
This fixes a few winetests and makes fsutil fsinfo ntfsinfo work in ROS :-)
Modified:
trunk/reactos/dll/win32/kernel32/client/file/volume.c
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] Mon Sep 25 21:33:56
2017
@@ -7,6 +7,7 @@
* Erik Bos, Alexandre Julliard :
* GetLogicalDriveStringsA,
* GetLogicalDriveStringsW, GetLogicalDrives
+ * Pierre Schweitzer (pierre(a)reactos.org)
* UPDATE HISTORY:
* Created 01/11/98
*/
@@ -204,9 +205,76 @@
return Result;
}
-#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))
+/*
+ * @implemented
+ */
+static BOOL
+IsThisARootDirectory(IN HANDLE VolumeHandle,
+ IN PUNICODE_STRING NtPathName)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ struct
+ {
+ FILE_NAME_INFORMATION;
+ WCHAR Buffer[MAX_PATH];
+ } FileNameInfo;
+
+ /* If we have a handle, query the name */
+ if (VolumeHandle)
+ {
+ 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;
+ }
+ }
+
+ /* If we have a path */
+ if (NtPathName != NULL)
+ {
+ HANDLE LinkHandle;
+ WCHAR Buffer[512];
+ ULONG ReturnedLength;
+ UNICODE_STRING LinkTarget;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+
+ NtPathName->Length -= sizeof(WCHAR);
+
+ 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;
+ }
+
+ /* If so, query the target */
+ LinkTarget.Buffer = Buffer;
+ LinkTarget.Length = 0;
+ LinkTarget.MaximumLength = sizeof(Buffer);
+
+ Status = NtQuerySymbolicLinkObject(LinkHandle, &LinkTarget,
&ReturnedLength);
+ NtClose(LinkHandle);
+ /* A root directory (NtName) is a symbolic link */
+ if (!NT_SUCCESS(Status))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
/*
* @implemented
@@ -222,104 +290,223 @@
OUT LPWSTR lpFileSystemNameBuffer OPTIONAL,
IN 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)
- {
- return FALSE;
- }
-
- TRACE("hFile: %p\n", hFile);
- errCode = NtQueryVolumeInformationFile(hFile,
- &IoStatusBlock,
- FileFsVolume,
- FS_VOLUME_BUFFER_SIZE,
- FileFsVolumeInformation);
- if ( !NT_SUCCESS(errCode) )
- {
- WARN("Status: %x\n", errCode);
- CloseHandle(hFile);
- BaseSetLastNTError (errCode);
- return FALSE;
- }
-
- if (lpVolumeSerialNumber)
- *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
-
- 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;
- }
- }
-
- errCode = NtQueryVolumeInformationFile (hFile,
- &IoStatusBlock,
- FileFsAttribute,
- FS_ATTRIBUTE_BUFFER_SIZE,
- FileFsAttributeInformation);
- CloseHandle(hFile);
- if (!NT_SUCCESS(errCode))
- {
- WARN("Status: %x\n", errCode);
- BaseSetLastNTError (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;
- }
- else
- {
- SetLastError(ERROR_MORE_DATA);
- return FALSE;
- }
- }
- return TRUE;
+ 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 no root path provided, default to \ */
+ if (lpRootPathName == NULL)
+ {
+ RootPathName = L"\\";
+ }
+ else
+ {
+ RootPathName = lpRootPathName;
+ }
+
+ /* Convert to NT name */
+ if (!RtlDosPathNameToNtPathName_U(RootPathName, &NtPathName, NULL, NULL))
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
+ }
+
+ /* Check we really end with a backslash */
+ if (NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 1] != L'\\')
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);
+ return FALSE;
+ }
+
+ /* 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))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ BaseSetLastNTError(Status);
+ return FALSE;
+ }
+
+ /* Check whether that's a root directory */
+ if (!IsThisARootDirectory(VolumeHandle, &NtPathName))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+ NtClose(VolumeHandle);
+ SetLastError(ERROR_DIR_NOT_ROOT);
+ return FALSE;
+ }
+
+ 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)
+ {
+ VolumeInfoSize = nVolumeNameSize + sizeof(FILE_FS_VOLUME_INFORMATION);
+ }
+ /* If user just wants the serial number, allocate a dummy buffer */
+ else if (lpVolumeSerialNumber != NULL)
+ {
+ VolumeInfoSize = MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION);
+ }
+ /* Otherwise, nothing to query */
+ else
+ {
+ VolumeInfoSize = 0;
+ }
+
+ /* If we're to query, allocate a big enough buffer */
+ if (VolumeInfoSize != 0)
+ {
+ VolumeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeInfoSize);
+ if (VolumeInfo == NULL)
+ {
+ NtClose(VolumeHandle);
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ return FALSE;
+ }
+ }
+
+ /* 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
+ {
+ VolumeAttrSize = 0;
+ }
+
+ /* If we're to query, allocate a big enough buffer */
+ if (VolumeAttrSize != 0)
+ {
+ VolumeAttr = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeAttrSize);
+ if (VolumeAttr == NULL)
+ {
+ if (VolumeInfo != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
+ }
+
+ NtClose(VolumeHandle);
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ return FALSE;
+ }
+ }
+
+ /* Assume we'll fail */
+ Ret = FALSE;
+
+ /* If we're to query FileFsVolumeInformation, do it now! */
+ if (VolumeInfo != NULL)
+ {
+ Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock,
VolumeInfo, VolumeInfoSize, FileFsVolumeInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ goto CleanAndQuit;
+ }
+ }
+
+ /* If we're to query FileFsAttributeInformation, do it now! */
+ if (VolumeAttr != NULL)
+ {
+ Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock,
VolumeAttr, VolumeAttrSize, FileFsAttributeInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ goto CleanAndQuit;
+ }
+ }
+
+ /* If user wants volume name */
+ if (lpVolumeNameBuffer != NULL)
+ {
+ /* 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;
+ }
+
+ /* If user wants wants serial number, return it */
+ if (lpVolumeSerialNumber != NULL)
+ {
+ *lpVolumeSerialNumber = VolumeInfo->VolumeSerialNumber;
+ }
+
+ /* 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;
+ }
+
+ /* Copy and zero */
+ RtlCopyMemory(lpFileSystemNameBuffer, VolumeAttr->FileSystemName,
VolumeAttr->FileSystemNameLength);
+ lpFileSystemNameBuffer[VolumeAttr->FileSystemNameLength / sizeof(WCHAR)] =
UNICODE_NULL;
+ }
+
+ /* If user wants wants max compo len, return it */
+ if (lpMaximumComponentLength != NULL)
+ {
+ *lpMaximumComponentLength = VolumeAttr->MaximumComponentNameLength;
+ }
+
+ /* If user wants wants FS flags, return them */
+ if (lpFileSystemFlags != NULL)
+ {
+ *lpFileSystemFlags = VolumeAttr->FileSystemAttributes;
+ }
+
+ /* We did it! */
+ Ret = TRUE;
+
+CleanAndQuit:
+ NtClose(VolumeHandle);
+
+ if (VolumeInfo != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
+ }
+
+ if (VolumeAttr != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeAttr);
+ }
+
+ return Ret;
}
/*