U0 DirContextDel(CDirContext *dirc, Bool restore=TRUE)
{//Change back to old cur_dir and drv.
    CBlkDev *bd;

    if (!dirc)
        return;
    if (restore)
    {
        bd = dirc->old_dv->bd;
        if (!(bd->flags & BDF_INIT_IN_PROGRESS))
        {
            if (dirc->old_dir)
            {
                Drive(Drive2Letter(dirc->old_dv));
                Cd(dirc->old_dir);
            }
        }
        else
        {
            Fs->cur_dv = dirc->old_dv;
            Free(Fs->cur_dir);
            Fs->cur_dir = StrNew("/");
        }
    }
    Free(dirc->old_dir);
    Free(dirc->mask);
    Free(dirc);
}

CDirContext *DirContextNew(U8 *_mask, Bool make_mask=FALSE, Bool make_dirs=FALSE, Bool no_mask=FALSE)
{//Save cur_dir and drv. Change to new dir.
    Bool         valid = TRUE, old_silent;
    I64          mask_len = StrLen(_mask);
    U8          *buf, *mask, *tmp_mask, *semicolon_mask;
    CDirContext *dirc = CAlloc(sizeof(CDirContext));

    dirc->old_dir = StrNew(Fs->cur_dir);
    dirc->old_dv  = Fs->cur_dv;
    mask = MStrUtil(_mask, SUF_REM_LEADING | SUF_REM_TRAILING | SUF_REM_CTRL_CHARS);
    tmp_mask = mask;
    if (*mask && mask[1] == ':')
    {
        if (Fs->cur_dv != Letter2Drive(*mask) && !Drive(*mask))
            valid = FALSE;
        mask += 2;
    }
    if (*mask == '~' && Fs->cur_dv != Letter2Drive('~') && !Drive('~'))
        valid = FALSE;
    dirc->drive = Fs->cur_dv;
    DriveCheck(dirc->drive);
    buf = MAlloc(mask_len + 2);
    StrCopy(buf, mask);

    dirc->mask = MAlloc(mask_len + 2);
    if (no_mask)
        *dirc->mask = 0;
    else if (StrOcc(buf, ';'))
    {
        semicolon_mask = MAlloc(mask_len + 2);
        StrCopy(semicolon_mask, mask);
        StrFirstRemove(semicolon_mask, ";", buf);
        StrLastRemove(buf, "/", dirc->mask);
        CatPrint(dirc->mask, ";%s", semicolon_mask);
        Free(semicolon_mask);
    }
    else
        StrLastRemove(buf, "/", dirc->mask);

    if (*mask == '/' && !*buf)
        StrCopy(buf, "/");
//If began with Dir, change to Dir.
    if (*buf && !Cd(buf, make_dirs))
        valid = FALSE;
    if (valid && make_mask)
    {
        if (!*dirc->mask)
        {
            Free(dirc->mask);
            dirc->mask = StrNew("*");
        }
        else
        {
            if (!make_dirs || FileNameCheck(dirc->mask))
            {
                old_silent = Silent;
//Try mask to see if Dir. If Dir, change to dir and set to "*".
                if (Cd(dirc->mask, make_dirs))
                {
                    Free(dirc->mask);
                    dirc->mask = StrNew("*");
                }
                Silent(old_silent);
            }
        }
    }
    Free(buf);
    Free(tmp_mask);
    if (!valid)
    {
        DirContextDel(dirc);
        dirc = NULL;
    }
    return dirc;
}