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 00000000000..b8d412e8227 Binary files /dev/null and b/rosapps/fraginator/Fraginator Motif Icon.bmp differ 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 00000000000..2ef93897ce3 Binary files /dev/null and b/rosapps/fraginator/Fraginator.exe differ diff --git a/rosapps/fraginator/Fraginator.h b/rosapps/fraginator/Fraginator.h new file mode 100644 index 00000000000..7008ca8856b --- /dev/null +++ b/rosapps/fraginator/Fraginator.h @@ -0,0 +1,24 @@ +/***************************************************************************** + + Fraginator !!! + +*****************************************************************************/ + + +#ifndef FRAGINATOR_H +#define FRAGINATOR_H + + +#include "unfrag.h" +#include + + +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 00000000000..c674481aaf8 Binary files /dev/null and b/rosapps/fraginator/Fraginator.suo differ diff --git a/rosapps/fraginator/Fraginator.vcproj b/rosapps/fraginator/Fraginator.vcproj new file mode 100644 index 00000000000..5d17321bb50 --- /dev/null +++ b/rosapps/fraginator/Fraginator.vcproj @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 00000000000..4acbd2ca4a6 Binary files /dev/null and b/rosapps/fraginator/icon1.ico differ diff --git a/rosapps/fraginator/resource.h b/rosapps/fraginator/resource.h new file mode 100644 index 00000000000..c98399ed8c0 --- /dev/null +++ b/rosapps/fraginator/resource.h @@ -0,0 +1,51 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Fraginator.rc +// +#define IDD_DIALOG1 101 +#define IDD_MAIN 101 +#define IDD_REPORT 106 +#define IDB_LOGO 110 +#define IDI_ICON 114 +#define IDC_QUIT 1010 +#define IDC_STARTSTOP 1014 +#define IDC_METHODS_LIST 1016 +#define IDC_DRIVES_LIST 1019 +#define IDC_PROGRESS 1021 +#define IDC_PERCENT 1022 +#define IDC_STATUS 1023 +#define IDC_DISKSIZEBYTES 1027 +#define IDC_DRIVELETTER 1028 +#define IDC_REPORTOK 1029 +#define IDC_DISKSIZECLUSTERS 1030 +#define IDC_DISKCLUSTERSIZE 1031 +#define IDC_FILESYSTEM 1032 +#define IDC_WISECRACKS 1033 +#define IDC_VOLUMELABEL 1033 +#define IDC_VOLUMESERIAL 1034 +#define IDC_BYTES 1035 +#define IDC_KILOBYTES 1036 +#define IDC_RECOMMEND 1037 +#define IDC_FILESCOUNT 1038 +#define IDC_FILESSIZEBYTES 1039 +#define IDC_FILESSIZEONDISK 1040 +#define IDC_FILESSLACKBYTES 1041 +#define IDC_GIGABYTES 1043 +#define IDC_DISKFREEBYTES 1044 +#define IDC_MEGABYTES 1045 +#define IDC_FILESFRAGGED 1047 +#define IDC_DIRSCOUNT 1048 +#define IDC_AVERAGEFRAGS 1049 +#define ID_MAIN_HELP 1054 +#define IDC_PRIORITY_LIST 1057 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 118 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1058 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/rosapps/fraginator/unfrag.dsp b/rosapps/fraginator/unfrag.dsp new file mode 100644 index 00000000000..fd5e8680931 --- /dev/null +++ b/rosapps/fraginator/unfrag.dsp @@ -0,0 +1,133 @@ +# Microsoft Developer Studio Project File - Name="unfrag" - Package Owner=<4> +# 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 00000000000..bcb1aef99a0 Binary files /dev/null and b/rosapps/fraginator/unfrag.exe differ 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +