|
|
Definition at line 760 of file dir.c.
Referenced by cache_UninstallAssembly(), DeleteItemW(), DELNODE_recurse_dirtree(), free_assembly(), IAssemblyCacheImpl_UninstallAssembly(), IntDeleteRecursive(), ITERATE_RemoveFiles(), ITERATE_UnpublishIcon(), MoveFileWithProgressW(), pendingRename(), RecursiveRemoveDir(), remove_folder(), remove_persistent_folder(), RemoveDirectoryA(), RemoveDirectoryPath(), SHNotifyRemoveDirectoryW(), and uninstall_assembly().
{
NTSTATUS Status;
DWORD BytesReturned;
HANDLE DirectoryHandle;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING NtPathU, PathName;
RTL_RELATIVE_NAME_U RelativeName;
PWSTR PathUBuffer, SubstituteName;
OBJECT_ATTRIBUTES ObjectAttributes;
PREPARSE_DATA_BUFFER ReparseDataBuffer;
FILE_DISPOSITION_INFORMATION FileDispInfo;
FILE_ATTRIBUTE_TAG_INFORMATION FileTagInfo;
if (!RtlDosPathNameToRelativeNtPathName_U(lpPathName, &NtPathU, NULL, &RelativeName))
{
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
PathUBuffer = NtPathU.Buffer;
if (RelativeName.RelativeName.Length != 0)
{
NtPathU.Length = RelativeName.RelativeName.Length;
NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
NtPathU.Buffer = RelativeName.RelativeName.Buffer;
}
else
{
RelativeName.ContainingDirectory = NULL;
}
InitializeObjectAttributes(&ObjectAttributes,
&NtPathU,
OBJ_CASE_INSENSITIVE,
RelativeName.ContainingDirectory,
NULL);
Status = NtOpenFile(&DirectoryHandle,
DELETE | SYNCHRONIZE | FAILED_ACCESS_ACE_FLAG,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
if (!NT_SUCCESS(Status))
{
if (Status != STATUS_INVALID_PARAMETER)
{
goto Cleanup;
}
Status = NtOpenFile(&DirectoryHandle,
DELETE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
goto MarkFileForDelete;
}
Status = NtQueryInformationFile(DirectoryHandle,
&IoStatusBlock,
&FileTagInfo,
sizeof(FileTagInfo),
FileAttributeTagInformation);
if (!NT_SUCCESS(Status))
{
if (Status != STATUS_NOT_IMPLEMENTED &&
Status != STATUS_INVALID_PARAMETER)
{
goto CleanupHandle;
}
goto MarkFileForDelete;
}
if (!(FileTagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
{
goto MarkFileForDelete;
}
if (FileTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
{
NtClose(DirectoryHandle);
Status = NtOpenFile(&DirectoryHandle,
DELETE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
FILE_OPEN_FOR_BACKUP_INTENT);
if (NT_SUCCESS(Status))
{
goto MarkFileForDelete;
}
if (Status != STATUS_IO_REPARSE_TAG_NOT_HANDLED)
{
goto Cleanup;
}
Status = NtOpenFile(&DirectoryHandle,
DELETE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
if (NT_SUCCESS(Status))
{
goto MarkFileForDelete;
}
goto Cleanup;
}
ReparseDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
if (!ReparseDataBuffer)
{
RtlReleaseRelativeName(&RelativeName);
RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
NtClose(DirectoryHandle);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
if (!DeviceIoControl(DirectoryHandle,
FSCTL_GET_REPARSE_POINT,
NULL, 0,
ReparseDataBuffer,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
&BytesReturned,
NULL))
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
goto MarkFileForDelete;
}
SubstituteName = (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
if (!IS_VOLUME_NAME(SubstituteName, ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength))
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
goto MarkFileForDelete;
}
RtlInitUnicodeString(&PathName, lpPathName);
PathName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathName.Length + 2 * sizeof(WCHAR));
if (!PathName.Buffer)
{
RtlReleaseRelativeName(&RelativeName);
RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
NtClose(DirectoryHandle);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
RtlCopyMemory(&PathName.Buffer, lpPathName, PathName.Length);
if (PathName.Buffer[PathName.Length / sizeof(WCHAR)] != L'\\')
{
PathName.Buffer[PathName.Length / sizeof(WCHAR)] = L'\\';
PathName.Buffer[(PathName.Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
}
DeleteVolumeMountPointW(PathName.Buffer);
RtlFreeHeap(RtlGetProcessHeap(), 0, PathName.Buffer);
RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
MarkFileForDelete:
RtlReleaseRelativeName(&RelativeName);
RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
FileDispInfo.DeleteFile = TRUE;
Status = NtSetInformationFile(DirectoryHandle,
&IoStatusBlock,
&FileDispInfo,
sizeof(FILE_DISPOSITION_INFORMATION),
FileDispositionInformation);
NtClose(DirectoryHandle);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
CleanupHandle:
NtClose(DirectoryHandle);
Cleanup:
RtlReleaseRelativeName(&RelativeName);
RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
BaseSetLastNTError(Status);
return FALSE;
}
|