ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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;

    /* Get relative name */
    if (!RtlDosPathNameToRelativeNtPathName_U(lpPathName, &NtPathU, NULL, &RelativeName))
    {
        SetLastError(ERROR_PATH_NOT_FOUND);
        return FALSE;
    }

    /* Save buffer to allow later freeing */
    PathUBuffer = NtPathU.Buffer;

    /* If we have relative name (and root dir), use them instead */
    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);

    /* Try to open directory */
    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))
    {
        /* We only accept failure for reparse points not being supported */
        if (Status != STATUS_INVALID_PARAMETER)
        {
            goto Cleanup;
        }

        /* Try to open, with reparse points support */
        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;
        }

        /* Success, mark directory */
        goto MarkFileForDelete;
    }

    /* Get information about file (and reparse point) */
    Status = NtQueryInformationFile(DirectoryHandle,
                                    &IoStatusBlock,
                                    &FileTagInfo,
                                    sizeof(FileTagInfo),
                                    FileAttributeTagInformation);
    if (!NT_SUCCESS(Status))
    {
        /* FSD might not support querying reparse points information */
        if (Status != STATUS_NOT_IMPLEMENTED &&
            Status != STATUS_INVALID_PARAMETER)
        {
            goto CleanupHandle;
        }

        /* If that's the case, then just delete directory */
        goto MarkFileForDelete;
    }

    /* If that's not a reparse point, nothing more to do than just delete */
    if (!(FileTagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
    {
        goto MarkFileForDelete;
    }

    /* Check if that's a mount point */
    if (FileTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
    {
        /* It's not */
        NtClose(DirectoryHandle);

        /* So, try to reopen directory, ignoring mount point */
        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))
        {
            /* It succeed, we can safely delete directory (and ignore reparse point) */
            goto MarkFileForDelete;
        }

        /* If it failed, only allow case where IO mount point was ignored */
        if (Status != STATUS_IO_REPARSE_TAG_NOT_HANDLED)
        {
            goto Cleanup;
        }

        /* Reopen with reparse point support */
        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))
        {
            /* And mark for delete */
            goto MarkFileForDelete;
        }

        goto Cleanup;
    }

    /* Here, we have a mount point, prepare to query information about it */
    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;
    }

    /* Query */
    if (!DeviceIoControl(DirectoryHandle,
                         FSCTL_GET_REPARSE_POINT,
                         NULL, 0,
                         ReparseDataBuffer,
                         MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
                         &BytesReturned,
                         NULL))
    {
        RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
        goto MarkFileForDelete;
    }

    /* Get volume name */
    SubstituteName = (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
                             ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
    if (!IS_VOLUME_NAME(SubstituteName, ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength))
    {
        /* This is not a volume, we can safely delete */
        RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
        goto MarkFileForDelete;
    }

    /* Prepare to delete mount point */
    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;
    }

    /* Delete mount point for that volume */
    DeleteVolumeMountPointW(PathName.Buffer);
    RtlFreeHeap(RtlGetProcessHeap(), 0, PathName.Buffer);
    RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);

    /* And mark directory for delete */
MarkFileForDelete:
    RtlReleaseRelativeName(&RelativeName);
    RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);

    /* Mark & set */
    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;
}

Generated on Sun May 27 2012 04:45:48 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.