From 9e30dec48689e003236b29f008e0415dcb037320 Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Thu, 30 Mar 2006 00:09:09 +0000 Subject: [PATCH] dropping this defragger in here for safe keeping. It's pretty hard to come by on the net now. svn path=/trunk/; revision=21411 --- rosapps/fraginator/COPYING | 340 ++++++++ rosapps/fraginator/DefragDialog.cpp | 38 + rosapps/fraginator/Defragment.cpp | 459 +++++++++++ rosapps/fraginator/Defragment.h | 92 +++ rosapps/fraginator/DriveVolume.cpp | 806 +++++++++++++++++++ rosapps/fraginator/DriveVolume.h | 157 ++++ rosapps/fraginator/Fraginator Motif Icon.bmp | Bin 0 -> 4438 bytes rosapps/fraginator/Fraginator.cpp | 58 ++ rosapps/fraginator/Fraginator.dsp | 186 +++++ rosapps/fraginator/Fraginator.dsw | 41 + rosapps/fraginator/Fraginator.exe | Bin 0 -> 122880 bytes rosapps/fraginator/Fraginator.h | 24 + rosapps/fraginator/Fraginator.mak | 224 ++++++ rosapps/fraginator/Fraginator.rc | 241 ++++++ rosapps/fraginator/Fraginator.sln | 27 + rosapps/fraginator/Fraginator.suo | Bin 0 -> 14336 bytes rosapps/fraginator/Fraginator.vcproj | 203 +++++ rosapps/fraginator/MainDialog.cpp | 574 +++++++++++++ rosapps/fraginator/MainDialog.h | 14 + rosapps/fraginator/Mutex.h | 78 ++ rosapps/fraginator/ReportDialog.cpp | 231 ++++++ rosapps/fraginator/ReportDialog.h | 18 + rosapps/fraginator/Unfrag.cpp | 464 +++++++++++ rosapps/fraginator/Unfrag.h | 83 ++ rosapps/fraginator/default1.bin | 22 + rosapps/fraginator/icon1.ico | Bin 0 -> 8166 bytes rosapps/fraginator/resource.h | 51 ++ rosapps/fraginator/unfrag.dsp | 133 +++ rosapps/fraginator/unfrag.exe | Bin 0 -> 90112 bytes rosapps/fraginator/unfrag.mak | 184 +++++ rosapps/fraginator/unfrag.plg | 48 ++ rosapps/fraginator/unfrag.vcproj | 160 ++++ 32 files changed, 4956 insertions(+) create mode 100644 rosapps/fraginator/COPYING create mode 100644 rosapps/fraginator/DefragDialog.cpp create mode 100644 rosapps/fraginator/Defragment.cpp create mode 100644 rosapps/fraginator/Defragment.h create mode 100644 rosapps/fraginator/DriveVolume.cpp create mode 100644 rosapps/fraginator/DriveVolume.h create mode 100644 rosapps/fraginator/Fraginator Motif Icon.bmp create mode 100644 rosapps/fraginator/Fraginator.cpp create mode 100644 rosapps/fraginator/Fraginator.dsp create mode 100644 rosapps/fraginator/Fraginator.dsw create mode 100644 rosapps/fraginator/Fraginator.exe create mode 100644 rosapps/fraginator/Fraginator.h create mode 100644 rosapps/fraginator/Fraginator.mak create mode 100644 rosapps/fraginator/Fraginator.rc create mode 100644 rosapps/fraginator/Fraginator.sln create mode 100644 rosapps/fraginator/Fraginator.suo create mode 100644 rosapps/fraginator/Fraginator.vcproj create mode 100644 rosapps/fraginator/MainDialog.cpp create mode 100644 rosapps/fraginator/MainDialog.h create mode 100644 rosapps/fraginator/Mutex.h create mode 100644 rosapps/fraginator/ReportDialog.cpp create mode 100644 rosapps/fraginator/ReportDialog.h create mode 100644 rosapps/fraginator/Unfrag.cpp create mode 100644 rosapps/fraginator/Unfrag.h create mode 100644 rosapps/fraginator/default1.bin create mode 100644 rosapps/fraginator/icon1.ico create mode 100644 rosapps/fraginator/resource.h create mode 100644 rosapps/fraginator/unfrag.dsp create mode 100644 rosapps/fraginator/unfrag.exe create mode 100644 rosapps/fraginator/unfrag.mak create mode 100644 rosapps/fraginator/unfrag.plg create mode 100644 rosapps/fraginator/unfrag.vcproj diff --git a/rosapps/fraginator/COPYING b/rosapps/fraginator/COPYING new file mode 100644 index 00000000000..fbdd65f6f8b --- /dev/null +++ b/rosapps/fraginator/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/rosapps/fraginator/DefragDialog.cpp b/rosapps/fraginator/DefragDialog.cpp new file mode 100644 index 00000000000..cd4b65a913b --- /dev/null +++ b/rosapps/fraginator/DefragDialog.cpp @@ -0,0 +1,38 @@ +#include "DefragDialog.h" +#include "Defragment.h" +#include "resource.h" + + +void UpdateDefragInfo (HWND Dlg) +{ + Defragment *Defrag; + HWND PercentItem; + char PercentText[100]; + + Defrag = (Defragment *) GetWindowLongPtr (Dlg, GWLP_USERDATA); + + sprintf (PercentText, "%6.2f%%", Defrag->GetStatusPercent()); + PercentItem = GetDlgItem (Dlg, IDC_PERCENT); + SendMessage (GetDlgItem (Dlg, IDC_PERCENT), WM_SETTEXT, 0, (LPARAM) PercentText); + SendMessage (GetDlgItem (Dlg, IDC_STATUS_TEXT), WM_SETTEXT, 0, (LPARAM) Defrag->GetStatusString().c_str()); + + return; +} + + +INT_PTR CALLBACK DefragDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam) +{ + switch (Msg) + { + case WM_INITDIALOG: + SetWindowLongPtr (Dlg, GWLP_USERDATA, (LONG_PTR)LParam); + UpdateDefragInfo (Dlg); + return (1); + + case WM_UPDATEINFO: + UpdateDefragInfo (Dlg); + return (1); + } + + return (0); +} diff --git a/rosapps/fraginator/Defragment.cpp b/rosapps/fraginator/Defragment.cpp new file mode 100644 index 00000000000..2b989e05a94 --- /dev/null +++ b/rosapps/fraginator/Defragment.cpp @@ -0,0 +1,459 @@ +#include "Defragment.h" + + +// Ahh yes I ripped this from my old Findupes project :) +// Fits a path name, composed of a path (i.e. "c:\blah\blah\cha\cha") and a filename ("stuff.txt") +// and fits it to a given length. If it has to truncate it will first truncate from the path, +// substituting in periods. So you might end up with something like: +// C:\Program Files\Micro...\Register.exe +int FitName (char *destination, const char *path, const char *filename, uint32 totalWidth) +{ + uint32 pathLen=0; + uint32 fnLen=0; + uint32 halfTotLen=0; + uint32 len4fn=0; /* number of chars remaining for filename after path is applied */ + uint32 len4path=0; /* number of chars for path before filename is applied */ + char fmtStrPath[20]=""; + char fmtStrFile[20]=""; + char fmtString[40]=""; + + /* + assert (destination != NULL); + assert (path != NULL); + assert (filename != NULL); + assert (totalWidth != 0); + */ + + pathLen = strlen(path); + fnLen = strlen(filename); + if (!(totalWidth % 2)) + halfTotLen=totalWidth / 2; + else + halfTotLen=(totalWidth-1) / 2; /* -1 because otherwise (halfTotLen*2) == +(totalWidth+1) which wouldn't be good */ + + /* determine how much width the path and filename each get */ + if ( (pathLen >= halfTotLen) && (fnLen < halfTotLen) ) + { + len4fn = fnLen; + len4path = (totalWidth - len4fn); + } + + if ( (pathLen < halfTotLen) && (fnLen < halfTotLen) ) + { + len4fn = fnLen; + len4path = pathLen; + } + + if ( (pathLen >= halfTotLen) && (fnLen >= halfTotLen) ) + { + len4fn = halfTotLen; + len4path = halfTotLen; + } + + if ( (pathLen < halfTotLen) && (fnLen >= halfTotLen) ) + { + len4path = pathLen; + len4fn = (totalWidth - len4path); + } + /* + if halfTotLen was adjusted above to avoid a rounding error, give the + extra char to the filename + */ + if (halfTotLen < (totalWidth/2)) len4path++; + + if (pathLen > len4path) sprintf (fmtStrPath, "%%.%ds...\\", len4path-4); + else + sprintf (fmtStrPath, "%%s"); + + if (fnLen > len4fn) sprintf (fmtStrFile, "%%.%ds...", len4fn-3); + else + sprintf (fmtStrFile, "%%s"); + + strcpy (fmtString, fmtStrPath); + strcat (fmtString, fmtStrFile); + /*sprintf (fmtString, "%s%s", fmtStrPath, fmtStrFile);*/ + sprintf (destination, fmtString, path,filename); + + return (1); +} + + +Defragment::Defragment (string Name, DefragType DefragMethod) +{ + Method = DefragMethod; + DoLimitLength = true; + Error = false; + Done = false; + PleaseStop = false; + PleasePause = false; + DriveName = Name; + StatusPercent = 0.0f; + LastBMPUpdate = GetTickCount (); + + SetStatusString ("Opening volume " + Name); + if (!Volume.Open (Name)) + { + SetStatusString ("Error opening volume " + Name); + Error = true; + Done = true; + StatusPercent = 100.0f; + } + + return; +} + + +Defragment::~Defragment () +{ + if (!IsDoneYet ()) + { + Stop (); + while (!IsDoneYet() && !HasError()) + { + SetStatusString ("Waiting for thread to stop ..."); + Sleep (150); + } + } + + Volume.Close (); + return; +} + + +void Defragment::SetStatusString (string NewStatus) +{ + Lock (); + StatusString = NewStatus; + Unlock (); + + return; +} + + +string Defragment::GetStatusString (void) +{ + string ReturnVal; + + Lock (); + ReturnVal = StatusString; + Unlock (); + + return (ReturnVal); +} + + +double Defragment::GetStatusPercent (void) +{ + return (StatusPercent); +} + + +bool Defragment::IsDoneYet (void) +{ + return (Done); +} + + +void Defragment::Start (void) +{ + uint32 i; + uint64 FirstFreeLCN; + uint64 TotalClusters; + uint64 ClustersProgress; + char PrintName[80]; + int Width = 70; + + if (Error) + goto DoneDefrag; + + // First thing: build a file list. + SetStatusString ("Getting volume bitmap"); + if (!Volume.GetBitmap()) + { + SetStatusString ("Could not get volume " + DriveName + " bitmap"); + Error = true; + goto DoneDefrag; + } + + LastBMPUpdate = GetTickCount (); + + if (PleaseStop) + goto DoneDefrag; + + SetStatusString ("Obtaining volume geometry"); + if (!Volume.ObtainInfo ()) + { + SetStatusString ("Could not obtain volume " + DriveName + " geometry"); + Error = true; + goto DoneDefrag; + } + + if (PleaseStop) + goto DoneDefrag; + + SetStatusString ("Building file database for volume " + DriveName); + if (!Volume.BuildFileList (PleaseStop, StatusPercent)) + { + SetStatusString ("Could not build file database for volume " + DriveName); + Error = true; + goto DoneDefrag; + } + + if (PleaseStop) + goto DoneDefrag; + + SetStatusString ("Analyzing database for " + DriveName); + TotalClusters = 0; + for (i = 0; i < Volume.GetDBFileCount(); i++) + { + TotalClusters += Volume.GetDBFile(i).Clusters; + } + + // Defragment! + ClustersProgress = 0; + + // Find first free LCN for speedier searches ... + Volume.FindFreeRange (0, 1, FirstFreeLCN); + + if (PleaseStop) + goto DoneDefrag; + + // Analyze? + if (Method == DefragAnalyze) + { + uint32 j; + + Report.RootPath = Volume.GetRootPath (); + + Report.FraggedFiles.clear (); + Report.UnfraggedFiles.clear (); + Report.UnmovableFiles.clear (); + + Report.FilesCount = Volume.GetDBFileCount () - Volume.GetDBDirCount (); + Report.DirsCount = Volume.GetDBDirCount (); + Report.DiskSizeBytes = Volume.GetVolumeInfo().TotalBytes; + + Report.FilesSizeClusters = 0; + Report.FilesSlackBytes = 0; + Report.FilesSizeBytes = 0; + Report.FilesFragments = 0; + + for (j = 0; j < Volume.GetDBFileCount(); j++) + { + FileInfo Info; + + Info = Volume.GetDBFile (j); + + Report.FilesFragments += max (1, Info.Fragments.size()); // add 1 fragment even for 0 bytes/0 cluster files + + if (Info.Attributes.Process == 0) + continue; + + SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name); + + Report.FilesSizeClusters += Info.Clusters; + Report.FilesSizeBytes += Info.Size; + + if (Info.Attributes.Unmovable == 1) + Report.UnmovableFiles.push_back (j); + + if (Info.Fragments.size() > 1) + Report.FraggedFiles.push_back (j); + else + Report.UnfraggedFiles.push_back (j); + + StatusPercent = ((double)j / (double)Report.FilesCount) * 100.0f; + } + + Report.FilesSizeOnDisk = Report.FilesSizeClusters * (uint64)Volume.GetVolumeInfo().ClusterSize; + Report.FilesSlackBytes = Report.FilesSizeOnDisk - Report.FilesSizeBytes; + Report.AverageFragments = (double)Report.FilesFragments / (double)Report.FilesCount; + Report.PercentFragged = 100.0f * ((double)(signed)Report.FraggedFiles.size() / (double)(signed)Report.FilesCount); + + uint64 Percent; + Percent = (10000 * Report.FilesSlackBytes) / Report.FilesSizeOnDisk; + Report.PercentSlack = (double)(signed)Percent / 100.0f; + } + else + // Go through all the files and ... defragment them! + for (i = 0; i < Volume.GetDBFileCount(); i++) + { + FileInfo Info; + bool Result; + uint64 TargetLCN; + uint64 PreviousClusters; + + // What? They want us to pause? Oh ok. + if (PleasePause) + { + SetStatusString ("Paused"); + PleasePause = false; + + while (PleasePause == false) + { + Sleep (50); + } + + PleasePause = false; + } + + if (PleaseStop) + { + SetStatusString ("Stopping"); + break; + } + + // + Info = Volume.GetDBFile (i); + + PreviousClusters = ClustersProgress; + ClustersProgress += Info.Clusters; + + if (Info.Attributes.Process == 0) + continue; + + if (!DoLimitLength) + SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name); + else + { + FitName (PrintName, Volume.GetDBDir (Info.DirIndice).c_str(), Info.Name.c_str(), Width); + SetStatusString (PrintName); + } + + // Calculate percentage complete + StatusPercent = 100.0f * double((double)PreviousClusters / (double)TotalClusters); + + // Can't defrag directories yet + if (Info.Attributes.Directory == 1) + continue; + + // Can't defrag 0 byte files :) + if (Info.Fragments.size() == 0) + continue; + + // If doing fast defrag, skip non-fragmented files + // Note: This assumes that the extents stored in Info.Fragments + // are consolidated. I.e. we assume it is NOT the case that + // two extents account for a sequential range of (non- + // fragmented) clusters. + if (Info.Fragments.size() == 1 && Method == DefragFast) + continue; + + // Otherwise, defrag0rize it! + int Retry = 3; // retry a few times + while (Retry > 0) + { + // Find a place that can fit the file + Result = Volume.FindFreeRange (FirstFreeLCN, Info.Clusters, TargetLCN); + + // If yes, try moving it + if (Result) + { + // If we're doing an extensive defrag and the file is already defragmented + // and if its new location would be after its current location, don't + // move it. + if (Method == DefragExtensive && Info.Fragments.size() == 1 && + TargetLCN > Info.Fragments[0].StartLCN) + { + Retry = 1; + } + else + { + if (Volume.MoveFileDumb (i, TargetLCN)) + { + Retry = 1; // yay, all done with this file. + Volume.FindFreeRange (0, 1, FirstFreeLCN); + } + } + } + + // New: Only update bitmap if it's older than 15 seconds + if ((GetTickCount() - LastBMPUpdate) < 15000) + Retry = 1; + else + if (!Result || Retry != 1) + { // hmm. Wait for a moment, then update the drive bitmap + //SetStatusString ("(Reobtaining volume " + DriveName + " bitmap)"); + + if (!DoLimitLength) + { + SetStatusString (GetStatusString() + string (" .")); + } + + if (Volume.GetBitmap ()) + { + LastBMPUpdate = GetTickCount (); + + if (!DoLimitLength) + SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name); + else + SetStatusString (PrintName); + + Volume.FindFreeRange (0, 1, FirstFreeLCN); + } + else + { + SetStatusString ("Could not re-obtain volume " + DriveName + " bitmap"); + Error = true; + } + } + + Retry--; + } + + if (Error == true) + break; + } + +DoneDefrag: + string OldStatus; + + OldStatus = GetStatusString (); + StatusPercent = 99.999999f; + SetStatusString ("Closing volume " + DriveName); + Volume.Close (); + StatusPercent = 100.0f; + + // If there was an error then the string has already been set + if (Error) + SetStatusString (OldStatus); + else + if (PleaseStop) + SetStatusString ("Volume " + DriveName + " defragmentation was stopped"); + else + SetStatusString ("Finished defragmenting " + DriveName); + + Done = true; + + return; +} + + +void Defragment::TogglePause (void) +{ + Lock (); + SetStatusString ("Pausing ..."); + PleasePause = true; + Unlock (); + + return; +} + + +void Defragment::Stop (void) +{ + Lock (); + SetStatusString ("Stopping ..."); + PleaseStop = true; + Unlock (); + + return; +} + + +bool Defragment::HasError (void) +{ + return (Error); +} + diff --git a/rosapps/fraginator/Defragment.h b/rosapps/fraginator/Defragment.h new file mode 100644 index 00000000000..f814234391f --- /dev/null +++ b/rosapps/fraginator/Defragment.h @@ -0,0 +1,92 @@ +/***************************************************************************** + + Defragment + +*****************************************************************************/ + + +#ifndef DEFRAGMENT_H +#define DEFRAGMENT_H + + +#include "Unfrag.h" +#include "DriveVolume.h" +#include "Mutex.h" + + +extern int FitName (char *destination, const char *path, const char *filename, uint32 totalWidth); + + +typedef struct DefragReport +{ + string RootPath; + uint64 DiskSizeBytes; + uint64 DirsCount; + uint64 FilesCount; + uint64 FilesSizeBytes; + uint64 FilesSizeOnDisk; + uint64 FilesSizeClusters; + uint64 FilesSlackBytes; + uint32 FilesFragments; + double AverageFragments; // = FilesFragments / FilesCount + double PercentFragged; + double PercentSlack; + + vector FraggedFiles; + vector UnfraggedFiles; + vector UnmovableFiles; +} DefragReport; + + +class Defragment +{ +public: + Defragment (string Name, DefragType DefragMethod); + ~Defragment (); + + // Commands + void Start (void); + void TogglePause (void); + void Stop (void); + + // Info + bool IsDoneYet (void); + bool HasError (void); + string GetStatusString (void); + double GetStatusPercent (void); + DefragType GetDefragType (void) { return (Method); } + DefragReport &GetDefragReport (void) { return (Report); } + DriveVolume &GetVolume (void) { return (Volume); } + + // Mutex + void Lock (void) { DefragMutex.Lock (); } + void Unlock (void) { DefragMutex.Unlock (); } + + // Limit length of status string to 70 chars? + bool GetDoLimitLength (void) { return (DoLimitLength); } + void SetDoLimitLength (bool L) { DoLimitLength = L; } + +private: + void FastDefrag (void); + void ExtensiveDefrag (void); + void SetStatusString (string NewStatus); + + DWORD LastBMPUpdate; // Last time volume bitmap was updated + DefragReport Report; + bool DoLimitLength; + DefragType Method; + string DriveName; + DriveVolume Volume; + string StatusString; + string ErrorString; + double StatusPercent; + Mutex DefragMutex; + bool Error; + bool Done; + bool PleaseStop; + bool PleasePause; + DefragType DefragMethod; +}; + + +#endif // DEFRAGMENT_H diff --git a/rosapps/fraginator/DriveVolume.cpp b/rosapps/fraginator/DriveVolume.cpp new file mode 100644 index 00000000000..6845ef4ba5c --- /dev/null +++ b/rosapps/fraginator/DriveVolume.cpp @@ -0,0 +1,806 @@ +#include "DriveVolume.h" + + +DriveVolume::DriveVolume () +{ + Handle = INVALID_HANDLE_VALUE; + BitmapDetail = NULL; + return; +} + + +DriveVolume::~DriveVolume () +{ + Close (); + Directories.clear (); + Files.clear (); + return; +} + + +void DriveVolume::Close (void) +{ + if (Handle != INVALID_HANDLE_VALUE) + { + CloseHandle (Handle); + Handle = INVALID_HANDLE_VALUE; + } + + if (BitmapDetail != NULL) + { + free (BitmapDetail); + BitmapDetail = NULL; + } + + return; +} + + +// "Name" should be the drive letter followed by a colon. ie, "c:" +// It's a string to allow for further expansion (ie, defragging over the network?) +// or some other baloney reason +bool DriveVolume::Open (string Name) +{ + char FileName[100]; + bool ReturnVal; + + sprintf (FileName, "\\\\.\\%s", Name.c_str()); + RootPath = Name.c_str(); + RootPath += "\\"; + + Handle = CreateFile + ( + FileName, + MAXIMUM_ALLOWED, // access + FILE_SHARE_READ | FILE_SHARE_WRITE, // share type + NULL, // security descriptor + OPEN_EXISTING, // open type + NULL, // attributes (none) + NULL // template + ); + + if (Handle == INVALID_HANDLE_VALUE) + ReturnVal = false; + else + { + char VolName[64]; + DWORD VolSN; + DWORD VolMaxFileLen; + DWORD FSFlags; + char FSName[64]; + BOOL Result; + + ReturnVal = true; + Result = GetVolumeInformation + ( + RootPath.c_str(), + VolName, + sizeof (VolName), + &VolSN, + &VolMaxFileLen, + &FSFlags, + FSName, + sizeof (FSName) + ); + + if (Result) + { + char SerialText[10]; + + VolInfo.FileSystem = FSName; + VolInfo.MaxNameLen = VolMaxFileLen; + VolInfo.Name = VolName; + + sprintf (SerialText, "%x-%x", (VolSN & 0xffff0000) >> 16, + VolSN & 0x0000ffff); + + strupr (SerialText); + VolInfo.Serial = SerialText; + } + else + { + VolInfo.FileSystem = "(Unknown)"; + VolInfo.MaxNameLen = 255; + VolInfo.Name = "(Unknown)"; + VolInfo.Serial = "(Unknown)"; + } + } + + return (ReturnVal); +} + + +bool DriveVolume::ObtainInfo (void) +{ + BOOL Result; + DWORD BytesGot; + uint64 nan; + + BytesGot = 0; + ZeroMemory (&Geometry, sizeof (Geometry)); + Result = DeviceIoControl + ( + Handle, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &Geometry, + sizeof (Geometry), + &BytesGot, + NULL + ); + + // Call failed? Aww :( + if (!Result) + return (false); + + // Get cluster size + DWORD SectorsPerCluster; + DWORD BytesPerSector; + DWORD FreeClusters; + DWORD TotalClusters; + + Result = GetDiskFreeSpace + ( + RootPath.c_str(), + &SectorsPerCluster, + &BytesPerSector, + &FreeClusters, + &TotalClusters + ); + + // Failed? Weird. + if (!Result) + return (false); + + VolInfo.ClusterSize = SectorsPerCluster * BytesPerSector; + + Result = GetDiskFreeSpaceEx + ( + RootPath.c_str(), + (PULARGE_INTEGER)&nan, + (PULARGE_INTEGER)&VolInfo.TotalBytes, + (PULARGE_INTEGER)&VolInfo.FreeBytes + ); + + return (true); +} + + +// Get bitmap, several clusters at a time ... +#define CLUSTERS 4096 +bool DriveVolume::GetBitmap (void) +{ + STARTING_LCN_INPUT_BUFFER StartingLCN; + VOLUME_BITMAP_BUFFER *Bitmap = NULL; + uint32 BitmapSize; + DWORD BytesReturned; + BOOL Result; + + StartingLCN.StartingLcn.QuadPart = 0; + + // Allocate buffer + // Call FSCTL_GET_VOLUME_BITMAP once with a very small buffer + // This will leave the total number of clusters in Bitmap->BitmapSize and we can + // then correctly allocate based off that + // I suppose this won't work if your drive has only 40 clusters on it or so :) + BitmapSize = sizeof (VOLUME_BITMAP_BUFFER) + 4; + Bitmap = (VOLUME_BITMAP_BUFFER *) malloc (BitmapSize); + + Result = DeviceIoControl + ( + Handle, + FSCTL_GET_VOLUME_BITMAP, + &StartingLCN, + sizeof (StartingLCN), + Bitmap, + BitmapSize, + &BytesReturned, + NULL + ); + + // Bad result? + if (Result == FALSE && GetLastError () != ERROR_MORE_DATA) + { + //printf ("\nDeviceIoControl returned false, GetLastError() was not ERROR_MORE_DATA\n"); + free (Bitmap); + return (false); + } + + // Otherwise, we're good + BitmapSize = sizeof (VOLUME_BITMAP_BUFFER) + (Bitmap->BitmapSize.QuadPart / 8) + 1; + Bitmap = (VOLUME_BITMAP_BUFFER *) realloc (Bitmap, BitmapSize); + Result = DeviceIoControl + ( + Handle, + FSCTL_GET_VOLUME_BITMAP, + &StartingLCN, + sizeof (StartingLCN), + Bitmap, + BitmapSize, + &BytesReturned, + NULL + ); + + DWORD LastError = GetLastError (); + + if (Result == FALSE) + { + printf ("\nCouldn't properly read volume bitmap\n"); + free (Bitmap); + return (false); + } + + // Convert to a 'quick use' bitmap + //const int BitShift[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; + + VolInfo.ClusterCount = Bitmap->BitmapSize.QuadPart; + + if (BitmapDetail != NULL) + free (BitmapDetail); + + BitmapDetail = (uint32 *) malloc (sizeof(uint32) * (1 + (VolInfo.ClusterCount / 32))); + memcpy (BitmapDetail, Bitmap->Buffer, sizeof(uint32) * (1 + (VolInfo.ClusterCount / 32))); + + /* + BitmapDetail = (Cluster *) malloc (VolInfo.ClusterCount * sizeof (Cluster)); + for (uint64 i = 0; i < VolInfo.ClusterCount; i++) + { + if (Bitmap->Buffer[i / 8] & BitShift[i % 8]) + BitmapDetail[i].Allocated = true; + else + BitmapDetail[i].Allocated = false; + } + */ + + free (Bitmap); + return (true); +} + + +bool DriveVolume::IsClusterUsed (uint64 Cluster) +{ + return ((BitmapDetail[Cluster / 32] & (1 << (Cluster % 32))) ? true : false); + //return (BitmapDetail[Cluster].Allocated); +} + + +void DriveVolume::SetClusterUsed (uint64 Cluster, bool Used) +{ + if (Used) + BitmapDetail[Cluster / 32] |= (1 << (Cluster % 32)); + else + BitmapDetail[Cluster / 32] &= ~(1 << (Cluster % 32)); + + return; +} + + +typedef struct +{ + DriveVolume *Volume; + double *Percent; + bool *QuitMonitor; + uint64 ClusterCount; + uint64 ClusterProgress; +} BuildDBInfo; + + +bool DriveVolume::BuildFileList (bool &QuitMonitor, double &Percent) +{ + BuildDBInfo Info; + + Files.clear (); + Directories.clear (); + Directories.push_back (RootPath); + + Info.Volume = this; + Info.QuitMonitor = &QuitMonitor; + Info.ClusterCount = (GetVolumeInfo().TotalBytes - GetVolumeInfo().FreeBytes) / (uint64)GetVolumeInfo().ClusterSize; + Info.ClusterProgress = 0; + Info.Percent = &Percent; + + ScanDirectory (RootPath, BuildDBCallback, &Info); + + if (QuitMonitor == true) + { + Directories.resize (0); + Files.resize (0); + } + + return (true); +} + + +// UserData = pointer to BuildDBInfo instance +bool BuildDBCallback (FileInfo &Info, HANDLE &FileHandle, void *UserData) +{ + BuildDBInfo *DBInfo = (BuildDBInfo *) UserData; + DriveVolume *Vol = DBInfo->Volume; + + Vol->Files.push_back (Info); + + if (*(DBInfo->QuitMonitor) == true) + return (false); + + DBInfo->ClusterProgress += (uint64)Info.Clusters; + *(DBInfo->Percent) = + ((double)DBInfo->ClusterProgress / (double)DBInfo->ClusterCount) * 100.0f; + + return (true); +} + + +string &DriveVolume::GetDBDir (uint32 Indice) +{ + return (Directories[Indice]); +} + + +uint32 DriveVolume::GetDBDirCount (void) +{ + return (Directories.size()); +} + + +FileInfo &DriveVolume::GetDBFile (uint32 Indice) +{ + return (Files[Indice]); +} + + +uint32 DriveVolume::GetDBFileCount (void) +{ + return (Files.size()); +} + + +uint32 DriveVolume::RemoveDBFile (uint32 Indice) +{ + vector::iterator it; + + it = Files.begin() + Indice; + Files.erase (it); + return (GetDBFileCount()); +} + + +bool DriveVolume::ScanDirectory (string DirPrefix, ScanCallback Callback, void *UserData) +{ + WIN32_FIND_DATA FindData; + HANDLE FindHandle; + string SearchString; + uint32 DirIndice; + + DirIndice = Directories.size() - 1; + + SearchString = DirPrefix; + SearchString += "*.*"; + ZeroMemory (&FindData, sizeof (FindData)); + FindHandle = FindFirstFile (SearchString.c_str(), &FindData); + + if (FindHandle == INVALID_HANDLE_VALUE) + return (false); + + do + { + FileInfo Info; + HANDLE Handle; + bool CallbackResult; + + Handle = INVALID_HANDLE_VALUE; + + // First copy over the easy stuff. + Info.Name = FindData.cFileName; + + // Don't ever include '.' and '..' + if (Info.Name == "." || Info.Name == "..") + continue; + + //Info.FullName = DirPrefix + Info.Name; + Info.Size = (uint64)FindData.nFileSizeLow + ((uint64)FindData.nFileSizeHigh << (uint64)32); + Info.DirIndice = DirIndice; + + Info.Attributes.Archive = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? 1 : 0; + Info.Attributes.Compressed = (FindData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ? 1 : 0; + Info.Attributes.Directory = (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0; + Info.Attributes.Encrypted = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) ? 1 : 0; + Info.Attributes.Hidden = (FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? 1 : 0; + Info.Attributes.Normal = (FindData.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ? 1 : 0; + Info.Attributes.Offline = (FindData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) ? 1 : 0; + Info.Attributes.ReadOnly = (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 1 : 0; + Info.Attributes.Reparse = (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; + Info.Attributes.Sparse = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) ? 1 : 0; + Info.Attributes.System = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? 1 : 0; + Info.Attributes.Temporary = (FindData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? 1 : 0; + Info.Attributes.AccessDenied = 0; + Info.Attributes.Unmovable = 0; + Info.Attributes.Process = 1; + + Info.Clusters = 0; + if (GetClusterInfo (Info, Handle)) + { + uint64 TotalClusters = 0; + + for (int i = 0; i < Info.Fragments.size(); i++) + { + TotalClusters += Info.Fragments[i].Length; + } + + Info.Clusters = TotalClusters; + } + else + { + Info.Attributes.Unmovable = 1; + Info.Attributes.Process = 0; + } + + if (Info.Attributes.Process == 1) + Info.Attributes.Process = ShouldProcess (Info.Attributes) ? 1 : 0; + + // Run the user-defined callback function + CallbackResult = Callback (Info, Handle, UserData); + + if (Handle != INVALID_HANDLE_VALUE) + CloseHandle (Handle); + + if (!CallbackResult) + break; + + // If directory, perform recursion + if (Info.Attributes.Directory == 1) + { + string Dir; + + Dir = GetDBDir (Info.DirIndice); + Dir += Info.Name; + Dir += "\\"; + + Directories.push_back (Dir); + ScanDirectory (Dir, Callback, UserData); + } + + } while (FindNextFile (FindHandle, &FindData) == TRUE); + + FindClose (FindHandle); + return (false); +} + + +bool DriveVolume::ShouldProcess (FileAttr Attr) +{ + if (Attr.Offline == 1 || Attr.Reparse == 1 || Attr.Temporary == 1) + { + return (false); + } + + return (true); +} + + +// Gets info on a file and returns a valid handle for read/write access +// Name, FullName, Clusters, Attributes, and Size should already be filled out. +// This function fills in the Fragments vector +bool DriveVolume::GetClusterInfo (FileInfo &Info, HANDLE &HandleResult) +{ + BOOL Result; + HANDLE Handle; + string FullName; + BY_HANDLE_FILE_INFORMATION FileInfo; + + Info.Fragments.resize (0); + + /* + if (Info.Attributes.Directory == 1) + return (false); + */ + + FullName = GetDBDir (Info.DirIndice) + Info.Name; + + Handle = CreateFile + ( + FullName.c_str(), + 0, //GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + (Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0, + NULL + ); + + if (Handle == INVALID_HANDLE_VALUE) + { + LPVOID lpMsgBuf; + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL ); + + + Info.Attributes.AccessDenied = 1; + LocalFree( lpMsgBuf ); + return (false); + } + + ZeroMemory (&FileInfo, sizeof (FileInfo)); + Result = GetFileInformationByHandle (Handle, &FileInfo); + + if (Result == FALSE) + { + Info.Attributes.AccessDenied = 1; + printf ("GetFileInformationByHandle ('%s%s') failed\n", GetDBDir (Info.DirIndice).c_str(), + Info.Name.c_str()); + + CloseHandle (Handle); + return (false); + } + + // Get cluster allocation information + STARTING_VCN_INPUT_BUFFER StartingVCN; + RETRIEVAL_POINTERS_BUFFER *Retrieval; + uint64 RetSize; + uint64 Extents; + DWORD BytesReturned; + + // Grab info one extent at a time, until it's done grabbing all the extent data + // Yeah, well it doesn't give us a way to ask "how many extents?" that I know of ... + // btw, the Extents variable tends to only reflect memory usage, so when we have + // all the extents we look at the structure Win32 gives us for the REAL count! + Extents = 10; + Retrieval = NULL; + RetSize = 0; + StartingVCN.StartingVcn.QuadPart = 0; + + do + { + Extents *= 2; + RetSize = sizeof (RETRIEVAL_POINTERS_BUFFER) + ((Extents - 1) * sizeof (LARGE_INTEGER) * 2); + + if (Retrieval != NULL) + Retrieval = (RETRIEVAL_POINTERS_BUFFER *) realloc (Retrieval, RetSize); + else + Retrieval = (RETRIEVAL_POINTERS_BUFFER *) malloc (RetSize); + + Result = DeviceIoControl + ( + Handle, + FSCTL_GET_RETRIEVAL_POINTERS, + &StartingVCN, + sizeof (StartingVCN), + Retrieval, + RetSize, + &BytesReturned, + NULL + ); + + if (Result == FALSE) + { + if (GetLastError() != ERROR_MORE_DATA) + { + Info.Clusters = 0; + Info.Attributes.AccessDenied = 1; + Info.Attributes.Process = 0; + Info.Fragments.clear (); + CloseHandle (Handle); + free (Retrieval); + + return (false); + } + + Extents++; + } + } while (Result == FALSE); + + // Readjust extents, as it only reflects how much memory was allocated and may not + // be accurate + Extents = Retrieval->ExtentCount; + + // Ok, we have the info. Now translate it. hrmrmr + int i; + Info.Fragments.clear (); + for (i = 0; i < Extents; i++) + { + Extent Add; + + Add.StartLCN = Retrieval->Extents[i].Lcn.QuadPart; + if (i != 0) + Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->Extents[i - 1].NextVcn.QuadPart; + else + Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->StartingVcn.QuadPart; + + Info.Fragments.push_back (Add); + } + + free (Retrieval); + HandleResult = Handle; + return (true); +} + + +bool DriveVolume::FindFreeRange (uint64 StartLCN, uint64 ReqLength, uint64 &LCNResult) +{ + uint64 Max; + uint64 i; + uint64 j; + + // Make sure we don't spill over our array + Max = VolInfo.ClusterCount - ReqLength; + + for (i = StartLCN; i < Max; i++) + { + bool Found = true; + + // First check the first cluster + if (IsClusterUsed (i)) + Found = false; + else + // THen check the last cluster + if (IsClusterUsed (i + ReqLength - 1)) + Found = false; + else + // Check the whole darn range. + for (j = (i + 1); j < (i + ReqLength - 2); j++) + { + if (IsClusterUsed (j) == true) + { + Found = false; + break; + } + } + + if (!Found) + continue; + else + { + LCNResult = i; + return (true); + } + } + + return (false); +} + + +// btw we have to move each fragment of the file, as per the Win32 API +bool DriveVolume::MoveFileDumb (uint32 FileIndice, uint64 NewLCN) +{ + bool ReturnVal = false; + FileInfo Info; + HANDLE FileHandle; + string FullName; + MOVE_FILE_DATA MoveData; + uint64 CurrentLCN; + uint64 CurrentVCN; + + // Set up variables + Info = GetDBFile (FileIndice); + FullName = GetDBDir (Info.DirIndice); + FullName += Info.Name; + CurrentLCN = NewLCN; + CurrentVCN = 0; + + /* + if (Info.Attributes.Directory == 1) + { + // + } + */ + + // Open file + FileHandle = CreateFile + ( + FullName.c_str (), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + (Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0, + NULL + ); + + if (FileHandle == INVALID_HANDLE_VALUE) + { + // + LPVOID lpMsgBuf; + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL ); + + + LocalFree (lpMsgBuf); + // + + ReturnVal = false; + } + else + { + ReturnVal = true; // innocent until proven guilty ... + + for (uint32 i = 0; i < Info.Fragments.size(); i++) + { + BOOL Result; + DWORD BytesReturned; + + //printf ("%3u", i); + + MoveData.ClusterCount = Info.Fragments[i].Length; + MoveData.StartingLcn.QuadPart = CurrentLCN; + MoveData.StartingVcn.QuadPart = CurrentVCN; + + MoveData.FileHandle = FileHandle; + + /* + printf ("\n"); + printf ("StartLCN: %I64u\n", MoveData.StartingLcn.QuadPart); + printf ("StartVCN: %I64u\n", MoveData.StartingVcn.QuadPart); + printf ("Clusters: %u (%I64u-%I64u --> %I64u-%I64u)\n", MoveData.ClusterCount, + Info.Fragments[i].StartLCN, + Info.Fragments[i].StartLCN + MoveData.ClusterCount, + MoveData.StartingLcn.QuadPart, + MoveData.StartingLcn.QuadPart + MoveData.ClusterCount - 1); + printf ("\n"); + */ + + Result = DeviceIoControl + ( + Handle, + FSCTL_MOVE_FILE, + &MoveData, + sizeof (MoveData), + NULL, + 0, + &BytesReturned, + NULL + ); + + //printf ("\b\b\b"); + + if (Result == FALSE) + { + // + LPVOID lpMsgBuf; + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL ); + + + LocalFree( lpMsgBuf ); + // + + ReturnVal = false; + goto FinishUp; // yeah, bite me + } + + // Ok good. Now update our drive bitmap and file infos. + uint64 j; + for (j = 0; + j < Info.Fragments[i].Length; + j++) + { + SetClusterUsed (Info.Fragments[i].StartLCN + j, false); + SetClusterUsed (CurrentLCN + j, true); + //BitmapDetail[Info.Fragments[i].StartLCN + j].Allocated = false; + //BitmapDetail[CurrentLCN + j].Allocated = true; + } + + CurrentLCN += Info.Fragments[i].Length; + CurrentVCN += Info.Fragments[i].Length; + } + + // Update file info either way + FinishUp: + CloseHandle (FileHandle); + FileHandle = INVALID_HANDLE_VALUE; + GetClusterInfo (Files[FileIndice], FileHandle); + CloseHandle (FileHandle); + } + + return (ReturnVal); +} + + diff --git a/rosapps/fraginator/DriveVolume.h b/rosapps/fraginator/DriveVolume.h new file mode 100644 index 00000000000..ea9fad0e6e8 --- /dev/null +++ b/rosapps/fraginator/DriveVolume.h @@ -0,0 +1,157 @@ +/***************************************************************************** + + DriveVolume + + Class for opening a volume and getting information on it and defragging it + and stuff. + +*****************************************************************************/ + + +#ifndef DRIVEVOLUME_H +#define DRIVEVOLUME_H + + +#include "Unfrag.h" +#include +#include + + +using namespace std; + +#pragma pack (push, 1) +typedef struct +{ + unsigned int Archive : 1; + unsigned int Compressed : 1; + unsigned int Directory : 1; + unsigned int Encrypted : 1; + unsigned int Hidden : 1; + unsigned int Normal : 1; + unsigned int Offline : 1; + unsigned int ReadOnly : 1; + unsigned int Reparse : 1; + unsigned int Sparse : 1; + unsigned int System : 1; + unsigned int Temporary : 1; + + // For defragmenting purposes and other information + unsigned int Unmovable : 1; // can we even touch it? + unsigned int Process : 1; // should we process it? + unsigned int AccessDenied : 1; // could we not open it? +} FileAttr; + + +typedef struct +{ + uint64 StartLCN; + uint64 Length; +} Extent; + + +typedef struct +{ + string Name; + uint32 DirIndice; // indice into directory list + uint64 Size; + uint64 Clusters; + FileAttr Attributes; + vector Fragments; +} FileInfo; + + +typedef vector FileList; + + +typedef struct +{ + string Name; + string Serial; + DWORD MaxNameLen; + string FileSystem; + uint64 ClusterCount; + uint32 ClusterSize; + uint64 TotalBytes; + uint64 FreeBytes; +} VolumeInfo; +#pragma pack (pop) + + +// Callback function for Scan() +// NOTE: Do *NOT* close the HANDLE given to you. It is provided for convenience, +// and is closed automatically by the function that calls you! +typedef bool (*ScanCallback) (FileInfo &Info, HANDLE &FileHandle, void *UserData); + + +extern bool BuildDBCallback (FileInfo &Info, HANDLE &FileHandle, void *UserData); + + +class DriveVolume +{ +public: + DriveVolume (); + ~DriveVolume (); + + bool Open (string Name); // opens the volume + void Close (void); + bool ObtainInfo (void); // retrieves drive geometry + bool GetBitmap (void); // gets drive bitmap + + // builds list of files on drive + // if QuitMonitor ever becomes true (ie from a separate thread) it will clean up and return + bool BuildFileList (bool &QuitMonitor, double &Progress); + + // Functions for accessing the volume bitmap + bool IsClusterUsed (uint64 Cluster); + void SetClusterUsed (uint64 Cluster, bool Used); + + DISK_GEOMETRY GetGeometry (void) { return (Geometry); } + VolumeInfo GetVolumeInfo (void) { return (VolInfo); } + + string GetRootPath (void) { return (RootPath); } + + // Scans drive starting from the root dir and calls a user defined function + // for each file/directory encountered. void* UserData is passed to this + // function so you can give it some good ol' fashioned context. + bool Scan (ScanCallback Callback, void *UserData); + + // Retrieve a directory string from the file database + string &GetDBDir (uint32 Indice); + uint32 GetDBDirCount (void); + // Retrieve file strings/info from the file database + FileInfo &GetDBFile (uint32 Indice); + uint32 GetDBFileCount (void); + // Kill it! + uint32 RemoveDBFile (uint32 Indice); + + // This is for actual defragmenting! It will automatically update the drive bitmap. + // Will not move any other files out of the way. + // Failure (return value of false) means that something is in the way. + bool MoveFileDumb (uint32 FileIndice, uint64 NewLCN); + + // Look for a range of sequential free clusters + // Returns true if one could be found, false if not + bool FindFreeRange (uint64 StartLCN, uint64 ReqLength, uint64 &LCNResult); + +private: + friend bool BuildDBCallback (FileInfo &Info, HANDLE &FileHandle, void *UserData); + + // DirPrefix should be in the form "drive:\\path\\" ie, C:\CRAP\ . + bool ScanDirectory (string DirPrefix, ScanCallback Callback, void *UserData); + + // given a file's attributes, should it be processed or not? + bool ShouldProcess (FileAttr Attr); + + bool GetClusterInfo (FileInfo &Info, HANDLE &HandleResult); + + VolumeInfo VolInfo; + FileList Files; + vector Directories; // Directories[Files[x].DirIndice] + string RootPath; // ie, C:\ . + HANDLE Handle; + DISK_GEOMETRY Geometry; + uint32 *BitmapDetail; +}; + + +#endif // DRIVEVOLUME_H diff --git a/rosapps/fraginator/Fraginator Motif Icon.bmp b/rosapps/fraginator/Fraginator Motif Icon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b8d412e8227965d96e06caeb8858fc2bba4fb137 GIT binary patch literal 4438 zcmb7{zmD8C5XLDWbr2N?C@HxvRBPYBeE>IH2u_oR!c{2~m$wV(%m;Ci2S|}eaOYR> zn_Rvbk~2eTPq7K?ijsaDe)EUq?%Q84z2o*LzDIn1!{9c!zc_}Qe)Wtnt@J+Ai{bE}T7kj(w|L$5or0?S6ydLl& zgms7$>8atvtL7uYsqYa#F-Xr|Gau8nXIl9X(rTj{u z!9qZpFV0DD(F1~U*d?uC(GV`ABwk5)X`(-OBJ8e&l9o6FPT(tyYs&)%D$j5SKD^Gu zX`8Va){x??>Nob00X0suz}1wls=nn>4=uhd6eerl>L>9m-IOU!V9i?|couKVG$a$u zHa?|%kO1R!Y|R_{Va{qyrrG00j`C9cHUSvWL^H>SGZbH`&L&%#r!XQlHd7p@94wpN zVjm77v&z_BQ#~bLSSgw+DmHF;)Q0CbNQz{(lrx@WeX%JAN2N}!su4Vuy(P{~K(Q{V zRi5(y@h@s0>R#0Hc`0;-r{$7yOj+V}mmjj8Sn&^{f19v8f$&uf)>(<_CSe<%wUhsn zy-h&3Jd~h`b*!;A!5g0GcIP_c5l+hBK|wV37gUA_FN2QsEOu#q6W>VT5r_77YL4TR zCBR|h#9jM+txp<3LDB(t`OfmNZx-|a^Uxf0{I~E+{C@tCN(0{Dc2QhjB?k}~+h}(Qo+k`RsE|sBP*+820`QbFF>wlkVX<27GCI{+^(4 zhsXNlryLixrMde4Shk>nwpUNqZnk>0M zIN1_SE(;*5Cw|Nva$0g>!lOU5Ix$kX`Hd*6Q=h%Amu|@N*#iH!X5a?M+8XVPereRv=f6v6F9iznlDf|lgFCYpJK z<^aSbLh|4?nmhnWu42K9qs6?`W|4zSZy4+cIvBBS|6}Aaok_x^ktB8FHabO-81>j+ zWddYGN?+xWB5`5twPwBFAE#xQxPWXzU2Y@(oHl0l1}?nefPn9?3*@#x-DN}xDpw2r jtmf8Mj literal 0 HcmV?d00001 diff --git a/rosapps/fraginator/Fraginator.cpp b/rosapps/fraginator/Fraginator.cpp new file mode 100644 index 00000000000..e80bb06a16e --- /dev/null +++ b/rosapps/fraginator/Fraginator.cpp @@ -0,0 +1,58 @@ +/***************************************************************************** + + Fraginator + +*****************************************************************************/ + + +#include "Fraginator.h" +#include "Mutex.h" +#include "DriveVolume.h" +#include "Defragment.h" +#include "MainDialog.h" +#include "resource.h" +#include + + +HINSTANCE GlobalHInstance = NULL; +Defragment *Defrag = NULL; + + +int WINAPI WinMain (HINSTANCE HInstance, HINSTANCE HPrevInstance, LPSTR CmdLine, int ShowCmd) +{ + INITCOMMONCONTROLSEX InitControls; + + // debugging crap +#ifndef NDEBUG + _CrtSetDbgFlag (_CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG)); + _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDOUT); + _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDOUT); + _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDOUT); +#endif + + GlobalHInstance = HInstance; + + // We want our progress bar! NOW! + InitControls.dwSize = sizeof (InitControls); + InitControls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx (&InitControls); + + if (!CheckWinVer()) + { + MessageBox (GetDesktopWindow(), "Sorry, this program requires Windows 2000.", "Error", MB_OK); + return (0); + } + + DialogBox (HInstance, MAKEINTRESOURCE (IDD_MAIN), GetDesktopWindow(), MainDialogProc); + +#if 0 + AllocConsole (); + if (_CrtDumpMemoryLeaks ()) + MessageBox (NULL, "Click OK to quit", "Leaks", MB_OK); +#endif + + return (0); +} diff --git a/rosapps/fraginator/Fraginator.dsp b/rosapps/fraginator/Fraginator.dsp new file mode 100644 index 00000000000..66b387b2372 --- /dev/null +++ b/rosapps/fraginator/Fraginator.dsp @@ -0,0 +1,186 @@ +# Microsoft Developer Studio Project File - Name="Fraginator" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=Fraginator - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Fraginator.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Fraginator.mak" CFG="Fraginator - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Fraginator - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Fraginator - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Fraginator - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /G6 /Gr /MT /W3 /GX /Ox /Ot /Og /Oi /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copying to Program Files ... +PostBuild_Cmds=copy Release\Fraginator.exe "c:\Program Files\Fraginator\Fraginator.exe" +# End Special Build Tool + +!ELSEIF "$(CFG)" == "Fraginator - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "Fraginator - Win32 Release" +# Name "Fraginator - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Defragment.cpp +# End Source File +# Begin Source File + +SOURCE=.\DriveVolume.cpp +# End Source File +# Begin Source File + +SOURCE=.\Fraginator.cpp +# End Source File +# Begin Source File + +SOURCE=.\MainDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\ReportDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\Unfrag.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\Defragment.h +# End Source File +# Begin Source File + +SOURCE=.\DriveVolume.h +# End Source File +# Begin Source File + +SOURCE=.\Fraginator.h +# End Source File +# Begin Source File + +SOURCE=.\MainDialog.h +# End Source File +# Begin Source File + +SOURCE=.\Mutex.h +# End Source File +# Begin Source File + +SOURCE=.\ReportDialog.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\Unfrag.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\default1.bin +# End Source File +# Begin Source File + +SOURCE=".\Fraginator Help - Fraginator Icon.bmp" +# End Source File +# Begin Source File + +SOURCE=".\Fraginator Motif Icon.bmp" +# End Source File +# Begin Source File + +SOURCE=.\Fraginator.rc +# End Source File +# Begin Source File + +SOURCE=.\icon1.ico +# End Source File +# End Group +# End Target +# End Project diff --git a/rosapps/fraginator/Fraginator.dsw b/rosapps/fraginator/Fraginator.dsw new file mode 100644 index 00000000000..3bd9b6d3e79 --- /dev/null +++ b/rosapps/fraginator/Fraginator.dsw @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Fraginator"=.\Fraginator.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "unfrag"=.\unfrag.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/rosapps/fraginator/Fraginator.exe b/rosapps/fraginator/Fraginator.exe new file mode 100644 index 0000000000000000000000000000000000000000..2ef93897ce3bcae25e5bf1554463d7d2dd5e822e GIT binary patch literal 122880 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 r^wzQkmPg>BvySv}#BmRddtlrH;~p6Iz_ + + +int WINAPI WinMain (HINSTANCE HInstance, HINSTANCE HPrevInstance, LPSTR CmdLine, int ShowCmd); +Defragment *StartDefragBox (string Drive, DefragType Method); + + +extern HINSTANCE GlobalHInstance; +extern Defragment *Defrag; + + +#endif // FRAGINATOR_H \ No newline at end of file diff --git a/rosapps/fraginator/Fraginator.mak b/rosapps/fraginator/Fraginator.mak new file mode 100644 index 00000000000..30cfd628dc5 --- /dev/null +++ b/rosapps/fraginator/Fraginator.mak @@ -0,0 +1,224 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on Fraginator.dsp +!IF "$(CFG)" == "" +CFG=Fraginator - Win32 Debug +!MESSAGE No configuration specified. Defaulting to Fraginator - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Fraginator - Win32 Release" && "$(CFG)" != "Fraginator - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Fraginator.mak" CFG="Fraginator - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Fraginator - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Fraginator - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Fraginator - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +ALL : "$(OUTDIR)\Fraginator.exe" + + +CLEAN : + -@erase "$(INTDIR)\Defragment.obj" + -@erase "$(INTDIR)\DriveVolume.obj" + -@erase "$(INTDIR)\Fraginator.obj" + -@erase "$(INTDIR)\Fraginator.res" + -@erase "$(INTDIR)\MainDialog.obj" + -@erase "$(INTDIR)\ReportDialog.obj" + -@erase "$(INTDIR)\Unfrag.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(OUTDIR)\Fraginator.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /G6 /Gr /MT /W3 /GX /Ox /Ot /Og /Oi /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\Fraginator.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\Fraginator.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Fraginator.bsc" +BSC32_SBRS= \ + +LINK32=xilink6.exe +LINK32_FLAGS=comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"$(OUTDIR)\Fraginator.exe" +LINK32_OBJS= \ + "$(INTDIR)\Defragment.obj" \ + "$(INTDIR)\DriveVolume.obj" \ + "$(INTDIR)\Fraginator.obj" \ + "$(INTDIR)\MainDialog.obj" \ + "$(INTDIR)\ReportDialog.obj" \ + "$(INTDIR)\Unfrag.obj" \ + "$(INTDIR)\Fraginator.res" + +"$(OUTDIR)\Fraginator.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +SOURCE="$(InputPath)" +PostBuild_Desc=Copying to Program Files ... +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +ALL : $(DS_POSTBUILD_DEP) + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\Fraginator.exe" + copy Release\Fraginator.exe "c:\Program Files\Fraginator\Fraginator.exe" + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "Fraginator - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +ALL : "$(OUTDIR)\Fraginator.exe" + + +CLEAN : + -@erase "$(INTDIR)\Defragment.obj" + -@erase "$(INTDIR)\DriveVolume.obj" + -@erase "$(INTDIR)\Fraginator.obj" + -@erase "$(INTDIR)\Fraginator.res" + -@erase "$(INTDIR)\MainDialog.obj" + -@erase "$(INTDIR)\ReportDialog.obj" + -@erase "$(INTDIR)\Unfrag.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(OUTDIR)\Fraginator.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\Fraginator.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\Fraginator.res" /d "_DEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Fraginator.bsc" +BSC32_SBRS= \ + +LINK32=xilink6.exe +LINK32_FLAGS=comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /debug /machine:I386 /out:"$(OUTDIR)\Fraginator.exe" +LINK32_OBJS= \ + "$(INTDIR)\Defragment.obj" \ + "$(INTDIR)\DriveVolume.obj" \ + "$(INTDIR)\Fraginator.obj" \ + "$(INTDIR)\MainDialog.obj" \ + "$(INTDIR)\ReportDialog.obj" \ + "$(INTDIR)\Unfrag.obj" \ + "$(INTDIR)\Fraginator.res" + +"$(OUTDIR)\Fraginator.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("Fraginator.dep") +!INCLUDE "Fraginator.dep" +!ELSE +!MESSAGE Warning: cannot find "Fraginator.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "Fraginator - Win32 Release" || "$(CFG)" == "Fraginator - Win32 Debug" +SOURCE=.\Defragment.cpp + +"$(INTDIR)\Defragment.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\DriveVolume.cpp + +"$(INTDIR)\DriveVolume.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\Fraginator.cpp + +"$(INTDIR)\Fraginator.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\MainDialog.cpp + +"$(INTDIR)\MainDialog.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\ReportDialog.cpp + +"$(INTDIR)\ReportDialog.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\Unfrag.cpp + +"$(INTDIR)\Unfrag.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\Fraginator.rc + +"$(INTDIR)\Fraginator.res" : $(SOURCE) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + + +!ENDIF + diff --git a/rosapps/fraginator/Fraginator.rc b/rosapps/fraginator/Fraginator.rc new file mode 100644 index 00000000000..c243fabd2a1 --- /dev/null +++ b/rosapps/fraginator/Fraginator.rc @@ -0,0 +1,241 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAIN DIALOGEX 0, 0, 346, 103 +STYLE DS_SETFONT | DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_DRIVES_LIST,78,52,29,111,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_METHODS_LIST,135,52,77,79,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_PRIORITY_LIST,223,52,59,91,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Start",IDC_STARTSTOP,294,7,45,15 + PUSHBUTTON "Help",ID_MAIN_HELP,294,28,45,15 + PUSHBUTTON "Exit",IDC_QUIT,294,49,45,15 + CONTROL 110,IDC_STATIC,"Static",SS_BITMAP | SS_SUNKEN | + WS_BORDER,7,7,63,58 + LTEXT "Choose a drive:",IDC_STATIC,78,40,50,8 + LTEXT "Choose an action:",IDC_STATIC,135,40,58,8 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER | + 0x1,7,71,299,10 + CONTROL "Static",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | + SS_SUNKEN | WS_GROUP,7,86,332,10 + LTEXT "I am a monkey, hear me eeK",IDC_WISECRACKS,78,15,91,8 + LTEXT "100.00%",IDC_PERCENT,311,71,28,8,0,WS_EX_RIGHT + LTEXT "Process Priority:",IDC_STATIC,223,40,51,8 +END + +IDD_REPORT DIALOG 0, 0, 391, 169 +STYLE DS_SETFONT | WS_POPUP | WS_CAPTION +CAPTION "Report" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Bytes",IDC_BYTES,7,148,50,14 + DEFPUSHBUTTON "Kilobytes",IDC_KILOBYTES,61,148,50,14 + DEFPUSHBUTTON "Megabytes",IDC_MEGABYTES,115,148,50,14 + DEFPUSHBUTTON "Gigabytes",IDC_GIGABYTES,169,148,50,14 + DEFPUSHBUTTON "OK",IDC_REPORTOK,334,148,50,14 + RTEXT "Volume",IDC_STATIC,7,7,24,8 + LTEXT "Capacity",IDC_STATIC,7,51,28,8 + RTEXT "(Drive Letter)",IDC_DRIVELETTER,63,7,117,10,SS_SUNKEN + RTEXT "(Disk Size, Bytes)",IDC_DISKSIZEBYTES,63,51,117,10, + SS_SUNKEN + RTEXT "(Disk Size, Clusters)",IDC_DISKSIZECLUSTERS,63,73,117, + 10,SS_SUNKEN + LTEXT "Total clusters",IDC_STATIC,7,73,43,8 + RTEXT "(Cluster size)",IDC_DISKCLUSTERSIZE,63,84,117,10, + SS_SUNKEN + LTEXT "Cluster size",IDC_STATIC,7,84,36,8 + RTEXT "(Files count)",IDC_FILESCOUNT,267,18,117,10,SS_SUNKEN + RTEXT "(Files size, bytes)",IDC_FILESSIZEBYTES,267,29,117,10, + SS_SUNKEN + LTEXT "# of files",IDC_STATIC,194,18,28,8 + LTEXT "Total size",IDC_STATIC,194,29,31,8 + LTEXT "Size on disk",IDC_STATIC,194,40,39,8 + RTEXT "(Total size, bytes)",IDC_FILESSIZEONDISK,267,40,117,10, + SS_SUNKEN + RTEXT "(Files slack bytes)",IDC_FILESSLACKBYTES,267,51,117,10, + SS_SUNKEN + LTEXT "Wasted slack",IDC_STATIC,194,51,44,8 + RTEXT "(Disk Free, Bytes)",IDC_DISKFREEBYTES,63,62,117,10, + SS_SUNKEN + LTEXT "Free space",IDC_STATIC,7,62,36,8 + RTEXT "(Files fragmented, count)",IDC_FILESFRAGGED,267,62,117, + 10,SS_SUNKEN + LTEXT "Fragmented files",IDC_STATIC,194,62,52,8 + RTEXT "(Dirs count)",IDC_DIRSCOUNT,267,7,117,10,SS_SUNKEN + LTEXT "# of directories",IDC_STATIC,194,7,48,8 + RTEXT "File System",IDC_STATIC,7,40,36,8 + RTEXT "(File System Name)",IDC_FILESYSTEM,63,40,117,10, + SS_SUNKEN + RTEXT "Volume Label",IDC_STATIC,7,18,44,8 + RTEXT "(Volume Name)",IDC_VOLUMELABEL,63,18,117,10,SS_SUNKEN + RTEXT "Serial",IDC_STATIC,7,29,18,8 + RTEXT "(Volume Serial)",IDC_VOLUMESERIAL,63,29,117,10, + SS_SUNKEN + RTEXT "(Average Frags Per File)",IDC_AVERAGEFRAGS,267,73,117, + 10,SS_SUNKEN + LTEXT "Average fragments per file",IDC_STATIC,194,73,60,20 + LTEXT "XX.X% of the files on this drive are fragmented. It is recommended that you perform a SSSSSSS defragmentation.", + IDC_RECOMMEND,7,106,377,38,SS_SUNKEN + LTEXT "Recommendations:",IDC_STATIC,7,96,62,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 339 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + END + + IDD_REPORT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 384 + TOPMARGIN, 7 + BOTTOMMARGIN, 162 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", " " + VALUE "FileDescription", "Fraginator" + VALUE "FileVersion", "1.03" + VALUE "InternalName", "Fraginator" + VALUE "LegalCopyright", "Copyright © 2000-2002 Rick Brewster" + VALUE "OriginalFilename", "Fraginator.exe" + VALUE "ProductName", "Fraginator" + VALUE "ProductVersion", "1.03" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_LOGO BITMAP "Fraginator Motif Icon.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "default1.bin" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/rosapps/fraginator/Fraginator.sln b/rosapps/fraginator/Fraginator.sln new file mode 100644 index 00000000000..8996ce9b5a3 --- /dev/null +++ b/rosapps/fraginator/Fraginator.sln @@ -0,0 +1,27 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Fraginator", "Fraginator.vcproj", "{7CB0DB3F-D4AB-4A99-807F-C56CC9F0B19C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unfrag", "unfrag.vcproj", "{8E7E76C1-739B-46E5-99C2-A0504558164B}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {7CB0DB3F-D4AB-4A99-807F-C56CC9F0B19C}.Debug.ActiveCfg = Debug|Win32 + {7CB0DB3F-D4AB-4A99-807F-C56CC9F0B19C}.Debug.Build.0 = Debug|Win32 + {7CB0DB3F-D4AB-4A99-807F-C56CC9F0B19C}.Release.ActiveCfg = Release|Win32 + {7CB0DB3F-D4AB-4A99-807F-C56CC9F0B19C}.Release.Build.0 = Release|Win32 + {8E7E76C1-739B-46E5-99C2-A0504558164B}.Debug.ActiveCfg = Debug|Win32 + {8E7E76C1-739B-46E5-99C2-A0504558164B}.Debug.Build.0 = Debug|Win32 + {8E7E76C1-739B-46E5-99C2-A0504558164B}.Release.ActiveCfg = Release|Win32 + {8E7E76C1-739B-46E5-99C2-A0504558164B}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/rosapps/fraginator/Fraginator.suo b/rosapps/fraginator/Fraginator.suo new file mode 100644 index 0000000000000000000000000000000000000000..c674481aaf891bf16f184dc0e84d36fc73e2160f GIT binary patch literal 14336 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rosapps/fraginator/MainDialog.cpp b/rosapps/fraginator/MainDialog.cpp new file mode 100644 index 00000000000..51dc8724b95 --- /dev/null +++ b/rosapps/fraginator/MainDialog.cpp @@ -0,0 +1,574 @@ +#include "unfrag.h" +#include "MainDialog.h" +#include "resource.h" +#include "Fraginator.h" +#include "Defragment.h" +#include "ReportDialog.h" + + +vector DrivesList; +LRESULT AnalyzeID; +LRESULT FastID; +LRESULT ExtensiveID; +bool QuitWhenDone; +bool Stopping; + + +LRESULT PriHighID; +LRESULT PriAboveNormID; +LRESULT PriNormalID; +LRESULT PriBelowNormID; +LRESULT PriIdleID; + + +void InitDialog (HWND Dlg); +void UpdateDefragInfo (HWND Dlg); +void UpdatePriority (HWND Dlg); +string GetDefaultTitle (void); +string GetDefragTitle (void); +void SetDisables (HWND Dlg); +INT_PTR CALLBACK MainDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam); + + +static void InitDialog (HWND Dlg) +{ + // Make internal list + DWORD DriveMask; + HWND DlgItem; + int d; + + // Clear out wisecracks line for now + SetDlgItemText (Dlg, IDC_WISECRACKS, "\"Defrag, baby!\""); + + // Make list of logical drives + DrivesList.resize (0); + DriveMask = GetLogicalDrives (); + + for (d = 0; d < 26; d++) + { + if (DriveMask & (1 << d)) + { + string Name; + + Name = (char)('A' + d); + Name += ':'; + DrivesList.push_back (Name); + } + } + + // Give list to dropdown list + DlgItem = GetDlgItem (Dlg, IDC_DRIVES_LIST); + SendMessage (DlgItem, CB_RESETCONTENT, 0, 0); + for (d = 0; d < DrivesList.size(); d++) + { + SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) DrivesList[d].c_str()); + } + + // Put in defrag methods + DlgItem = GetDlgItem (Dlg, IDC_METHODS_LIST); + SendMessage (DlgItem, CB_RESETCONTENT, 0, 0); + AnalyzeID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) "Analyze Only"); + FastID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) "Fast Defrag"); + ExtensiveID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) "Extensive Defrag"); + + // Set up process priorities + DlgItem = GetDlgItem (Dlg, IDC_PRIORITY_LIST); + SendMessage (Dlg, CB_RESETCONTENT, 0, 0); + PriHighID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) "High"); + PriAboveNormID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) "Above Normal"); + PriNormalID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) "Normal"); + PriBelowNormID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) "Below Normal"); + PriIdleID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) "Idle"); + UpdatePriority (Dlg); + + // Reset texts and progress meters + SendDlgItemMessage (Dlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM) ""); + SendDlgItemMessage (Dlg, IDC_PERCENT, WM_SETTEXT, 0, (LPARAM) ""); + SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM (0, 10000)); + SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETPOS, 0, 0); + + return; +} + + +void UpdateDefragInfo (HWND Dlg) +{ + char PercentText[100]; + static double OldPercent = 200.0f; + static string OldStatus = "Non"; + string NewStatus; + double NewPercent; + + if (Defrag == NULL) + return; + + NewPercent = Defrag->GetStatusPercent (); + if (NewPercent > 100.0f) + NewPercent = 100.0f; + if (NewPercent < 0.0f) + NewPercent = 0.0f; + if (NewPercent != OldPercent) + { + sprintf (PercentText, "%6.2f%%", NewPercent); + SendDlgItemMessage (Dlg, IDC_PERCENT, WM_SETTEXT, 0, (LPARAM) PercentText); + SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETPOS, + (WPARAM) (int)(NewPercent * 100.0f), 0); + OldPercent = NewPercent; + } + + NewStatus = Defrag->GetStatusString (); + if (NewStatus != OldStatus) + { // Change & characters to && to avoid underlining + string Status; + string::iterator it; + + Status = NewStatus; + it = Status.begin (); + while (it < Status.end()) + { + if (*it == '&') + { + Status.insert (it, 1, '&'); + it++; + } + + it++; + } + + SendDlgItemMessage (Dlg, IDC_STATUS, WM_SETTEXT, 0, + (LPARAM) Status.c_str()); + + OldStatus = NewStatus; + } + + return; +} + + +string GetDefaultTitle (void) +{ + string DefaultText; + + DefaultText = string(string(APPNAME_GUI) + string(" v") + string(APPVER_STR) + + string(" (C) 2000 by Rick Brewster")); + + return (DefaultText); +} + + +string GetDefragTitle (void) +{ + string DefragText; + char Percent[10]; + + sprintf (Percent, "%.2f%%", Defrag->GetStatusPercent()); + + DefragText = GetDefaultTitle (); + if (Defrag != NULL) + { + DefragText = string(Percent) + string (" - ") + Defrag->GetVolume().GetRootPath() + + string (" - ") + DefragText; + } + + return (DefragText); +} + + +void SetDisables (HWND Dlg) +{ + // If a defrag is in process, set 'Start' button to say 'Stop' and disable + // the Select Drive and Select Action controls + if (Defrag != NULL && !Defrag->IsDoneYet() && !Defrag->HasError()) + { + SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), WM_SETTEXT, 0, (LPARAM) "Stop"); + EnableWindow (GetDlgItem (Dlg, IDC_DRIVES_LIST), FALSE); + EnableWindow (GetDlgItem (Dlg, IDC_METHODS_LIST), FALSE); + } + else + { + SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), WM_SETTEXT, 0, (LPARAM) "Start"); + EnableWindow (GetDlgItem (Dlg, IDC_STARTSTOP), TRUE); + EnableWindow (GetDlgItem (Dlg, IDC_QUIT), TRUE); + EnableWindow (GetDlgItem (Dlg, IDC_DRIVES_LIST), TRUE); + EnableWindow (GetDlgItem (Dlg, IDC_METHODS_LIST), TRUE); + } + + return; +} + + +void UpdatePriority (HWND Dlg) +{ + LRESULT Id; + DWORD Priority; + + Id = SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_GETCURSEL, 0, 0); + + if (Id == PriHighID) + Priority = HIGH_PRIORITY_CLASS; + else + if (Id == PriAboveNormID) + Priority = ABOVE_NORMAL_PRIORITY_CLASS; + else + if (Id == PriNormalID) + Priority = NORMAL_PRIORITY_CLASS; + else + if (Id == PriBelowNormID) + Priority = BELOW_NORMAL_PRIORITY_CLASS; + else + if (Id == PriIdleID) + Priority = IDLE_PRIORITY_CLASS; + else + return; + + SetPriorityClass (GetCurrentProcess(), Priority); + return; +} + + +// Save settings (ie, process priority and defrag type options) +bool GetRegKeys (HKEY *RegKeyResult) +{ + HKEY RegKey; + LONG Error; + + Error = RegCreateKeyEx + ( + HKEY_CURRENT_USER, + "Software\\Fraginator", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &RegKey, + NULL + ); + + if (Error != ERROR_SUCCESS) + return (false); + + *RegKeyResult = RegKey; + return (true); +} + + +bool DoneRegKey (HKEY RegKey) +{ + RegCloseKey (RegKey); + return (true); +} + + +void SaveSettings (HWND Dlg) +{ + LRESULT DefragID; + DWORD DefragVal; + LRESULT PriID; + DWORD PriVal; + HKEY RegKey; + + DefragID = SendDlgItemMessage (Dlg, IDC_METHODS_LIST, CB_GETCURSEL, 0, 0); + PriID = SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_GETCURSEL, 0, 0); + + // Action + if (DefragID == AnalyzeID) + DefragVal = (DWORD) DefragAnalyze; + else + if (DefragID == FastID) + DefragVal = (DWORD) DefragFast; + else + if (DefragID == ExtensiveID) + DefragVal = (DWORD) DefragExtensive; + + // Process Priority + if (PriID == PriHighID) + PriVal = HIGH_PRIORITY_CLASS; + else + if (PriID == PriAboveNormID) + PriVal = ABOVE_NORMAL_PRIORITY_CLASS; + else + if (PriID == PriNormalID) + PriVal = NORMAL_PRIORITY_CLASS; + else + if (PriID == PriBelowNormID) + PriVal = BELOW_NORMAL_PRIORITY_CLASS; + else + if (PriID == PriIdleID) + PriVal = IDLE_PRIORITY_CLASS; + + if (!GetRegKeys (&RegKey)) + return; + + RegSetValueEx + ( + RegKey, + "Default Action", + 0, + REG_DWORD, + (CONST BYTE *)&DefragVal, + sizeof (DefragVal) + ); + + RegSetValueEx + ( + RegKey, + "Process Priority", + 0, + REG_DWORD, + (CONST BYTE *)&PriVal, + sizeof (PriVal) + ); + + DoneRegKey (RegKey); + return; +} + + +void LoadSettings (HWND Dlg) +{ + DefragType DType; + DWORD DTypeVal; + LRESULT DefragID; + DWORD PriVal; + LRESULT PriID; + HKEY RegKey; + DWORD RegType; + DWORD RegSize; + LONG Error; + + if (!GetRegKeys (&RegKey)) + return; + + RegSize = sizeof (DTypeVal); + RegType = REG_DWORD; + + Error = RegQueryValueEx + ( + RegKey, + "Default Action", + 0, + &RegType, + (BYTE *)&DTypeVal, + &RegSize + ); + + if (Error != ERROR_SUCCESS) + DTypeVal = DefragAnalyze; + + Error = RegQueryValueEx + ( + RegKey, + "Process Priority", + 0, + &RegType, + (BYTE *)&PriVal, + &RegSize + ); + + DoneRegKey (RegKey); + + if (Error != ERROR_SUCCESS) + PriVal = NORMAL_PRIORITY_CLASS; + + DType = (DefragType) DTypeVal; + switch (DType) + { + default: + case DefragAnalyze: + DefragID = AnalyzeID; + break; + + case DefragFast: + DefragID = FastID; + break; + + case DefragExtensive: + DefragID = ExtensiveID; + break; + } + + switch (PriVal) + { + case HIGH_PRIORITY_CLASS: + PriID = PriHighID; + break; + + case ABOVE_NORMAL_PRIORITY_CLASS: + PriID = PriAboveNormID; + break; + + default: + case NORMAL_PRIORITY_CLASS: + PriID = PriNormalID; + break; + + case BELOW_NORMAL_PRIORITY_CLASS: + PriID = PriBelowNormID; + break; + + case IDLE_PRIORITY_CLASS: + PriID = PriIdleID; + break; + } + + SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_SETCURSEL, PriID, 0); + SendDlgItemMessage (Dlg, IDC_METHODS_LIST, CB_SETCURSEL, DefragID, 0); + return; +} + + +#define IDLETIME 25 +string OldWindowText = ""; + +INT_PTR CALLBACK MainDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam) +{ + static bool ReEntrance = false; + + switch (Msg) + { + case WM_INITDIALOG: + Stopping = false; + SetWindowText (Dlg, GetDefaultTitle().c_str()); + SetDisables (Dlg); + InitDialog (Dlg); + SetTimer (Dlg, 1, IDLETIME, NULL); + SetClassLong (Dlg, GCL_HICON, (LONG) LoadIcon (GlobalHInstance, MAKEINTRESOURCE(IDI_ICON))); + QuitWhenDone = false; + LoadSettings (Dlg); + UpdatePriority (Dlg); + return (1); + + + case WM_TIMER: + if (Defrag != NULL && !ReEntrance) + { + string NewTitle; + + SendMessage (Dlg, WM_UPDATEINFO, 0, 0); + + NewTitle = GetDefragTitle (); + if (NewTitle != OldWindowText) + { + OldWindowText = NewTitle; + SetWindowText (Dlg, NewTitle.c_str()); + } + + if (Defrag->IsDoneYet() || Defrag->HasError()) + { // This is the code executed when defragging is finished (or stopped :) + if (Defrag->GetDefragType() == DefragAnalyze && + !Defrag->HasError() && + !Stopping) + { // Show report + ReEntrance = true; + + DialogBoxParam (GlobalHInstance, MAKEINTRESOURCE (IDD_REPORT), + Dlg, ReportDialogProc, (LPARAM) Defrag); + + ReEntrance = false; + } + + delete Defrag; + Defrag = NULL; + SetDisables (Dlg); + SetWindowText (Dlg, GetDefaultTitle().c_str()); + + Stopping = false; + + if (QuitWhenDone) + SendMessage (GetDlgItem (Dlg, IDC_QUIT), BM_CLICK, 0, 0); + } + } + + SetTimer (Dlg, 1, IDLETIME, NULL); + return (0); + + + case WM_UPDATEINFO: + UpdateDefragInfo (Dlg); + return (1); + + + case WM_CLOSE: + SendMessage (GetDlgItem (Dlg, IDC_QUIT), BM_CLICK, 0, 0); + return (1); + + + case WM_COMMAND: + switch (LOWORD(WParam)) + { + case IDC_PRIORITY_LIST: + UpdatePriority (Dlg); + return (1); + + + case ID_MAIN_HELP: + ShellExecute (Dlg, "open", "Fraginator.chm", "", ".", SW_SHOW); + return (1); + + + case IDC_QUIT: + if (Defrag == NULL) + { // This is the code executing when quitting + SaveSettings (Dlg); + EndDialog (Dlg, 0); + } + else + { // Tell defragging to finish and disable our button + QuitWhenDone = true; + SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), BM_CLICK, 0, 0); + EnableWindow (GetDlgItem (Dlg, IDC_QUIT), FALSE); + } + return (1); + + + case IDC_STARTSTOP: + if (Defrag == NULL) + { // "Start" + char Drive[10]; + LRESULT ID; + DefragType Method; + HANDLE H; + + if (Defrag != NULL) + return (1); + + SendMessage (GetDlgItem (Dlg, IDC_DRIVES_LIST), WM_GETTEXT, + sizeof (Drive) - 1, (LPARAM) Drive); + + if (strlen(Drive) != 2 || Drive[1] != ':') + return (1); + + ID = SendMessage (GetDlgItem (Dlg, IDC_METHODS_LIST), CB_GETCURSEL, 0, 0); + Method = DefragInvalid; + if (ID == AnalyzeID) + Method = DefragAnalyze; + else + if (ID == FastID) + Method = DefragFast; + else + if (ID == ExtensiveID) + Method = DefragExtensive; + + if (Method != DefragInvalid) + { + Defrag = StartDefragThread (Drive, Method, H); + Defrag->SetDoLimitLength (false); + SetWindowText (Dlg, GetDefragTitle().c_str()); + SetDisables (Dlg); + } + } + else + { // "Stop" + Stopping = true; + Defrag->Stop (); + EnableWindow (GetDlgItem (Dlg, IDC_STARTSTOP), FALSE); + EnableWindow (GetDlgItem (Dlg, IDC_QUIT), FALSE); + } + return (1); + } + } + + // Otherwise, return 0 to say we did not process the message. + return (0); +} diff --git a/rosapps/fraginator/MainDialog.h b/rosapps/fraginator/MainDialog.h new file mode 100644 index 00000000000..88d5496a615 --- /dev/null +++ b/rosapps/fraginator/MainDialog.h @@ -0,0 +1,14 @@ +#ifndef MAINDIALOG_H +#define MAINDIALOG_H + + +#include + + +#define WM_UPDATEINFO (WM_USER + 1) + + +INT_PTR CALLBACK MainDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam); + + +#endif // MAINDIALOG_H \ No newline at end of file diff --git a/rosapps/fraginator/Mutex.h b/rosapps/fraginator/Mutex.h new file mode 100644 index 00000000000..5a36c9f4ff1 --- /dev/null +++ b/rosapps/fraginator/Mutex.h @@ -0,0 +1,78 @@ +/***************************************************************************** + + Mutex + +*****************************************************************************/ + + +#ifndef MUTEX_H +#define MUTEX_H + + +#include "Unfrag.h" + + +class Mutex +{ +public: + Mutex () + { + // NT only code begin ... Win9x disregards this part + SECURITY_ATTRIBUTES MutexAttribs; + + memset (&MutexAttribs, 0, sizeof (SECURITY_ATTRIBUTES)); + + MutexAttribs.bInheritHandle = false; + MutexAttribs.nLength = sizeof (SECURITY_ATTRIBUTES); + MutexAttribs.lpSecurityDescriptor = NULL; + // NT only code end + + Locked = false; + LockCount = 0; + MutexHandle = CreateMutex (&MutexAttribs, Locked, NULL); + + return; + } + + ~Mutex () + { + Lock (); + CloseHandle (MutexHandle); + } + + void Lock (void) + { + Locked = true; + WaitForSingleObject (MutexHandle, INFINITE); + LockCount += 1; + return; + } + + + void Unlock (void) + { + LockCount -= 1; + if (LockCount <= 0) + { + LockCount = 0; + Locked = false; + } + + ReleaseMutex (MutexHandle); + return; + } + + + bool IsLocked (void) + { + return (Locked); + } + +protected: + uint32 LockCount; + HANDLE MutexHandle; + bool Locked; +}; + + +#endif // MUTEX_H diff --git a/rosapps/fraginator/ReportDialog.cpp b/rosapps/fraginator/ReportDialog.cpp new file mode 100644 index 00000000000..4ddad62847a --- /dev/null +++ b/rosapps/fraginator/ReportDialog.cpp @@ -0,0 +1,231 @@ +#include "ReportDialog.h" +#include "unfrag.h" +#include "Fraginator.h" +#include "DriveVolume.h" +#include "Defragment.h" +#include "resource.h" + + +void SetReportInfo (HWND Dlg, DefragReport &Report, uint32 BytesDivisor, char *BytesUnits, bool Fractional) +{ + char Text[1000]; + char Text2[1000]; + char Text3[1000]; + + memset (Text, 0, sizeof (Text)); + + // Volume name + SetDlgItemText (Dlg, IDC_DRIVELETTER, Report.RootPath.c_str()); + + // Volume label + SetDlgItemText (Dlg, IDC_VOLUMELABEL, Defrag->GetVolume().GetVolumeInfo().Name.c_str()); + + // Volume Serial + SetDlgItemText (Dlg, IDC_VOLUMESERIAL, Defrag->GetVolume().GetVolumeInfo().Serial.c_str()); + + // File System + SetDlgItemText (Dlg, IDC_FILESYSTEM, Defrag->GetVolume().GetVolumeInfo().FileSystem.c_str()); + + // DiskSizeBytes + if (Fractional) + { + sprintf (Text, "%.2f %s", (double)(signed)(Report.DiskSizeBytes / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, Report.DiskSizeBytes / BytesDivisor); + strcat (Text, " "); + strcat (Text, BytesUnits); + } + + SetDlgItemText (Dlg, IDC_DISKSIZEBYTES, Text); + + // DiskFreeBytes + if (Fractional) + { + sprintf (Text, "%.2f %s", (double)(signed)(Defrag->GetVolume().GetVolumeInfo().FreeBytes / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, Defrag->GetVolume().GetVolumeInfo().FreeBytes / BytesDivisor); + strcat (Text, " "); + strcat (Text, BytesUnits); + } + SetDlgItemText (Dlg, IDC_DISKFREEBYTES, Text); + + // DiskSizeClusters + AddCommas (Text, Defrag->GetVolume().GetVolumeInfo().ClusterCount); + strcat (Text, " clusters"); + SetDlgItemText (Dlg, IDC_DISKSIZECLUSTERS, Text); + + // DiskClusterSize + sprintf (Text, "%u bytes", Defrag->GetVolume().GetVolumeInfo().ClusterSize); + SetDlgItemText (Dlg, IDC_DISKCLUSTERSIZE, Text); + + // DirsCount + AddCommas (Text, Report.DirsCount); + SetDlgItemText (Dlg, IDC_DIRSCOUNT, Text); + + // FilesCount + AddCommas (Text, Report.FilesCount); + SetDlgItemText (Dlg, IDC_FILESCOUNT, Text); + + // FilesFragged + sprintf (Text, "(%.2f%%)", Report.PercentFragged); + AddCommas (Text2, Report.FraggedFiles.size()); + sprintf (Text3, "%s %s", Text, Text2); + SetDlgItemText (Dlg, IDC_FILESFRAGGED, Text3); + + // Average Frags + sprintf (Text, "%.2f", Report.AverageFragments); + SetDlgItemText (Dlg, IDC_AVERAGEFRAGS, Text); + + // FilesSizeBytes + if (Fractional) + { + sprintf (Text, "%.2f %s", (double)(signed)(Report.FilesSizeBytes / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, Report.FilesSizeBytes / (uint64)BytesDivisor); + strcat (Text, " "); + strcat (Text, BytesUnits); + } + SetDlgItemText (Dlg, IDC_FILESSIZEBYTES, Text); + + // Files SizeOnDisk + if (Fractional) + { + sprintf (Text, "%.2f %s", (double)(signed)((Report.FilesSizeBytes + Report.FilesSlackBytes) / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, (Report.FilesSizeBytes + Report.FilesSlackBytes) / (uint64)BytesDivisor); + strcat (Text, " "); + strcat (Text, BytesUnits); + + } + SetDlgItemText (Dlg, IDC_FILESSIZEONDISK, Text); + + // FilesSlackBytes + if (Fractional) + { + sprintf (Text, "%.2f %s", (double)(signed)(Report.FilesSlackBytes / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, Report.FilesSlackBytes / BytesDivisor); + strcat (Text, " "); + strcat (Text, BytesUnits); + } + sprintf (Text2, "(%.2f%%)", Report.PercentSlack); + sprintf (Text3, "%s %s", Text2, Text); + SetDlgItemText (Dlg, IDC_FILESSLACKBYTES, Text3); + + // Recommendation + bool PFRec = false; // Recommend based off percent fragged files? + bool AFRec = false; // Recommend based off average fragments per file? + + if (Report.PercentFragged >= 5.0f) + PFRec = true; + + if (Report.AverageFragments >= 1.1f) + AFRec = true; + + strcpy (Text, "* "); + + if (PFRec) + { + sprintf + ( + Text2, + "%.2f%% of the files on this volume are fragmented. ", + Report.PercentFragged + ); + + strcat (Text, Text2); + } + + if (AFRec) + { + sprintf + ( + Text2, + "The average fragments per file (%.2f) indicates a high degree of fragmentation. ", + Report.AverageFragments + ); + + strcat (Text, Text2); + } + + if (Report.PercentFragged < 5.0f && Report.AverageFragments < 1.1f) + sprintf (Text, "* No defragmentation is necessary at this point."); + else + if (Report.PercentFragged < 15.0f && Report.AverageFragments < 1.3f) + strcat (Text, "It is recommended that you perform a Fast Defrag."); + else + strcat (Text, "It is recommended that you perform an Extensive Defrag."); + + // Should we recommend a smaller cluster size? + if (Report.PercentSlack >= 10.0f) + { + sprintf + ( + Text2, + "\n* A large amount of disk space (%.2f%%) is being lost " + "due to a large (%u bytes) cluster size. It is recommended " + "that you use a disk utility such as Partition Magic to " + "reduce the cluster size of this volume.", + Report.PercentSlack, + Defrag->GetVolume().GetVolumeInfo().ClusterSize + ); + + strcat (Text, Text2); + } + + SetDlgItemText (Dlg, IDC_RECOMMEND, Text); + + return; +} + + +INT_PTR CALLBACK ReportDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam) +{ + switch (Msg) + { + case WM_INITDIALOG: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1, "bytes", false); + return (1); + + case WM_COMMAND: + switch (LOWORD(WParam)) + { + case IDC_REPORTOK: + EndDialog (Dlg, 0); + return (1); + + case IDC_GIGABYTES: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1024*1024*1024, "GB", true); + return (1); + + case IDC_MEGABYTES: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1024*1024, "MB", false); + return (1); + + case IDC_KILOBYTES: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1024, "KB", false); + return (1); + + case IDC_BYTES: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1, "bytes", false); + return (1); + } + } + + return (0); +} diff --git a/rosapps/fraginator/ReportDialog.h b/rosapps/fraginator/ReportDialog.h new file mode 100644 index 00000000000..d5de5559bc7 --- /dev/null +++ b/rosapps/fraginator/ReportDialog.h @@ -0,0 +1,18 @@ +/***************************************************************************** + + ReportDialog + +*****************************************************************************/ + + +#ifndef REPORTDIALOG_H +#define REPORTDIALOG_H + + +#include + + +INT_PTR CALLBACK ReportDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam); + + +#endif // REPORTDIALOG_H \ No newline at end of file diff --git a/rosapps/fraginator/Unfrag.cpp b/rosapps/fraginator/Unfrag.cpp new file mode 100644 index 00000000000..23477fd9ce7 --- /dev/null +++ b/rosapps/fraginator/Unfrag.cpp @@ -0,0 +1,464 @@ +/***************************************************************************** + + Unfrag + +*****************************************************************************/ + + +#include "Unfrag.h" +#include "DriveVolume.h" +#include "Defragment.h" +#include + + +bool QuietMode = false; +bool VerboseMode = false; + + +// Makes sure we're in Windows 2000 +bool CheckWinVer (void) +{ + OSVERSIONINFO OSVersion; + + ZeroMemory (&OSVersion, sizeof (OSVersion)); + OSVersion.dwOSVersionInfoSize = sizeof (OSVersion); + GetVersionEx (&OSVersion); + + // Need Windows 2000! + + // Check for NT first + // Actually what we do is check that we're not on Win31+Win32s and that we're + // not in Windows 9x. It's possible that there could be more Windows "platforms" + // in the future and there's no sense in claiming incompatibility. + if (OSVersion.dwPlatformId == VER_PLATFORM_WIN32s || + OSVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + return (false); + } + + // Ok we're in Windows NT, now make sure we're in 2000 + if (OSVersion.dwMajorVersion < 5) + return (false); + + // Kew, we're in at least Windows 2000 ("NT 5.0") + return (true); +} + + +char *AddCommas (char *Result, uint64 Number) +{ + char Temp[128]; + int TempLen; + char *p = NULL; + int AddCommas = 0; + char *StrPosResult = NULL; + char *StrPosOrig = NULL; + + // we get the string form of the number, then we count down w/ AddCommas + // while copying the string from Temp1 to Result. when AddCommas % 3 == 1, + // slap in a commas as well, before the #. + sprintf (Temp, "%I64u", Number); + AddCommas = TempLen = strlen (Temp); + StrPosOrig = Temp; + StrPosResult = Result; + while (AddCommas) + { + if ((AddCommas % 3) == 0 && AddCommas != TempLen) // avoid stuff like ",345" + { + *StrPosResult = ','; + StrPosResult++; + } + + *StrPosResult = *StrPosOrig; + StrPosResult++; + StrPosOrig++; + + *StrPosResult = 0; + + AddCommas--; + } + + return (Result); +} + + +void PrintBanner (void) +{ + printf ("%s v%s\n", APPNAME_CLI, APPVER_STR); + printf ("%s\n", APPCOPYRIGHT); + printf ("\n"); + + return; +} + + +void FraggerHelp (void) +{ + printf ("Usage: unfrag drive: [...] <-f | -e>\n"); + printf ("\n"); + printf ("drive: : The drive to defrag. Should be two characters long, ie 'c:' or 'd:'.\n"); + printf (" Multiple drives may be given, and all will be simultaneously\n"); + printf (" defragmented using the same options.\n"); + printf ("-f : Do a fast defragmentation. Files that are not fragmented will not be\n"); + printf (" moved. Only one pass is made over the file list. Using this option\n"); + printf (" may result in not all files being defragmented, depending on\n"); + printf (" available disk space.\n"); + printf ("-e : Do an extensive defragmention. Files will be moved in an attempt to\n"); + printf (" defragment both files and free space.\n"); + + if (!CheckWinVer()) + { + printf ("\n"); + printf ("NOTE: This program requires Windows 2000, which is not presently running on\n"); + printf ("this system.\n"); + } + + return; +} + + +void __cdecl DefragThread (LPVOID parm) +{ + Defragment *Defrag; + + Defrag = (Defragment *) parm; + Defrag->Start (); + + _endthread (); + return; +} + + +Defragment *StartDefragThread (string Drive, DefragType Method, HANDLE &Handle) +{ + Defragment *Defragger; + unsigned long Thread; + + Defragger = new Defragment (Drive, Method); + //Thread = /*CreateThread*/ _beginthreadex (NULL, 0, DefragThread, Defragger, 0, &ThreadID); + Thread = _beginthread (DefragThread, 0, Defragger); + Handle = *((HANDLE *)&Thread); + return (Defragger); +} + + +// Main Initialization +int __cdecl main (int argc, char **argv) +{ + vector Drives; + vector Defrags; + DefragType DefragMode = DefragInvalid; + int d; + + PrintBanner (); + + // Parse command line arguments + bool ValidCmdLine = false; + for (int c = 0; c < argc; c++) + { + if (strlen(argv[c]) == 2 && argv[c][1] == ':') + { + Drives.push_back (strupr(argv[c])); + } + else + if (argv[c][0] == '-' || argv[c][0] == '/' && strlen(argv[c]) == 2) + { + switch (tolower(argv[c][1])) + { + case '?' : + case 'h' : + FraggerHelp (); + return (0); + + case 'f' : + if (DefragMode != DefragInvalid) + { + ValidCmdLine = false; + break; + } + DefragMode = DefragFast; + ValidCmdLine = true; + break; + + case 'e' : + if (DefragMode != DefragInvalid) + { + ValidCmdLine = false; + break; + } + DefragMode = DefragExtensive; + ValidCmdLine = true; + break; + + } + } + } + + if (DefragMode == DefragInvalid) + ValidCmdLine = false; + + if (!ValidCmdLine) + { + printf ("Invalid command-line options. Use '%s -?' for help.\n", argv[0]); + return (0); + } + + // Check OS requirements + if (!CheckWinVer()) + { + printf ("Fatal Error: This program requires Windows 2000.\n"); + return (0); + } + + for (d = 0; d < Drives.size (); d++) + { + HANDLE TossMe; + Defrags.push_back (StartDefragThread (Drives[d], DefragMode, TossMe)); + } + + for (d = 0; d < Drives.size () - 1; d++) + printf ("\n "); + + bool Continue = true; + HANDLE Screen; + + Screen = GetStdHandle (STD_OUTPUT_HANDLE); + while (Continue) + { + Sleep (25); + + // Get current screen coords + CONSOLE_SCREEN_BUFFER_INFO ScreenInfo; + + GetConsoleScreenBufferInfo (Screen, &ScreenInfo); + + // Now set back to the beginning + ScreenInfo.dwCursorPosition.X = 0; + ScreenInfo.dwCursorPosition.Y -= Drives.size(); + SetConsoleCursorPosition (Screen, ScreenInfo.dwCursorPosition); + + for (d = 0; d < Drives.size (); d++) + { + printf ("\n%6.2f%% %-70s", Defrags[d]->GetStatusPercent(), Defrags[d]->GetStatusString().c_str()); + } + + // Determine if we should keep going + Continue = false; + for (d = 0; d < Drives.size (); d++) + { + if (!Defrags[d]->IsDoneYet() && !Defrags[d]->HasError()) + Continue = true; + } + } + +#if 0 + // Loop through the drives list + for (int d = 0; d < Drives.size(); d++) + { + DriveVolume *Drive; + + Drive = new DriveVolume; + + // First thing: build a file list. + printf ("Opening volume %s ...", Drives[d].c_str()); + if (!Drive->Open (Drives[d])) + { + printf ("FAILED\n\n"); + delete Drive; + continue; + } + printf ("\n"); + + printf (" Getting drive bitmap ..."); + if (!Drive->GetBitmap ()) + { + printf ("FAILED\n\n"); + delete Drive; + continue; + } + printf ("\n"); + + printf (" Obtaining drive geometry ..."); + if (!Drive->ObtainInfo ()) + { + printf ("FAILED\n\n"); + delete Drive; + continue; + } + printf ("\n"); + + printf (" Building file database for drive %s ...", Drives[d].c_str()); + if (!Drive->BuildFileList ()) + { + printf ("FAILED\n\n"); + delete Drive; + continue; + } + printf ("\n"); + + printf (" %u files\n", Drive->GetDBFileCount ()); + + // Analyze only? + if (DefragMode == DefragAnalyze) + { + uint64 UsedBytes = 0; // total bytes used, with cluster size considerations + uint64 TotalBytes = 0; // total bytes used + uint64 SlackBytes = 0; // wasted space due to slack + uint32 Fragged = 0; // fragmented files + + printf (" Analyzing ..."); + if (VerboseMode) + printf ("\n"); + + for (int i = 0; i < Drive->GetDBFileCount(); i++) + { + uint64 Used; + uint64 Slack; + FileInfo Info; + + Info = Drive->GetDBFile (i); + + // Compute total used disk space + Used = ((Info.Size + Drive->GetClusterSize() - 1) / Drive->GetClusterSize()) * Drive->GetClusterSize(); + Slack = Used - Info.Size; + + UsedBytes += Used; + SlackBytes += Slack; + TotalBytes += Info.Size; + + if (VerboseMode) + { + printf (" %s%s, ", Drive->GetDBDir (Info.DirIndice).c_str(), Info.Name.c_str()); + + if (Info.Attributes.AccessDenied) + printf ("access was denied\n"); + else + { + if (Info.Attributes.Unmovable == 1) + printf ("unmovable, "); + + printf ("%I64u bytes, %I64u bytes on disk, %I64u bytes slack, %u fragments\n", + Info.Size, Used, Slack, Info.Fragments.size()); + } + } + + if (Info.Fragments.size() > 1) + Fragged++; + } + + if (!VerboseMode) + printf ("\n"); + + // TODO: Make it not look like ass + printf ("\n"); + printf (" Overall Analysis\n"); + printf (" ----------------\n"); + printf (" %u clusters\n", Drive->GetClusterCount ()); + printf (" %u bytes per cluster\n", Drive->GetClusterSize()); + printf (" %I64u total bytes on drive\n", (uint64)Drive->GetClusterCount() * (uint64)Drive->GetClusterSize()); + printf ("\n"); + printf (" %u files\n", Drive->GetDBFileCount ()); + printf (" %u contiguous files\n", Drive->GetDBFileCount () - Fragged); + printf (" %u fragmented files\n", Fragged); + printf ("\n"); + printf (" %I64u bytes\n", TotalBytes); + printf (" %I64u bytes on disk\n", UsedBytes); + printf (" %I64u bytes slack\n", SlackBytes); + } + + // Fast defragment! + if (DefragMode == DefragFast || DefragMode == DefragExtensive) + { + uint32 i; + uint64 FirstFreeLCN; + char PrintName[80]; + int Width = 66; + + if (DefragMode == DefragFast) + printf (" Performing fast file defragmentation ...\n"); + else + if (DefragMode == DefragExtensive) + printf (" Performing extensive file defragmentation\n"); + + // Find first free LCN for speedier searches ... + Drive->FindFreeRange (0, 1, FirstFreeLCN); + + for (i = 0; i < Drive->GetDBFileCount(); i++) + { + FileInfo Info; + bool Result; + uint64 TargetLCN; + + printf ("\r"); + + Info = Drive->GetDBFile (i); + + FitName (PrintName, Drive->GetDBDir (Info.DirIndice).c_str(), Info.Name.c_str(), Width); + printf (" %6.2f%% %-66s", (float)i / (float)Drive->GetDBFileCount() * 100.0f, PrintName); + + // Can't defrag 0 byte files :) + if (Info.Fragments.size() == 0) + continue; + + // If doing fast defrag, skip non-fragmented files + if (Info.Fragments.size() == 1 && DefragMode == DefragFast) + continue; + + // Find a place that can fit the file + Result = Drive->FindFreeRange (FirstFreeLCN, Info.Clusters, TargetLCN); + + // If we're doing an extensive defrag and the file is already defragmented + // and if its new location would be after its current location, don't + // move it. + if (DefragMode == DefragExtensive && Info.Fragments.size() == 1) + { + if (TargetLCN > Info.Fragments[0].StartLCN) + continue; + } + + // Otherwise, defrag0rize it! + if (Result) + { + bool Success = false; + + if (Drive->MoveFileDumb (i, TargetLCN)) + Success = true; + else + { // hmm, look for another area to move it to + Result = Drive->FindFreeRange (TargetLCN + 1, Info.Clusters, TargetLCN); + if (Result) + { + if (Drive->MoveFileDumb (i, TargetLCN)) + Success = true; + else + { // Try updating the drive bitmap + if (Drive->GetBitmap ()) + { + Result = Drive->FindFreeRange (0, Info.Clusters, TargetLCN); + if (Result) + { + if (Drive->MoveFileDumb (i, TargetLCN)) + Success = true; + } + } + } + } + } + + if (!Success) + printf ("\n -> failed\n"); + + Drive->FindFreeRange (0, 1, FirstFreeLCN); + } + } + + printf ("\n"); + } + printf ("Closing volume %s ...", Drives[d].c_str()); + delete Drive; + printf ("\n"); + } +#endif + + return (0); +} diff --git a/rosapps/fraginator/Unfrag.h b/rosapps/fraginator/Unfrag.h new file mode 100644 index 00000000000..877d7cc39a8 --- /dev/null +++ b/rosapps/fraginator/Unfrag.h @@ -0,0 +1,83 @@ +/***************************************************************************** + + Unfrag + +*****************************************************************************/ + + +#ifndef UNFRAG_H +#define UNFRAG_H + + +// Blah blah blah your template name is too long ... SO WHAT +#pragma warning (disable: 4786) + + +// I forget what this disables +#ifdef __ICL +#pragma warning (disable: 268) +#endif + + +// Hello Mr. Platform SDK, please let us use Windows 2000 only features +#ifndef WINVER +#define WINVER 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + + +#include +#include +#include +#include + + +#define APPNAME_CLI "Unfrag" +#define APPNAME_GUI "Fraginator" +#define APPVER_STR "1.03" +#define APPVER_NUM 1.03f +#define APPAUTHOR "Rick Brewster" +#define APPCOPYRIGHT "Copyright 2000-2002 Rick Brewster" + + +#include +#include +using namespace std; + + +typedef unsigned __int8 uint8; +typedef signed __int8 sint8; +typedef unsigned __int16 uint16; +typedef signed __int16 sint16; +typedef unsigned __int32 uint32; +typedef signed __int32 sint32; +typedef unsigned __int64 uint64; +typedef signed __int64 sint64; +typedef unsigned char uchar; + + +extern bool QuietMode; +extern bool VerboseMode; + + +typedef enum +{ + DefragInvalid, + DefragFast, + DefragExtensive, + DefragAnalyze +} DefragType; + + +extern bool CheckWinVer (void); + + +class Defragment; +extern Defragment *StartDefragThread (string Drive, DefragType Method, HANDLE &Handle); + + +extern char *AddCommas (char *Result, uint64 Number); + + +#endif // UNFRAG_H + diff --git a/rosapps/fraginator/default1.bin b/rosapps/fraginator/default1.bin new file mode 100644 index 00000000000..5d598c0a91d --- /dev/null +++ b/rosapps/fraginator/default1.bin @@ -0,0 +1,22 @@ + + + + Fraginator + + + + + + diff --git a/rosapps/fraginator/icon1.ico b/rosapps/fraginator/icon1.ico new file mode 100644 index 0000000000000000000000000000000000000000..4acbd2ca4a601cd6d3f380c28a1e675d3f363e64 GIT binary patch literal 8166 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 +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=unfrag - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "unfrag.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "unfrag.mak" CFG="unfrag - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "unfrag - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "unfrag - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +RSC=rc.exe + +!IF "$(CFG)" == "unfrag - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /G6 /Gr /MD /W3 /GX /Ox /Ot /Og /Oi /Ob2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copying to Program Files ... +PostBuild_Cmds=copy Release\unfrag.exe "c:\Program Files\Fraginator\unfrag.exe" +# End Special Build Tool + +!ELSEIF "$(CFG)" == "unfrag - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "unfrag___Win32_Debug" +# PROP BASE Intermediate_Dir "unfrag___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "unfrag___Win32_Debug" +# PROP Intermediate_Dir "unfrag___Win32_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "unfrag - Win32 Release" +# Name "unfrag - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Defragment.cpp +# End Source File +# Begin Source File + +SOURCE=.\DriveVolume.cpp +# End Source File +# Begin Source File + +SOURCE=.\Unfrag.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\Defragment.h +# End Source File +# Begin Source File + +SOURCE=.\DriveVolume.h +# End Source File +# Begin Source File + +SOURCE=.\Mutex.h +# End Source File +# Begin Source File + +SOURCE=.\Unfrag.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/rosapps/fraginator/unfrag.exe b/rosapps/fraginator/unfrag.exe new file mode 100644 index 0000000000000000000000000000000000000000..bcb1aef99a06ccc81794970158fe8a48d77173f3 GIT binary patch literal 90112 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 Nz^VbO2L6v4_yZk2aLfPz literal 0 HcmV?d00001 diff --git a/rosapps/fraginator/unfrag.mak b/rosapps/fraginator/unfrag.mak new file mode 100644 index 00000000000..838fc089b9f --- /dev/null +++ b/rosapps/fraginator/unfrag.mak @@ -0,0 +1,184 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on unfrag.dsp +!IF "$(CFG)" == "" +CFG=unfrag - Win32 Debug +!MESSAGE No configuration specified. Defaulting to unfrag - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "unfrag - Win32 Release" && "$(CFG)" != "unfrag - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "unfrag.mak" CFG="unfrag - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "unfrag - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "unfrag - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=xicl6.exe +RSC=rc.exe + +!IF "$(CFG)" == "unfrag - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +ALL : "$(OUTDIR)\unfrag.exe" + + +CLEAN : + -@erase "$(INTDIR)\Defragment.obj" + -@erase "$(INTDIR)\DriveVolume.obj" + -@erase "$(INTDIR)\Unfrag.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(OUTDIR)\unfrag.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /G6 /Gr /MD /W3 /GX /Ox /Ot /Og /Oi /Ob2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\unfrag.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\unfrag.bsc" +BSC32_SBRS= \ + +LINK32=xilink6.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\unfrag.pdb" /machine:I386 /out:"$(OUTDIR)\unfrag.exe" +LINK32_OBJS= \ + "$(INTDIR)\Defragment.obj" \ + "$(INTDIR)\DriveVolume.obj" \ + "$(INTDIR)\Unfrag.obj" + +"$(OUTDIR)\unfrag.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +SOURCE="$(InputPath)" +PostBuild_Desc=Copying to Program Files ... +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +ALL : $(DS_POSTBUILD_DEP) + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\unfrag.exe" + copy Release\unfrag.exe "c:\Program Files\Fraginator\unfrag.exe" + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "unfrag - Win32 Debug" + +OUTDIR=.\unfrag___Win32_Debug +INTDIR=.\unfrag___Win32_Debug +# Begin Custom Macros +OutDir=.\unfrag___Win32_Debug +# End Custom Macros + +ALL : "$(OUTDIR)\unfrag.exe" + + +CLEAN : + -@erase "$(INTDIR)\Defragment.obj" + -@erase "$(INTDIR)\DriveVolume.obj" + -@erase "$(INTDIR)\Unfrag.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(OUTDIR)\unfrag.exe" + -@erase "$(OUTDIR)\unfrag.ilk" + -@erase "$(OUTDIR)\unfrag.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\unfrag.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\unfrag.bsc" +BSC32_SBRS= \ + +LINK32=xilink6.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\unfrag.pdb" /debug /machine:I386 /out:"$(OUTDIR)\unfrag.exe" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\Defragment.obj" \ + "$(INTDIR)\DriveVolume.obj" \ + "$(INTDIR)\Unfrag.obj" + +"$(OUTDIR)\unfrag.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("unfrag.dep") +!INCLUDE "unfrag.dep" +!ELSE +!MESSAGE Warning: cannot find "unfrag.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "unfrag - Win32 Release" || "$(CFG)" == "unfrag - Win32 Debug" +SOURCE=.\Defragment.cpp + +"$(INTDIR)\Defragment.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\DriveVolume.cpp + +"$(INTDIR)\DriveVolume.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\Unfrag.cpp + +"$(INTDIR)\Unfrag.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/rosapps/fraginator/unfrag.plg b/rosapps/fraginator/unfrag.plg new file mode 100644 index 00000000000..5e0486eb640 --- /dev/null +++ b/rosapps/fraginator/unfrag.plg @@ -0,0 +1,48 @@ + + +
+

Build Log

+

+--------------------Configuration: unfrag - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\TEMP\RSP9D8.tmp" with contents +[ +/nologo /G6 /Gr /MD /W3 /GX /Ox /Ot /Og /Oi /Ob2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"Release/" /Fd"Release/" /FD /c +"C:\src\Fraginator\Defragment.cpp" +"C:\src\Fraginator\DriveVolume.cpp" +"C:\src\Fraginator\Unfrag.cpp" +] +Creating command line "xicl6.exe @C:\TEMP\RSP9D8.tmp" +Creating temporary file "C:\TEMP\RSP9D9.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /pdb:"Release/unfrag.pdb" /machine:I386 /out:"Release/unfrag.exe" +.\Release\Defragment.obj +.\Release\DriveVolume.obj +.\Release\Unfrag.obj +] +Creating command line "xilink6.exe @C:\TEMP\RSP9D9.tmp" +

Output Window

+Compiling... +Defragment.cpp +DriveVolume.cpp +Unfrag.cpp +Generating Code... +Linking... +xilink6: executing 'C:\PROGRA~1\MIAF9D~1\VC98\Bin\link.exe' +Creating temporary file "C:\TEMP\RSP9DB.bat" with contents +[ +@echo off +copy Release\unfrag.exe "c:\Program Files\Fraginator\unfrag.exe" +] +Creating command line "C:\TEMP\RSP9DB.bat" +Copying to Program Files ... + 1 file(s) copied. + + + +

Results

+unfrag.exe - 0 error(s), 0 warning(s) +
+ + diff --git a/rosapps/fraginator/unfrag.vcproj b/rosapps/fraginator/unfrag.vcproj new file mode 100644 index 00000000000..efb793fbf41 --- /dev/null +++ b/rosapps/fraginator/unfrag.vcproj @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +