Коммит d2669dc0 создал по автору Pierre Schweitzer's avatar Pierre Schweitzer
Просмотр файлов

[KERNEL32]

- Implement IsThisARootDirectory()
- Reimplement GetVolumeInformationW() to make it w2k3 compliant.
This fixes a few winetests and makes fsutil fsinfo ntfsinfo work in ROS :-)

svn path=/trunk/; revision=75967
владелец 282de8ae
......@@ -7,6 +7,7 @@
* Erik Bos, Alexandre Julliard :
* GetLogicalDriveStringsA,
* GetLogicalDriveStringsW, GetLogicalDrives
* Pierre Schweitzer (pierre@reactos.org)
* UPDATE HISTORY:
* Created 01/11/98
*/
......@@ -204,9 +205,76 @@ FailNoMem:
return Result;
}
#define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_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;
}
#define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
/* 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 @@ GetVolumeInformationW(IN LPCWSTR lpRootPathName,
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)
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)
{
return FALSE;
RootPathName = L"\\";
}
else
{
RootPathName = lpRootPathName;
}
TRACE("hFile: %p\n", hFile);
errCode = NtQueryVolumeInformationFile(hFile,
&IoStatusBlock,
FileFsVolume,
FS_VOLUME_BUFFER_SIZE,
FileFsVolumeInformation);
if ( !NT_SUCCESS(errCode) )
/* Convert to NT name */
if (!RtlDosPathNameToNtPathName_U(RootPathName, &NtPathName, NULL, NULL))
{
WARN("Status: %x\n", errCode);
CloseHandle(hFile);
BaseSetLastNTError (errCode);
return FALSE;
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
if (lpVolumeSerialNumber)
*lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
/* 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;
}
if (lpVolumeNameBuffer)
/* 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)
{
if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR))
VolumeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeInfoSize);
if (VolumeInfo == NULL)
{
memcpy(lpVolumeNameBuffer,
FileFsVolume->VolumeLabel,
FileFsVolume->VolumeLabelLength);
lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0;
}
else
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)
{
CloseHandle(hFile);
SetLastError(ERROR_MORE_DATA);
return FALSE;
}
if (VolumeInfo != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
}
NtClose(VolumeHandle);
BaseSetLastNTError(STATUS_NO_MEMORY);
return FALSE;
}
}
errCode = NtQueryVolumeInformationFile (hFile,
&IoStatusBlock,
FileFsAttribute,
FS_ATTRIBUTE_BUFFER_SIZE,
FileFsAttributeInformation);
CloseHandle(hFile);
if (!NT_SUCCESS(errCode))
/* Assume we'll fail */
Ret = FALSE;
/* If we're to query FileFsVolumeInformation, do it now! */
if (VolumeInfo != NULL)
{
WARN("Status: %x\n", errCode);
BaseSetLastNTError (errCode);
return FALSE;
Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, VolumeInfo, VolumeInfoSize, FileFsVolumeInformation);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
goto CleanAndQuit;
}
}
if (lpFileSystemFlags)
*lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
if (lpMaximumComponentLength)
*lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
if (lpFileSystemNameBuffer)
/* If we're to query FileFsAttributeInformation, do it now! */
if (VolumeAttr != NULL)
{
if (nFileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, VolumeAttr, VolumeAttrSize, FileFsAttributeInformation);
if (!NT_SUCCESS(Status))
{
memcpy(lpFileSystemNameBuffer,
FileFsAttribute->FileSystemName,
FileFsAttribute->FileSystemNameLength);
lpFileSystemNameBuffer[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0;
}
else
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_MORE_DATA);
return FALSE;
}
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;
}
return TRUE;
/* 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;
}
/*
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать