Changeset 2015


Ignore:
Timestamp:
5/2/2010 10:51:06 AM (4 years ago)
Author:
lowjoel
Message:

Implemented a confirmation dialog before erasures are processed. Fixes #340.

Location:
trunk/eraser
Files:
3 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/eraser/Eraser.Shell/CtxMenu.cpp

    r2006 r2015  
    491491 
    492492        //Build the command line 
    493         std::wstring commandAction; 
    494493        std::wstring commandLine; 
    495494        bool commandElevate = false; 
    496         HRESULT result = E_INVALIDARG; 
    497495        switch (VerbMenuIndices[LOWORD(pCmdInfo->lpVerb)]) 
    498496        { 
    499497        case ACTION_ERASE_ON_RESTART: 
    500             commandLine += L"/schedule=restart "; 
    501  
    502498        case ACTION_ERASE: 
    503             { 
    504                 //Add Task command. 
    505                 commandAction = L"addtask"; 
    506  
    507                 //See the invocation context: if it is executed from the recycle bin 
    508                 //then the list of selected files will be empty. 
    509                 if (InvokeReason == INVOKEREASON_RECYCLEBIN) 
    510                 { 
    511                     commandLine += L"recyclebin"; 
    512                 } 
    513                 else 
    514                 { 
    515                     //Okay, we were called from an item right-click; iterate over every 
    516                     //selected file 
    517                     for (std::list<std::wstring>::const_iterator i = SelectedFiles.begin(); 
    518                         i != SelectedFiles.end(); ++i) 
    519                     { 
    520                         //Check if the current item is a file or folder. 
    521                         std::wstring item(*i); 
    522                         if (item.length() > 2 && item[item.length() - 1] == '\\') 
    523                             item.erase(item.end() - 1); 
    524                         DWORD attributes = GetFileAttributes(item.c_str()); 
    525  
    526                         //Add the correct command line for the file type. 
    527                         if (attributes & FILE_ATTRIBUTE_DIRECTORY) 
    528                             commandLine += L"\"dir=" + item + L"\" "; 
    529                         else 
    530                             commandLine += L"\"file=" + item + L"\" "; 
    531                     } 
    532                 } 
    533  
    534                 break; 
    535             } 
     499            //See the invocation context: if it is executed from the recycle bin 
     500            //then the list of selected files will be empty. 
     501            if (InvokeReason == INVOKEREASON_RECYCLEBIN) 
     502            { 
     503                commandLine += L"/recyclebin"; 
     504            } 
     505 
     506            break; 
    536507 
    537508        case ACTION_ERASE_UNUSED_SPACE: 
    538             { 
    539                 //We want to add a new task 
    540                 commandAction = L"addtask"; 
    541  
    542                 //Erasing unused space requires elevation 
    543                 commandElevate = true; 
    544  
    545                 //Add every item onto the command line 
    546                 for (std::list<std::wstring>::const_iterator i = SelectedFiles.begin(); 
    547                     i != SelectedFiles.end(); ++i) 
    548                 { 
    549                     commandLine += L"\"unused=" + *i + L",clusterTips\" "; 
    550                 } 
    551                  
    552                 break; 
    553             } 
     509            //Erasing unused space requires elevation 
     510            commandElevate = true; 
     511            break; 
    554512 
    555513        default: 
     
    559517                    VerbMenuIndices[LOWORD(pCmdInfo->lpVerb)]).c_str(), 
    560518                    LoadString(IDS_ERASERSHELLEXT).c_str(), MB_OK | MB_ICONERROR); 
    561             } 
     519                return E_INVALIDARG; 
     520            } 
     521        } 
     522 
     523        //Add the list of items selected. 
     524        for (std::list<std::wstring>::const_iterator i = SelectedFiles.begin(); 
     525            i != SelectedFiles.end(); ++i) 
     526        { 
     527            commandLine += L"\"" + *i + L"\" "; 
    562528        } 
    563529 
     
    565531        { 
    566532            BusyCursor cursor; 
    567             RunEraser(commandAction, commandLine, commandElevate, pCmdInfo->hwnd, 
    568                 pCmdInfo->nShow); 
     533            RunEraser(VerbMenuIndices[LOWORD(pCmdInfo->lpVerb)], commandLine, commandElevate, 
     534                pCmdInfo->hwnd, pCmdInfo->nShow); 
    569535        } 
    570536        catch (const std::wstring& e) 
     
    577543        } 
    578544 
    579         return result; 
     545        return S_OK; 
    580546    } 
    581547 
     
    812778    } 
    813779 
    814     void CCtxMenu::RunEraser(const std::wstring& action, const std::wstring& parameters, 
    815         bool elevated, HWND parent, int show) 
     780    void CCtxMenu::RunEraser(Actions action, const std::wstring& parameters, bool elevated, 
     781        HWND parent, int show) 
    816782    { 
    817783        //Get the path to this DLL so we can look for Eraser.exe 
     
    834800        eraserPath += L"Eraser.exe"; 
    835801 
    836         std::wstring finalParameters; 
     802        //Compile the final set of parameters we are going to pass to Eraser. 
     803        std::wstring finalParameters(L"shell /quiet "); 
     804 
     805        //Set the action selected by the user. 
     806        switch (action) 
     807        { 
     808        case ACTION_ERASE: 
     809            finalParameters += L"/action=EraseNow "; 
     810            break; 
     811        case ACTION_ERASE_ON_RESTART: 
     812            finalParameters += L"/action=EraseOnRestart "; 
     813            break; 
     814        case ACTION_ERASE_UNUSED_SPACE: 
     815            finalParameters += L"/action=EraseUnusedSpace "; 
     816            break; 
     817        default: 
     818            return; 
     819        } 
     820 
     821        //Then append the rest of the arguments, depending on the length. 
    837822        { 
    838823            //Depending on the length of the argument, we either use a response file 
     
    851836 
    852837                std::wofstream stream(buffer); 
    853                 stream << "\"" << action << L"\" /quiet " << parameters; 
    854  
    855                 finalParameters = L"\"@"; 
     838                stream << parameters; 
     839 
     840                finalParameters += L"\"@"; 
    856841                finalParameters += buffer; 
    857842                finalParameters += '"'; 
     
    860845            { 
    861846                //Short command line, pass directly to the program 
    862                 std::wostringstream stream; 
    863                 stream << "\"" << action << L"\" /quiet " << parameters; 
    864                 finalParameters = stream.str(); 
     847                finalParameters += parameters; 
    865848            } 
    866849        } 
  • trunk/eraser/Eraser.Shell/CtxMenu.h

    r1828 r2015  
    5454        }; 
    5555 
     56        /// This has the equivalent in Eraser.Program.ShellActions 
    5657        enum Actions 
    5758        { 
     
    8687 
    8788        static bool IsUserAdmin(); 
    88         static void RunEraser(const std::wstring& action, const std::wstring& parameters, 
     89        static void RunEraser(Actions action, const std::wstring& parameters, 
    8990            bool elevated, HWND parent, int show); 
    9091 
  • trunk/eraser/Eraser/Eraser.csproj

    r1996 r2015  
    212212      <DependentUpon>SettingsPanel.cs</DependentUpon> 
    213213    </EmbeddedResource> 
     214    <EmbeddedResource Include="ShellConfirmationDialog.resx"> 
     215      <DependentUpon>ShellConfirmationDialog.cs</DependentUpon> 
     216    </EmbeddedResource> 
    214217    <EmbeddedResource Include="Strings.en.resx"> 
    215218      <SubType>Designer</SubType> 
     
    333336  <ItemGroup> 
    334337    <Compile Include="Program.ConsoleProgram.cs" /> 
     338    <Compile Include="ShellConfirmationDialog.cs"> 
     339      <SubType>Form</SubType> 
     340    </Compile> 
     341    <Compile Include="ShellConfirmationDialog.Designer.cs"> 
     342      <DependentUpon>ShellConfirmationDialog.cs</DependentUpon> 
     343    </Compile> 
    335344    <None Include="Resources\AboutDialog.png" /> 
    336345    <CodeAnalysisDictionary Include="..\CustomDictionary.xml"> 
  • trunk/eraser/Eraser/Program.cs

    r2009 r2015  
    101101        } 
    102102 
     103        class ShellArguments : ConsoleArguments 
     104        { 
     105            /// <summary> 
     106            /// The action which the shell extension has requested. 
     107            /// </summary> 
     108            [Arg("action", "The action selected by the user", typeof(string), true, null, null)] 
     109            public ShellActions ShellAction { get; set; } 
     110 
     111            /// <summary> 
     112            /// Whether the recycle bin was specified on the command line. 
     113            /// </summary> 
     114            [Arg("recycleBin", "The recycle bin as an erasure target", typeof(string), false, null, null)] 
     115            public bool RecycleBin { get; set; } 
     116        } 
     117 
     118        public enum ShellActions 
     119        { 
     120            /// <summary> 
     121            /// Erase the selected items now. 
     122            /// </summary> 
     123            EraseNow, 
     124 
     125            /// <summary> 
     126            /// Erase the selected items on restart. 
     127            /// </summary> 
     128            EraseOnRestart, 
     129 
     130            /// <summary> 
     131            /// Erase the unused space on the drive. 
     132            /// </summary> 
     133            EraseUnusedSpace 
     134        } 
     135 
    103136        /// <summary> 
    104137        /// The main entry point for the application. 
     
    154187        #region Console Program code 
    155188        /// <summary> 
     189        /// Connects to the running Eraser instance for erasures. 
     190        /// </summary> 
     191        /// <returns>The connectin with the remote instance.</returns> 
     192        private static RemoteExecutorClient CommandConnect() 
     193        { 
     194            try 
     195            { 
     196                RemoteExecutorClient result = new RemoteExecutorClient(); 
     197                result.Run(); 
     198                if (!result.IsConnected) 
     199                { 
     200                    //The client cannot connect to the server. This probably means 
     201                    //that the server process isn't running. Start an instance. 
     202                    Process eraserInstance = Process.Start( 
     203                        Assembly.GetExecutingAssembly().Location, "/quiet"); 
     204                    Thread.Sleep(0); 
     205                    eraserInstance.WaitForInputIdle(); 
     206 
     207                    result.Run(); 
     208                    if (!result.IsConnected) 
     209                        throw new IOException("Eraser cannot connect to the running " + 
     210                            "instance for erasures."); 
     211                } 
     212 
     213                return result; 
     214            } 
     215            catch (UnauthorizedAccessException e) 
     216            { 
     217                //We can't connect to the pipe because the other instance of Eraser 
     218                //is running with higher privileges than this instance. 
     219                throw new UnauthorizedAccessException("Another instance of Eraser " + 
     220                    "is already running but it is running with higher privileges than " + 
     221                    "this instance of Eraser. Tasks cannot be added in this manner.\n\n" + 
     222                    "Close the running instance of Eraser and start it again without " + 
     223                    "administrator privileges, or run the command again as an " + 
     224                    "administrator.", e); 
     225            } 
     226        } 
     227 
     228        /// <summary> 
    156229        /// Runs Eraser as a command-line application. 
    157230        /// </summary> 
     
    171244                    program.Handlers.Add("importtasklist", 
    172245                        new ConsoleActionData(CommandImportTaskList, new ConsoleArguments())); 
     246                    program.Handlers.Add("shell", 
     247                        new ConsoleActionData(CommandShell, new ShellArguments())); 
    173248                    program.Run(); 
    174249                    return 0; 
     
    408483 
    409484            //Send the task out. 
    410             try 
    411             { 
    412                 using (RemoteExecutorClient client = new RemoteExecutorClient()) 
    413                 { 
    414                     client.Run(); 
    415                     if (!client.IsConnected) 
    416                     { 
    417                         //The client cannot connect to the server. This probably means 
    418                         //that the server process isn't running. Start an instance. 
    419                         Process eraserInstance = Process.Start( 
    420                             Assembly.GetExecutingAssembly().Location, "/quiet"); 
    421                         Thread.Sleep(0); 
    422                         eraserInstance.WaitForInputIdle(); 
    423  
    424                         client.Run(); 
    425                         if (!client.IsConnected) 
    426                             throw new IOException("Eraser cannot connect to the running " + 
    427                                 "instance for erasures."); 
    428                     } 
    429  
    430                     client.Tasks.Add(task); 
    431                 } 
    432             } 
    433             catch (UnauthorizedAccessException e) 
    434             { 
    435                 //We can't connect to the pipe because the other instance of Eraser 
    436                 //is running with higher privileges than this instance. 
    437                 throw new UnauthorizedAccessException("Another instance of Eraser " + 
    438                     "is already running but it is running with higher privileges than " + 
    439                     "this instance of Eraser. Tasks cannot be added in this manner.\n\n" + 
    440                     "Close the running instance of Eraser and start it again without " + 
    441                     "administrator privileges, or run the command again as an " + 
    442                     "administrator.", e); 
    443             } 
     485            using (eraserClient = CommandConnect()) 
     486                eraserClient.Tasks.Add(task); 
    444487        } 
    445488 
     
    451494        { 
    452495            //Import the task list 
    453             try 
    454             { 
    455                 using (RemoteExecutorClient client = new RemoteExecutorClient()) 
    456                 { 
    457                     client.Run(); 
    458                     if (!client.IsConnected) 
     496            using (eraserClient = CommandConnect()) 
     497                foreach (string path in args.PositionalArguments) 
     498                    using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) 
     499                        eraserClient.Tasks.LoadFromStream(stream); 
     500        } 
     501 
     502        /// <summary> 
     503        /// Handles the files from the Shell extension. 
     504        /// </summary> 
     505        /// <param name="args">The command line parameters passed to the program.</param> 
     506        private static void CommandShell(ConsoleArguments args) 
     507        { 
     508            //Construct a draft task. 
     509            Task task = new Task(); 
     510            switch (((ShellArguments)args).ShellAction) 
     511            { 
     512                case ShellActions.EraseOnRestart: 
     513                    task.Schedule = Schedule.RunOnRestart; 
     514                    goto case ShellActions.EraseNow; 
     515 
     516                case ShellActions.EraseNow: 
     517                    foreach (string path in args.PositionalArguments) 
    459518                    { 
    460                         //The client cannot connect to the server. This probably means 
    461                         //that the server process isn't running. Start an instance. 
    462                         Process eraserInstance = Process.Start( 
    463                             Assembly.GetExecutingAssembly().Location, "/quiet"); 
    464                         eraserInstance.WaitForInputIdle(); 
    465  
    466                         client.Run(); 
    467                         if (!client.IsConnected) 
    468                             throw new IOException("Eraser cannot connect to the running " + 
    469                                 "instance for erasures."); 
     519                        FileSystemObjectTarget target = null; 
     520                        if (Directory.Exists(path)) 
     521                        { 
     522                            target = new FolderTarget(); 
     523                            target.Path = path; 
     524                        }  
     525                        else 
     526                        { 
     527                            target = new FileTarget(); 
     528                            target.Path = path; 
     529                        } 
     530 
     531                        task.Targets.Add(target); 
    470532                    } 
    471533 
     534                    //Was the recycle bin specified? 
     535                    if (((ShellArguments)args).RecycleBin) 
     536                        task.Targets.Add(new RecycleBinTarget()); 
     537                    break; 
     538 
     539                case ShellActions.EraseUnusedSpace: 
    472540                    foreach (string path in args.PositionalArguments) 
    473                         using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) 
    474                             client.Tasks.LoadFromStream(stream); 
    475                 } 
    476             } 
    477             catch (UnauthorizedAccessException e) 
    478             { 
    479                 //We can't connect to the pipe because the other instance of Eraser 
    480                 //is running with higher privileges than this instance. 
    481                 throw new UnauthorizedAccessException("Another instance of Eraser " + 
    482                     "is already running but it is running with higher privileges than " + 
    483                     "this instance of Eraser. Tasks cannot be added in this manner.\n\n" + 
    484                     "Close the running instance of Eraser and start it again without " + 
    485                     "administrator privileges, or run the command again as an " + 
    486                     "administrator.", e); 
    487             } 
     541                    { 
     542                        UnusedSpaceTarget target = new UnusedSpaceTarget(); 
     543                        target.Drive = path; 
     544                        task.Targets.Add(target); 
     545                    } 
     546                    break; 
     547            } 
     548 
     549            //Confirm that the user wants the erase. 
     550            Application.EnableVisualStyles(); 
     551            using (Form dialog = new ShellConfirmationDialog(task)) 
     552            { 
     553                if (dialog.ShowDialog() != DialogResult.Yes) 
     554                    return; 
     555            } 
     556 
     557            //Then queue for erasure. 
     558            using (eraserClient = CommandConnect()) 
     559                eraserClient.Tasks.Add(task); 
    488560        } 
    489561        #endregion 
Note: See TracChangeset for help on using the changeset viewer.