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;
}