├── .gitattributes ├── dskwipe.ico ├── vcbuild.mk ├── version.h ├── dskwipe.dep ├── nmake.mk ├── msbuild.mk ├── dskwipe.dsw ├── dskwipe.sln ├── CHANGELOG.md ├── LICENSE ├── dskwipe.vcxproj.filters ├── dskwipe.rc ├── README.md ├── dskwipe.dsp ├── CONTRIBUTING.md ├── dskwipe.mak ├── dskwipe.vcproj ├── dskwipe.vcxproj ├── .gitignore ├── Makefile └── dskwipe.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | *.dsp eol=crlf 2 | *.dsw eol=crlf 3 | -------------------------------------------------------------------------------- /dskwipe.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rasa/dskwipe/HEAD/dskwipe.ico -------------------------------------------------------------------------------- /vcbuild.mk: -------------------------------------------------------------------------------- 1 | all: 2 | VCBuild.exe /nologo dskwipe.vcproj /rebuild 3 | 4 | clean: 5 | VCBuild.exe /nologo dskwipe.vcproj /clean 6 | 7 | upgrade: 8 | devenv dskwipe.sln /upgrade 9 | 10 | .PHONY: all clean upgrade 11 | 12 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2002-2016 Ross Smith II. MIT licensed. 2 | 3 | #define VER_INTERNAL_NAME "dskwipe" 4 | #define VER_FILE_DESCRIPTION "Securely wipe disk media" 5 | #define VER_MAJOR 1 6 | #define VER_MINOR 3 7 | #define VER_STRING2 "1.3" 8 | 9 | #include "ver_defaults.h" 10 | -------------------------------------------------------------------------------- /dskwipe.dep: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Generated Dependency File, included by dskwipe.mak 2 | 3 | .\dskwipe.cpp : \ 4 | {$(INCLUDE)}"getopt.h"\ 5 | ".\version.h"\ 6 | {$(INCLUDE)}"ver_defaults.h"\ 7 | 8 | 9 | .\dskwipe.rc : \ 10 | ".\dskwipe.ico"\ 11 | ".\version.h"\ 12 | {$(INCLUDE)}"ver_defaults.h"\ 13 | 14 | -------------------------------------------------------------------------------- /nmake.mk: -------------------------------------------------------------------------------- 1 | all: 2 | nmake /nologo /f dskwipe.mak CFG="dskwipe - Win32 Release" NO_EXTERNAL_DEPS=1 all 3 | nmake /nologo /f dskwipe.mak CFG="dskwipe - Win32 Debug" NO_EXTERNAL_DEPS=1 all 4 | 5 | clean: 6 | nmake /nologo /f dskwipe.mak CFG="dskwipe - Win32 Release" clean 7 | nmake /nologo /f dskwipe.mak CFG="dskwipe - Win32 Debug" clean 8 | 9 | .PHONY: all clean -------------------------------------------------------------------------------- /msbuild.mk: -------------------------------------------------------------------------------- 1 | all: 2 | MSBuild.exe /nologo dskwipe.sln /p:Configuration=Debug 3 | MSBuild.exe /nologo dskwipe.sln /p:Configuration=Release 4 | 5 | clean: 6 | MSBuild.exe /nologo dskwipe.sln /p:Configuration=Debug /t:clean 7 | MSBuild.exe /nologo dskwipe.sln /p:Configuration=Release /t:clean 8 | 9 | upgrade: 10 | devenv dskwipe.sln /upgrade 11 | 12 | .PHONY: all clean upgrade 13 | 14 | 15 | -------------------------------------------------------------------------------- /dskwipe.dsw: -------------------------------------------------------------------------------- 1 | Microsoft Developer Studio Workspace File, Format Version 6.00 2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! 3 | 4 | ############################################################################### 5 | 6 | Project: "dskwipe"=.\dskwipe.dsp - Package Owner=<4> 7 | 8 | Package=<5> 9 | {{{ 10 | }}} 11 | 12 | Package=<4> 13 | {{{ 14 | Begin Project Dependency 15 | End Project Dependency 16 | }}} 17 | 18 | ############################################################################### 19 | 20 | Global: 21 | 22 | Package=<5> 23 | {{{ 24 | }}} 25 | 26 | Package=<3> 27 | {{{ 28 | }}} 29 | 30 | ############################################################################### 31 | 32 | -------------------------------------------------------------------------------- /dskwipe.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dskwipe", "dskwipe.vcxproj", "{54D2922C-4D55-461F-9B3C-967849BC7F59}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {54D2922C-4D55-461F-9B3C-967849BC7F59}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {54D2922C-4D55-461F-9B3C-967849BC7F59}.Debug|Win32.Build.0 = Debug|Win32 14 | {54D2922C-4D55-461F-9B3C-967849BC7F59}.Release|Win32.ActiveCfg = Release|Win32 15 | {54D2922C-4D55-461F-9B3C-967849BC7F59}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.3 (18-Dec-2016) 2 | 3 | * Wipe entire sector (fixes #1) 4 | * Update to Visual Studio 2015 5 | 6 | ## 1.2 (07-Apr-2015) 7 | 8 | * Add version number to executable 9 | * Add .rc and .ico files to build 10 | 11 | ## 1.1 (27-Mar-2015) 12 | 13 | * Executables signed with StartSSL code signing certificate 14 | * Release zip files are gpg signed and sha256 hashed 15 | * Standardize build scripts 16 | * Update documentation 17 | 18 | ## 1.0 (22-Feb-2015) 19 | 20 | * Improve option processing 21 | * Updated to Visual Studio 2013 22 | * Switch to MIT license 23 | 24 | ## 0.4 (25-Dec-2012) 25 | 26 | * Works on mounted disks in Windows 7 27 | * Fixed -2 Windows RNG function in Windows 7 28 | * Added Bruce Schneier's wiping method (7 passes) 29 | * Added German BCI/VSITR wiping method (7 passes) 30 | * Other minor bugfixes 31 | 32 | ## 0.3 (10-Apr-2007) 33 | 34 | * Require 'yes' to start wipe 35 | 36 | ## 0.2 (05-Mar-2007) 37 | 38 | * Corrected a few minor grammatical errors 39 | 40 | ## 0.1 (27-Feb-2007) 41 | 42 | * Initial release 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2007-2015 Ross Smith II 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /dskwipe.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {3227cca3-9edb-4c50-887a-303c52c9c729} 6 | cpp;c;cxx;rc;def;r;odl;idl;hpj;bat 7 | 8 | 9 | {9c23e298-a773-4879-8009-78d3db5b233a} 10 | h;hpp;hxx;hm;inl 11 | 12 | 13 | {8d81ff5b-d49a-4b11-a357-d782f81ac18d} 14 | ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | 28 | 29 | Resource Files 30 | 31 | 32 | 33 | 34 | Resource Files 35 | 36 | 37 | -------------------------------------------------------------------------------- /dskwipe.rc: -------------------------------------------------------------------------------- 1 | //Microsoft Developer Studio generated resource script. 2 | // 3 | 4 | #include "winver.h" 5 | #include "version.h" 6 | 7 | #define APSTUDIO_READONLY_SYMBOLS 8 | ///////////////////////////////////////////////////////////////////////////// 9 | // 10 | // Generated from the TEXTINCLUDE 2 resource. 11 | // 12 | #include "windows.h" 13 | 14 | ///////////////////////////////////////////////////////////////////////////// 15 | #undef APSTUDIO_READONLY_SYMBOLS 16 | 17 | ///////////////////////////////////////////////////////////////////////////// 18 | // Neutral resources 19 | 20 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) 21 | #ifdef _WIN32 22 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 23 | #pragma code_page(1252) 24 | #endif //_WIN32 25 | 26 | ///////////////////////////////////////////////////////////////////////////// 27 | // 28 | // Icon & Bitmaps 29 | // 30 | IDI_ICON ICON DISCARDABLE "dskwipe.ico" 31 | 32 | #ifndef _MAC 33 | ///////////////////////////////////////////////////////////////////////////// 34 | // 35 | // Version 36 | // 37 | 38 | VS_VERSION_INFO VERSIONINFO 39 | FILEVERSION VER_FILE_VERSION 40 | PRODUCTVERSION VER_PRODUCT_VERSION 41 | FILEFLAGSMASK 0x3fL 42 | #ifdef _DEBUG 43 | FILEFLAGS 0x1L 44 | #else 45 | FILEFLAGS 0x0L 46 | #endif 47 | FILEOS 0x40004L 48 | FILETYPE 0x1L 49 | FILESUBTYPE 0x0L 50 | BEGIN 51 | BLOCK "StringFileInfo" 52 | BEGIN 53 | BLOCK "000004b0" 54 | BEGIN 55 | VALUE "Comments", VER_COMMENTS "\0" 56 | VALUE "CompanyName", VER_COMPANY_NAME "\0" 57 | VALUE "FileDescription", VER_FILE_DESCRIPTION "\0" 58 | VALUE "FileVersion", VER_FILE_STRING "\0" 59 | VALUE "InternalName", VER_INTERNAL_NAME "\0" 60 | VALUE "LegalCopyright", VER_LEGAL_COPYRIGHT "\0" 61 | VALUE "OriginalFilename", VER_ORIGINAL_FILENAME "\0" 62 | VALUE "ProductName", VER_PRODUCT_NAME "\0" 63 | VALUE "ProductVersion", VER_PRODUCT_STRING "\0" 64 | END 65 | END 66 | BLOCK "VarFileInfo" 67 | BEGIN 68 | VALUE "Translation", 0x0, 1200 69 | END 70 | END 71 | 72 | #endif // !_MAC 73 | 74 | 75 | #ifdef APSTUDIO_INVOKED 76 | ///////////////////////////////////////////////////////////////////////////// 77 | // 78 | // TEXTINCLUDE 79 | // 80 | 81 | 1 TEXTINCLUDE DISCARDABLE 82 | BEGIN 83 | "windows.h\0" 84 | END 85 | 86 | 2 TEXTINCLUDE DISCARDABLE 87 | BEGIN 88 | "#include ""afxres.h""\r\n" 89 | "\0" 90 | END 91 | 92 | 3 TEXTINCLUDE DISCARDABLE 93 | BEGIN 94 | "\r\n" 95 | "\0" 96 | END 97 | 98 | #endif // APSTUDIO_INVOKED 99 | 100 | #endif // Neutral resources 101 | ///////////////////////////////////////////////////////////////////////////// 102 | 103 | 104 | ///////////////////////////////////////////////////////////////////////////// 105 | // English (U.S.) resources 106 | 107 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 108 | #ifdef _WIN32 109 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 110 | #pragma code_page(1252) 111 | #endif //_WIN32 112 | 113 | #endif // English (U.S.) resources 114 | ///////////////////////////////////////////////////////////////////////////// 115 | 116 | #ifndef APSTUDIO_INVOKED 117 | ///////////////////////////////////////////////////////////////////////////// 118 | // 119 | // Generated from the TEXTINCLUDE 3 resource. 120 | // 121 | 122 | 123 | ///////////////////////////////////////////////////////////////////////////// 124 | #endif // not APSTUDIO_INVOKED 125 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dskwipe [![Flattr this][flatter_png]][flatter] 2 | 3 | Securely wipe disk media. 4 | 5 | ## Usage 6 | 7 | ```` 8 | dskwipe [options] device(s) [byte(s)] 9 | bytes can be one or more numbers between 0 to 255, use 0xNN for hexidecimal, 10 | 0NNN for octal, r for random bytes, default is 0 11 | 12 | Options: 13 | 14 | -l | --list List available devices and exit 15 | -p | --passes n Wipe device n times (default is 1) 16 | -d | --dod Wipe device using US DoD 5220.22-M method (3 passes) 17 | -E | --doe Wipe device using US DoE method (3 passes) 18 | -D | --dod7 Wipe device using US DoD 5200.28-STD method (7 passes) 19 | -S | --schneier Wipe device using Bruce Schneier's method (7 passes) 20 | -b | --bci Wipe device using German BCI/VSITR method (7 passes) 21 | -g | --gutmann Wipe device using Peter Gutmann's method (35 passes) 22 | -1 | --pseudo Use pseudo RNG (fast, not secure, this is the default) 23 | -2 | --windows Use Windows RNG (slower, more secure) 24 | -k | --kilobyte Use 1024 for kilobyte (default is 1000) 25 | -y | --yes Start processing without waiting for confirmation 26 | -x | --exit mode Exit Windows. mode can be: poweroff, shutdown, hibernate, 27 | logoff, reboot, or standby. 28 | -f | --force Force poweroff/shutdown/logoff/reboot (WARNING: DATA LOSS!) 29 | -q | --quiet Display less information (-qq = quieter, etc.) 30 | -z | --refresh n Refresh display every n seconds (default is 1) 31 | -n | --sectors n Write n sectors at once (1-65535, default is 64) 32 | -s | --start n Start at relative sector n (default is 0) 33 | -e | --end n End at relative sector n (default is last sector) 34 | -r | --read Only read the data on the device (DOES NOT WIPE!) 35 | -i | --ignore Ignore certain read/write errors 36 | -v | --version Show version and copyright information and quit 37 | -? | --help Show this help message and quit (-?? = more help, etc.) 38 | ```` 39 | 40 | ## Examples 41 | 42 | ````batch 43 | dskwipe -l & lists devices, and exit 44 | dskwipe \\.\PhysicalDrive1 & erase disk once using the byte 0 45 | dskwipe \Device\Ramdisk 1 & erase disk once using the byte 1 46 | dskwipe \Device\Ramdisk 0 255 & erase disk twice using bytes 0 then 255 47 | dskwipe --dod \Device\Ramdisk & erase disk using DoD 5220.22-M method 48 | dskwipe \Device\Ramdisk 0 0xff r & same as --dod (bytes 0, 255, weak random) 49 | dskwipe -p 2 \Device\Ramdisk 0 1 & erase disk 4 times using bytes 0/1/0/1 50 | dskwipe -p 2 --dod \Device\Ramdisk & erase disk twice using DoD method 51 | dskwipe -1 \Device\Ramdisk r r & erase disk twice using weak RNG 52 | dskwipe -2 \Device\Ramdisk r r r r & erase disk four times using strong RNG 53 | ```` 54 | Here are some device names that have worked for me: 55 | 56 | ```` 57 | \\.\PhysicalDrive0 58 | \\.\c: 59 | \device\harddisk0\partition0 60 | \device\harddisk0\partition1 61 | \device\floppy0 62 | \device\ramdisk 63 | ```` 64 | 65 | ## Verify a Release 66 | 67 | To verify a release, download the .zip, .sha256, and .asc files for the release 68 | (replacing dskwipe-1.1-win32.zip with the release you are verifying): 69 | 70 | ```` 71 | $ wget https://github.com/rasa/dskwipe/releases/download/v1.1/dskwipe-1.1-win32.zip{,.sha256,.asc} 72 | ```` 73 | 74 | Next, check that sha256sum reports "OK": 75 | ```` 76 | $ sha256sum -c dskwipe-1.1-win32.zip.sha256 77 | dskwipe-1.1-win32.zip: OK 78 | ```` 79 | 80 | Lastly, check that GPG reports "Good signature": 81 | 82 | ```` 83 | $ gpg --keyserver hkps.pool.sks-keyservers.net --recv-key 0x105a5225b6ab4b22 84 | $ gpg --verify dskwipe-1.1-win32.zip.asc dskwipe-1.1-win32.zip 85 | gpg: using RSA key 0xFF914F74B4BB6EF3 86 | gpg: Good signature from "Ross Smith II " [ultimate] 87 | ... 88 | ```` 89 | 90 | ## Contributing 91 | 92 | To contribute to this project, please see [CONTRIBUTING.md](CONTRIBUTING.md). 93 | 94 | ## Bugs 95 | 96 | To view existing bugs, or report a new bug, please see [issues](../../issues). 97 | 98 | ## Changelog 99 | 100 | To view the version history for this project, please see [CHANGELOG.md](CHANGELOG.md). 101 | 102 | ## License 103 | 104 | This project is [MIT licensed](LICENSE). 105 | 106 | ## Contact 107 | 108 | This project was created and is maintained by [Ross Smith II][] [![endorse][endorse_png]][endorse] 109 | 110 | Feedback, suggestions, and enhancements are welcome. 111 | 112 | [Ross Smith II]: mailto:ross@smithii.com "ross@smithii.com" 113 | [flatter]: https://flattr.com/submit/auto?user_id=rasa&url=https%3A%2F%2Fgithub.com%2Frasa%2Fdskwipe 114 | [flatter_png]: http://button.flattr.com/flattr-badge-large.png "Flattr this" 115 | [endorse]: https://coderwall.com/rasa 116 | [endorse_png]: https://api.coderwall.com/rasa/endorsecount.png "endorse" 117 | 118 | -------------------------------------------------------------------------------- /dskwipe.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="dskwipe" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 6 | 7 | CFG=dskwipe - Win32 Debug 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "dskwipe.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "dskwipe.mak" CFG="dskwipe - Win32 Debug" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "dskwipe - Win32 Release" (based on "Win32 (x86) Console Application") 21 | !MESSAGE "dskwipe - Win32 Debug" (based on "Win32 (x86) Console Application") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | RSC=rc.exe 30 | 31 | !IF "$(CFG)" == "dskwipe - Win32 Release" 32 | 33 | # PROP BASE Use_MFC 0 34 | # PROP BASE Use_Debug_Libraries 0 35 | # PROP BASE Output_Dir "Release" 36 | # PROP BASE Intermediate_Dir "Release" 37 | # PROP BASE Target_Dir "" 38 | # PROP Use_MFC 0 39 | # PROP Use_Debug_Libraries 0 40 | # PROP Output_Dir "Release" 41 | # PROP Intermediate_Dir "Release" 42 | # PROP Ignore_Export_Lib 0 43 | # PROP Target_Dir "" 44 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 45 | # ADD CPP /nologo /W3 /GX /O2 /I "..\shared" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 46 | # ADD BASE RSC /l 0x409 /d "NDEBUG" 47 | # ADD RSC /l 0x409 /d "NDEBUG" 48 | BSC32=bscmake.exe 49 | # ADD BASE BSC32 /nologo 50 | # ADD BSC32 /nologo 51 | LINK32=link.exe 52 | # 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 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 53 | # ADD LINK32 shared.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 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 54 | 55 | !ELSEIF "$(CFG)" == "dskwipe - Win32 Debug" 56 | 57 | # PROP BASE Use_MFC 0 58 | # PROP BASE Use_Debug_Libraries 1 59 | # PROP BASE Output_Dir "Debug" 60 | # PROP BASE Intermediate_Dir "Debug" 61 | # PROP BASE Target_Dir "" 62 | # PROP Use_MFC 0 63 | # PROP Use_Debug_Libraries 1 64 | # PROP Output_Dir "Debug" 65 | # PROP Intermediate_Dir "Debug" 66 | # PROP Ignore_Export_Lib 0 67 | # PROP Target_Dir "" 68 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\shared" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c 70 | # ADD BASE RSC /l 0x409 /d "_DEBUG" 71 | # ADD RSC /l 0x409 /d "_DEBUG" 72 | BSC32=bscmake.exe 73 | # ADD BASE BSC32 /nologo 74 | # ADD BSC32 /nologo 75 | LINK32=link.exe 76 | # 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 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 77 | # ADD LINK32 sharedd.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 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 78 | 79 | !ENDIF 80 | 81 | # Begin Target 82 | 83 | # Name "dskwipe - Win32 Release" 84 | # Name "dskwipe - Win32 Debug" 85 | # Begin Group "Source Files" 86 | 87 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 88 | # Begin Source File 89 | 90 | SOURCE=.\dskwipe.cpp 91 | # End Source File 92 | # End Group 93 | # Begin Group "Header Files" 94 | 95 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 96 | # Begin Source File 97 | 98 | SOURCE=.\version.h 99 | # End Source File 100 | # End Group 101 | # Begin Group "Resource Files" 102 | 103 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" 104 | # Begin Source File 105 | 106 | SOURCE=.\dskwipe.ico 107 | # End Source File 108 | # Begin Source File 109 | 110 | SOURCE=.\dskwipe.rc 111 | # End Source File 112 | # End Group 113 | # End Target 114 | # End Project 115 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks! There are plenty of ways you can help! 4 | 5 | Please take a moment to review this document in order to make the contribution 6 | process easy and effective for everyone involved. 7 | 8 | Following these guidelines helps to communicate that you respect the time of 9 | the developers managing and developing this open source project. In return, 10 | they should reciprocate that respect in addressing your issue or assessing 11 | patches and features. 12 | 13 | ## Using the issue tracker 14 | 15 | The link:/issues[issue tracker] is 16 | the preferred channel for [bug reports](#bug-reports), [feature requests](#feature-requests) 17 | and submitting [pull requests](#pull-requests). 18 | 19 | ## Bug reports 20 | 21 | A bug is a _demonstrable problem_ that is caused by the code in the repository. 22 | Good bug reports are extremely helpful - thank you! 23 | 24 | Guidelines for bug reports: 25 | 26 | 1. **Use the GitHub issue search** — check if the issue has already been 27 | reported. 28 | 29 | 2. **Check if the issue has been fixed** — try to reproduce it using the 30 | latest `master` or development branch in the repository. 31 | 32 | 3. **Isolate the problem** — ideally create a reduced test 33 | case] and a live example. 34 | 35 | A good bug report shouldn't leave others needing to chase you up for more 36 | information. Please try to be as detailed as possible in your report. What is 37 | your environment? What steps will reproduce the issue? What browser(s) and OS 38 | experience the problem? What would you expect to be the outcome? All these 39 | details will help people to fix any potential bugs. 40 | 41 | Example: 42 | 43 | > Short and descriptive example bug report title 44 | > 45 | > A summary of the issue and the browser/OS environment in which it occurs. If 46 | > suitable, include the steps required to reproduce the bug. 47 | > 48 | > 1. This is the first step 49 | > 2. This is the second step 50 | > 3. Further steps, etc. 51 | > 52 | > `` - a link to the reduced test case 53 | > 54 | > Any other information you want to share that is relevant to the issue being 55 | > reported. This might include the lines of code that you have identified as 56 | > causing the bug, and potential solutions (and your opinions on their 57 | > merits). 58 | 59 | ## Feature requests 60 | 61 | Feature requests are welcome. But take a moment to find out whether your idea 62 | fits with the scope and aims of the project. It's up to *you* to make a strong 63 | case to convince the project's developers of the merits of this feature. Please 64 | provide as much detail and context as possible. 65 | 66 | ## Pull requests 67 | 68 | Good pull requests - patches, improvements, new features - are a fantastic 69 | help. They should remain focused in scope and avoid containing unrelated 70 | commits. 71 | 72 | **Please ask first** before embarking on any significant pull request (e.g. 73 | implementing features, refactoring code, porting to a different language), 74 | otherwise you risk spending a lot of time working on something that the 75 | project's developers might not want to merge into the project. 76 | 77 | Please adhere to the coding conventions used throughout a project (indentation, 78 | accurate comments, etc.) and any other requirements (such as test coverage). 79 | 80 | Adhering to the following process is the best way to get your work 81 | included in the project: 82 | 83 | 1. [Fork](https://help.github.com/articles/fork-a-repo) the project, clone your 84 | fork, and configure the remotes: 85 | ```bash 86 | # Clone your fork of the repo into the current directory 87 | git clone https://github.com//dskwipe.git 88 | # Navigate to the newly cloned directory 89 | cd dskwipe 90 | # Assign the original repo to a remote called "upstream" 91 | git remote add upstream https://github.com/rasa/dskwipe.git 92 | ``` 93 | 94 | 2. If you cloned a while ago, get the latest changes from upstream: 95 | ```bash 96 | $ git checkout master 97 | $ git pull upstream master 98 | ``` 99 | 3. Create a new topic branch (off the main project development branch) to 100 | contain your feature, change, or fix: 101 | ```bash 102 | $ git checkout -b 103 | ``` 104 | 4. Commit your changes in logical chunks. Please adhere to these 105 | [git commit message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) 106 | or your code is unlikely be merged into the main project. Use Git's 107 | [interactive rebase](https://help.github.com/articles/about-git-rebase) 108 | feature to tidy up your commits before making them public. 109 | 110 | 5. Locally merge (or rebase) the upstream development branch into your topic branch: 111 | ```bash 112 | $ git pull [--rebase] upstream master 113 | ``` 114 | 115 | 6. Push your topic branch up to your fork: 116 | ```bash 117 | $ git push origin 118 | ``` 119 | 120 | 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests) 121 | with a clear title and description. 122 | 123 | **IMPORTANT**: By submitting a patch, you agree to allow the project owners to 124 | license your work under the terms of the [MIT License](/LICENSE). 125 | -------------------------------------------------------------------------------- /dskwipe.mak: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Generated NMAKE File, Based on dskwipe.dsp 2 | !IF "$(CFG)" == "" 3 | CFG=dskwipe - Win32 Debug 4 | !MESSAGE No configuration specified. Defaulting to dskwipe - Win32 Debug. 5 | !ENDIF 6 | 7 | !IF "$(CFG)" != "dskwipe - Win32 Release" && "$(CFG)" != "dskwipe - Win32 Debug" 8 | !MESSAGE Invalid configuration "$(CFG)" specified. 9 | !MESSAGE You can specify a configuration when running NMAKE 10 | !MESSAGE by defining the macro CFG on the command line. For example: 11 | !MESSAGE 12 | !MESSAGE NMAKE /f "dskwipe.mak" CFG="dskwipe - Win32 Debug" 13 | !MESSAGE 14 | !MESSAGE Possible choices for configuration are: 15 | !MESSAGE 16 | !MESSAGE "dskwipe - Win32 Release" (based on "Win32 (x86) Console Application") 17 | !MESSAGE "dskwipe - Win32 Debug" (based on "Win32 (x86) Console Application") 18 | !MESSAGE 19 | !ERROR An invalid configuration is specified. 20 | !ENDIF 21 | 22 | !IF "$(OS)" == "Windows_NT" 23 | NULL= 24 | !ELSE 25 | NULL=nul 26 | !ENDIF 27 | 28 | !IF "$(CFG)" == "dskwipe - Win32 Release" 29 | 30 | OUTDIR=.\Release 31 | INTDIR=.\Release 32 | # Begin Custom Macros 33 | OutDir=.\Release 34 | # End Custom Macros 35 | 36 | ALL : "$(OUTDIR)\dskwipe.exe" 37 | 38 | 39 | CLEAN : 40 | -@erase "$(INTDIR)\dskwipe.obj" 41 | -@erase "$(INTDIR)\dskwipe.res" 42 | -@erase "$(INTDIR)\vc60.idb" 43 | -@erase "$(OUTDIR)\dskwipe.exe" 44 | 45 | "$(OUTDIR)" : 46 | if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" 47 | 48 | CPP=cl.exe 49 | CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\shared" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dskwipe.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 50 | 51 | .c{$(INTDIR)}.obj:: 52 | $(CPP) @<< 53 | $(CPP_PROJ) $< 54 | << 55 | 56 | .cpp{$(INTDIR)}.obj:: 57 | $(CPP) @<< 58 | $(CPP_PROJ) $< 59 | << 60 | 61 | .cxx{$(INTDIR)}.obj:: 62 | $(CPP) @<< 63 | $(CPP_PROJ) $< 64 | << 65 | 66 | .c{$(INTDIR)}.sbr:: 67 | $(CPP) @<< 68 | $(CPP_PROJ) $< 69 | << 70 | 71 | .cpp{$(INTDIR)}.sbr:: 72 | $(CPP) @<< 73 | $(CPP_PROJ) $< 74 | << 75 | 76 | .cxx{$(INTDIR)}.sbr:: 77 | $(CPP) @<< 78 | $(CPP_PROJ) $< 79 | << 80 | 81 | RSC=rc.exe 82 | RSC_PROJ=/l 0x409 /fo"$(INTDIR)\dskwipe.res" /d "NDEBUG" 83 | BSC32=bscmake.exe 84 | BSC32_FLAGS=/nologo /o"$(OUTDIR)\dskwipe.bsc" 85 | BSC32_SBRS= \ 86 | 87 | LINK32=link.exe 88 | LINK32_FLAGS=shared.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 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)\dskwipe.pdb" /machine:I386 /out:"$(OUTDIR)\dskwipe.exe" 89 | LINK32_OBJS= \ 90 | "$(INTDIR)\dskwipe.obj" \ 91 | "$(INTDIR)\dskwipe.res" 92 | 93 | "$(OUTDIR)\dskwipe.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) 94 | $(LINK32) @<< 95 | $(LINK32_FLAGS) $(LINK32_OBJS) 96 | << 97 | 98 | !ELSEIF "$(CFG)" == "dskwipe - Win32 Debug" 99 | 100 | OUTDIR=.\Debug 101 | INTDIR=.\Debug 102 | # Begin Custom Macros 103 | OutDir=.\Debug 104 | # End Custom Macros 105 | 106 | ALL : "$(OUTDIR)\dskwipe.exe" "$(OUTDIR)\dskwipe.bsc" 107 | 108 | 109 | CLEAN : 110 | -@erase "$(INTDIR)\dskwipe.obj" 111 | -@erase "$(INTDIR)\dskwipe.res" 112 | -@erase "$(INTDIR)\dskwipe.sbr" 113 | -@erase "$(INTDIR)\vc60.idb" 114 | -@erase "$(INTDIR)\vc60.pdb" 115 | -@erase "$(OUTDIR)\dskwipe.bsc" 116 | -@erase "$(OUTDIR)\dskwipe.exe" 117 | -@erase "$(OUTDIR)\dskwipe.ilk" 118 | -@erase "$(OUTDIR)\dskwipe.pdb" 119 | 120 | "$(OUTDIR)" : 121 | if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" 122 | 123 | CPP=cl.exe 124 | CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /I "..\shared" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\dskwipe.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 125 | 126 | .c{$(INTDIR)}.obj:: 127 | $(CPP) @<< 128 | $(CPP_PROJ) $< 129 | << 130 | 131 | .cpp{$(INTDIR)}.obj:: 132 | $(CPP) @<< 133 | $(CPP_PROJ) $< 134 | << 135 | 136 | .cxx{$(INTDIR)}.obj:: 137 | $(CPP) @<< 138 | $(CPP_PROJ) $< 139 | << 140 | 141 | .c{$(INTDIR)}.sbr:: 142 | $(CPP) @<< 143 | $(CPP_PROJ) $< 144 | << 145 | 146 | .cpp{$(INTDIR)}.sbr:: 147 | $(CPP) @<< 148 | $(CPP_PROJ) $< 149 | << 150 | 151 | .cxx{$(INTDIR)}.sbr:: 152 | $(CPP) @<< 153 | $(CPP_PROJ) $< 154 | << 155 | 156 | RSC=rc.exe 157 | RSC_PROJ=/l 0x409 /fo"$(INTDIR)\dskwipe.res" /d "_DEBUG" 158 | BSC32=bscmake.exe 159 | BSC32_FLAGS=/nologo /o"$(OUTDIR)\dskwipe.bsc" 160 | BSC32_SBRS= \ 161 | "$(INTDIR)\dskwipe.sbr" 162 | 163 | "$(OUTDIR)\dskwipe.bsc" : "$(OUTDIR)" $(BSC32_SBRS) 164 | $(BSC32) @<< 165 | $(BSC32_FLAGS) $(BSC32_SBRS) 166 | << 167 | 168 | LINK32=link.exe 169 | LINK32_FLAGS=sharedd.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 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)\dskwipe.pdb" /debug /machine:I386 /out:"$(OUTDIR)\dskwipe.exe" /pdbtype:sept 170 | LINK32_OBJS= \ 171 | "$(INTDIR)\dskwipe.obj" \ 172 | "$(INTDIR)\dskwipe.res" 173 | 174 | "$(OUTDIR)\dskwipe.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) 175 | $(LINK32) @<< 176 | $(LINK32_FLAGS) $(LINK32_OBJS) 177 | << 178 | 179 | !ENDIF 180 | 181 | 182 | !IF "$(NO_EXTERNAL_DEPS)" != "1" 183 | !IF EXISTS("dskwipe.dep") 184 | !INCLUDE "dskwipe.dep" 185 | !ELSE 186 | !MESSAGE Warning: cannot find "dskwipe.dep" 187 | !ENDIF 188 | !ENDIF 189 | 190 | 191 | !IF "$(CFG)" == "dskwipe - Win32 Release" || "$(CFG)" == "dskwipe - Win32 Debug" 192 | SOURCE=.\dskwipe.cpp 193 | 194 | !IF "$(CFG)" == "dskwipe - Win32 Release" 195 | 196 | 197 | "$(INTDIR)\dskwipe.obj" : $(SOURCE) "$(INTDIR)" 198 | 199 | 200 | !ELSEIF "$(CFG)" == "dskwipe - Win32 Debug" 201 | 202 | 203 | "$(INTDIR)\dskwipe.obj" "$(INTDIR)\dskwipe.sbr" : $(SOURCE) "$(INTDIR)" 204 | 205 | 206 | !ENDIF 207 | 208 | SOURCE=.\dskwipe.rc 209 | 210 | "$(INTDIR)\dskwipe.res" : $(SOURCE) "$(INTDIR)" 211 | $(RSC) $(RSC_PROJ) $(SOURCE) 212 | 213 | 214 | 215 | !ENDIF 216 | 217 | -------------------------------------------------------------------------------- /dskwipe.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 27 | 30 | 33 | 36 | 39 | 44 | 61 | 64 | 69 | 72 | 85 | 88 | 91 | 94 | 99 | 102 | 105 | 108 | 109 | 119 | 122 | 125 | 128 | 131 | 136 | 152 | 155 | 160 | 163 | 175 | 178 | 181 | 184 | 189 | 192 | 195 | 198 | 199 | 200 | 201 | 202 | 203 | 207 | 210 | 213 | 218 | 219 | 222 | 227 | 228 | 229 | 230 | 234 | 237 | 238 | 239 | 243 | 246 | 247 | 250 | 253 | 257 | 258 | 261 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | -------------------------------------------------------------------------------- /dskwipe.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {54D2922C-4D55-461F-9B3C-967849BC7F59} 15 | 16 | 17 | 18 | Application 19 | false 20 | MultiByte 21 | v140 22 | 23 | 24 | Application 25 | false 26 | MultiByte 27 | v140 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>10.0.30319.1 43 | .\Debug\ 44 | .\Debug\ 45 | true 46 | .\Release\ 47 | .\Release\ 48 | false 49 | 50 | 51 | 52 | .\Debug/dskwipe.tlb 53 | 54 | 55 | 56 | 57 | Disabled 58 | ..\shared;%(AdditionalIncludeDirectories) 59 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 60 | true 61 | EnableFastChecks 62 | MultiThreadedDebug 63 | .\Debug/dskwipe.pch 64 | .\Debug/ 65 | .\Debug/ 66 | .\Debug/ 67 | true 68 | Level3 69 | false 70 | EditAndContinue 71 | 72 | 73 | _DEBUG;%(PreprocessorDefinitions) 74 | 0x0409 75 | 76 | 77 | sharedd.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 78 | .\Debug/dskwipe.exe 79 | true 80 | true 81 | .\Debug/dskwipe.pdb 82 | Console 83 | false 84 | 85 | 86 | MachineX86 87 | false 88 | 89 | 90 | true 91 | .\Debug/dskwipe.bsc 92 | 93 | 94 | 95 | 96 | .\Release/dskwipe.tlb 97 | 98 | 99 | 100 | 101 | MaxSpeed 102 | OnlyExplicitInline 103 | ..\shared;%(AdditionalIncludeDirectories) 104 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | MultiThreaded 107 | true 108 | .\Release/dskwipe.pch 109 | .\Release/ 110 | .\Release/ 111 | .\Release/ 112 | Level3 113 | false 114 | 115 | 116 | NDEBUG;%(PreprocessorDefinitions) 117 | 0x0409 118 | 119 | 120 | shared.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 121 | .\Release/dskwipe.exe 122 | true 123 | .\Release/dskwipe.pdb 124 | Console 125 | false 126 | 127 | 128 | MachineX86 129 | 130 | 131 | true 132 | .\Release/dskwipe.bsc 133 | 134 | 135 | 136 | 137 | %(AdditionalIncludeDirectories) 138 | %(PreprocessorDefinitions) 139 | %(AdditionalIncludeDirectories) 140 | %(PreprocessorDefinitions) 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | 3 | # 4 | 5 | syntax: glob 6 | 7 | ### VisualStudio ### 8 | 9 | # User-specific files 10 | *.suo 11 | *.user 12 | *.userosscache 13 | *.sln.docstates 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | build/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | msbuild.log 27 | 28 | # Roslyn stuff 29 | *.sln.ide 30 | *.ide/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | #NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding addin-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | *.pubxml 137 | *.publishproj 138 | 139 | # NuGet Packages 140 | *.nupkg 141 | **/packages/* 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *.dbmdl 157 | *.dbproj.schemaview 158 | *.pfx 159 | *.publishsettings 160 | node_modules/ 161 | *.metaproj 162 | *.metaproj.tmp 163 | 164 | # RIA/Silverlight projects 165 | Generated_Code/ 166 | 167 | # Backup & report files from converting an old project file 168 | # to a newer Visual Studio version. Backup files are not needed, 169 | # because we have git ;-) 170 | _UpgradeReport_Files/ 171 | Backup*/ 172 | UpgradeLog*.XML 173 | UpgradeLog*.htm 174 | 175 | # SQL Server files 176 | *.mdf 177 | *.ldf 178 | 179 | # Business Intelligence projects 180 | *.rdl.data 181 | *.bim.layout 182 | *.bim_*.settings 183 | 184 | # Microsoft Fakes 185 | FakesAssemblies/ 186 | 187 | ### MonoDevelop ### 188 | 189 | *.pidb 190 | *.userprefs 191 | 192 | ### Windows ### 193 | 194 | # Windows image file caches 195 | Thumbs.db 196 | ehthumbs.db 197 | 198 | # Folder config file 199 | Desktop.ini 200 | 201 | # Recycle Bin used on file shares 202 | $RECYCLE.BIN/ 203 | 204 | # Windows Installer files 205 | *.cab 206 | *.msi 207 | *.msm 208 | *.msp 209 | 210 | # Windows shortcuts 211 | *.lnk 212 | 213 | ### Linux ### 214 | 215 | *~ 216 | 217 | # KDE directory preferences 218 | .directory 219 | 220 | ### OSX ### 221 | 222 | .DS_Store 223 | .AppleDouble 224 | .LSOverride 225 | 226 | # Icon must end with two \r 227 | Icon 228 | 229 | # Thumbnails 230 | ._* 231 | 232 | # Files that might appear on external disk 233 | .Spotlight-V100 234 | .Trashes 235 | 236 | # Directories potentially created on remote AFP share 237 | .AppleDB 238 | .AppleDesktop 239 | Network Trash Folder 240 | Temporary Items 241 | .apdisk 242 | # 243 | # 244 | ## Ignore Visual Studio temporary files, build results, and 245 | ## files generated by popular Visual Studio add-ons. 246 | 247 | # User-specific files 248 | *.suo 249 | *.user 250 | *.userosscache 251 | *.sln.docstates 252 | 253 | # User-specific files (MonoDevelop/Xamarin Studio) 254 | *.userprefs 255 | 256 | # Build results 257 | [Dd]ebug/ 258 | [Dd]ebugPublic/ 259 | [Rr]elease/ 260 | [Rr]eleases/ 261 | x64/ 262 | x86/ 263 | build/ 264 | bld/ 265 | [Bb]in/ 266 | [Oo]bj/ 267 | 268 | # Roslyn cache directories 269 | *.ide/ 270 | 271 | # MSTest test Results 272 | [Tt]est[Rr]esult*/ 273 | [Bb]uild[Ll]og.* 274 | 275 | #NUNIT 276 | *.VisualState.xml 277 | TestResult.xml 278 | 279 | # Build Results of an ATL Project 280 | [Dd]ebugPS/ 281 | [Rr]eleasePS/ 282 | dlldata.c 283 | 284 | *_i.c 285 | *_p.c 286 | *_i.h 287 | *.ilk 288 | *.meta 289 | *.obj 290 | *.pch 291 | *.pdb 292 | *.pgc 293 | *.pgd 294 | *.rsp 295 | *.sbr 296 | *.tlb 297 | *.tli 298 | *.tlh 299 | *.tmp 300 | *.tmp_proj 301 | *.log 302 | *.vspscc 303 | *.vssscc 304 | .builds 305 | *.pidb 306 | *.svclog 307 | *.scc 308 | 309 | # Chutzpah Test files 310 | _Chutzpah* 311 | 312 | # Visual C++ cache files 313 | ipch/ 314 | *.aps 315 | *.ncb 316 | *.opensdf 317 | *.sdf 318 | *.cachefile 319 | 320 | # Visual Studio profiler 321 | *.psess 322 | *.vsp 323 | *.vspx 324 | 325 | # TFS 2012 Local Workspace 326 | $tf/ 327 | 328 | # Guidance Automation Toolkit 329 | *.gpState 330 | 331 | # ReSharper is a .NET coding add-in 332 | _ReSharper*/ 333 | *.[Rr]e[Ss]harper 334 | *.DotSettings.user 335 | 336 | # JustCode is a .NET coding addin-in 337 | .JustCode 338 | 339 | # TeamCity is a build add-in 340 | _TeamCity* 341 | 342 | # DotCover is a Code Coverage Tool 343 | *.dotCover 344 | 345 | # NCrunch 346 | _NCrunch_* 347 | .*crunch*.local.xml 348 | 349 | # MightyMoose 350 | *.mm.* 351 | AutoTest.Net/ 352 | 353 | # Web workbench (sass) 354 | .sass-cache/ 355 | 356 | # Installshield output folder 357 | [Ee]xpress/ 358 | 359 | # DocProject is a documentation generator add-in 360 | DocProject/buildhelp/ 361 | DocProject/Help/*.HxT 362 | DocProject/Help/*.HxC 363 | DocProject/Help/*.hhc 364 | DocProject/Help/*.hhk 365 | DocProject/Help/*.hhp 366 | DocProject/Help/Html2 367 | DocProject/Help/html 368 | 369 | # Click-Once directory 370 | publish/ 371 | 372 | # Publish Web Output 373 | *.[Pp]ublish.xml 374 | *.azurePubxml 375 | # TODO: Comment the next line if you want to checkin your web deploy settings 376 | # but database connection strings (with potential passwords) will be unencrypted 377 | *.pubxml 378 | *.publishproj 379 | 380 | # NuGet Packages 381 | *.nupkg 382 | # The packages folder can be ignored because of Package Restore 383 | **/packages/* 384 | # except build/, which is used as an MSBuild target. 385 | !**/packages/build/ 386 | # Uncomment if necessary however generally it will be regenerated when needed 387 | #!**/packages/repositories.config 388 | 389 | # Windows Azure Build Output 390 | csx/ 391 | *.build.csdef 392 | 393 | # Windows Store app package directory 394 | AppPackages/ 395 | 396 | # Others 397 | *.[Cc]ache 398 | ClientBin/ 399 | [Ss]tyle[Cc]op.* 400 | ~$* 401 | *~ 402 | *.dbmdl 403 | *.dbproj.schemaview 404 | *.pfx 405 | *.publishsettings 406 | node_modules/ 407 | bower_components/ 408 | 409 | # RIA/Silverlight projects 410 | Generated_Code/ 411 | 412 | # Backup & report files from converting an old project file 413 | # to a newer Visual Studio version. Backup files are not needed, 414 | # because we have git ;-) 415 | _UpgradeReport_Files/ 416 | Backup*/ 417 | UpgradeLog*.XML 418 | UpgradeLog*.htm 419 | 420 | # SQL Server files 421 | *.mdf 422 | *.ldf 423 | 424 | # Business Intelligence projects 425 | *.rdl.data 426 | *.bim.layout 427 | *.bim_*.settings 428 | 429 | # Microsoft Fakes 430 | FakesAssemblies/ 431 | 432 | # Node.js Tools for Visual Studio 433 | .ntvs_analysis.dat 434 | 435 | # Visual Studio 6 build log 436 | *.plg 437 | 438 | # Visual Studio 6 workspace options file 439 | *.opt 440 | # 441 | 442 | # other compiler artifacts 443 | *.bsc 444 | *.idb 445 | 446 | # build artifacts 447 | [Dd]ebug*/ 448 | [Rr]elease*/ 449 | *.exe 450 | *.lib 451 | *.zip 452 | 453 | # backup files 454 | *.bak 455 | *.old 456 | 457 | md5s.txt 458 | sha1s.txt 459 | sha256s.txt 460 | *.asc 461 | *.sha256 462 | 463 | .*.uploaded 464 | .*.scanned 465 | .*.released 466 | .*.tagged 467 | 468 | *.opendb 469 | 470 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2002-2015, Ross Smith II. MIT licensed. 2 | 3 | ## dependencies: 4 | ## Cygwin 5 | ## NSIS 2.41 (https://sourceforge.net/projects/nsis/files/NSIS%202/2.41/) 6 | ## NSIS log build (http://sourceforge.net/projects/nsis/files/NSIS%202/2.41/nsis-2.41-log.zip/download) 7 | ## NSIS NsUnzip plugin (http://nsis.sourceforge.net/NsUnzip_plugin) 8 | ## NSIS Inetc plugin (http://nsis.sourceforge.net/Inetc_plug-in) 9 | ## signtool (provided by Visual Studio or Windows SDK) 10 | 11 | ## cygwin dependencies: 12 | ## curl 13 | ## cygpath 14 | ## git 15 | ## gpg 16 | ## md5sum 17 | ## sha1sum 18 | ## sha256sum 19 | ## upx 20 | ## zip 21 | ## basename, cat, cp, echo, grep, mkdir, rm, sed, sleep, test, touch, etc. 22 | 23 | ## nsis builds: 24 | ifneq ("$(wildcard version.txt)", "") 25 | VER?=$(strip $(shell cat version.txt)) 26 | APP?=$(basename $(wildcard *.nsi)) 27 | endif 28 | 29 | ## c/c++ builds: 30 | ifneq ("$(wildcard version.h)", "") 31 | VER?=$(strip $(shell sed -rne 's/^\s*\#define\s+(VER_STRING2|PACKAGE_VERSION)\s+"([^"]*)".*/\2/p' version.h)) 32 | APP?=$(strip $(shell sed -rne 's/^\s*\#define\s+(VER_INTERNAL_NAME|PACKAGE)\s+"([^"]*)".*/\2/p' version.h)) 33 | endif 34 | 35 | APP_EXE:=$(APP).exe 36 | 37 | APP_FILES:=\ 38 | $(APP_EXE) \ 39 | $(wildcard LICENSE) \ 40 | $(wildcard *.md) 41 | 42 | ####################################################################### 43 | 44 | FLAVOR?=win32 45 | REPO?=$(notdir $(PWD)) 46 | 47 | APP_DESC?=$(APP) 48 | APP_URL?=http://github.com/rasa/$(REPO)/ 49 | APP_ZIP?=$(APP)-$(VER)-$(FLAVOR).zip 50 | CODESIGN_PFX?=../codesign.pfx 51 | CURL?=curl 52 | CURL_OPTS?=--netrc --insecure --silent --show-error 53 | GPG_OPTS?= 54 | HASH_FILES?=md5s.txt sha1s.txt sha256s.txt 55 | ifeq ("$(FLAVOR)", "win32") 56 | RELEASE_APP_EXE?=Release/$(APP_EXE) 57 | else 58 | RELEASE_APP_EXE?=Release/$(FLAVOR)/$(APP_EXE) 59 | endif 60 | RELEASE_URL?=https://api.github.com/repos/rasa/$(REPO)/releases 61 | TAG?=v$(VER) 62 | ## fails occasionally: http://timestamp.verisign.com/scripts/timstamp.dll 63 | TIMESTAMP_URL?=http://timestamp.globalsign.com/scripts/timstamp.dll 64 | VIRUSTOTAL_URL?=https://www.virustotal.com/vtapi/v2/file/scan 65 | ZIP_OPTS+=-9 66 | 67 | APP_FILES+=$(HASH_FILES) 68 | RELEASED:=.$(TAG).released 69 | 70 | ####################################################################### 71 | 72 | ifneq ("$(wildcard makensis.mk)", "") 73 | NMAKER?=makensis.mk 74 | endif 75 | 76 | ifneq ("$(wildcard msbuild.mk)", "") 77 | ifneq ("$(shell which MSBuild.exe 2>/dev/null)", "") 78 | CMAKER?=msbuild.mk 79 | endif 80 | endif 81 | 82 | ifneq ("$(wildcard vcbuild.mk)", "") 83 | ifneq ("$(shell which VCBuild.exe 2>/dev/null)", "") 84 | CMAKER?=vcbuild.mk 85 | endif 86 | endif 87 | 88 | CMAKER?=nmake.mk 89 | 90 | ####################################################################### 91 | 92 | ifndef SIGNTOOL 93 | ifneq ($(shell which signtool.exe 2>/dev/null),) 94 | SIGNTOOL:=$(shell which signtool.exe 2>/dev/null) 95 | endif 96 | endif 97 | 98 | define FIND_SIGNTOOL 99 | 100 | ifndef SIGNTOOL 101 | SDK_DIR:=$$(shell cygpath -m -s "$(1)" 2>/dev/null) 102 | ifneq ($$(wildcard $$(SDK_DIR)/signtool.exe),) 103 | SIGNTOOL:=$$(SDK_DIR)/signtool.exe 104 | endif 105 | endif 106 | 107 | endef 108 | 109 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v8.2/Bin)) 110 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v8.1A/Bin)) 111 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v8.1/Bin)) 112 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v8.0A/Bin)) 113 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v8.0/Bin)) 114 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v7.1A/Bin)) 115 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v7.1/Bin)) 116 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v7.0A/Bin)) 117 | $(eval $(call FIND_SIGNTOOL,$(PROGRAMFILES)/Microsoft SDKs/Windows/v7.0/Bin)) 118 | 119 | ####################################################################### 120 | 121 | UPXED_FILES= 122 | 123 | define UPX_FILE 124 | 125 | $(2): $(1) 126 | test -d $(dir $(2)) || mkdir $(dir $(2)) 127 | test ! -f $(2) || rm -f $(2) 128 | upx --best --overlay=skip --quiet -o $(2) $(1) || cp -p $(1) $(2) 129 | 130 | UPXED_FILES+=$(2) 131 | 132 | endef 133 | 134 | ####################################################################### 135 | 136 | SIGNED_FILES= 137 | 138 | define SIGN_FILE 139 | 140 | $(2): $(1) $(CODESIGN_PFX) 141 | test -d $(dir $(2)) || mkdir $(dir $(2)) 142 | for try in 1 2 3 4 5 6 7 8 9 10; do \ 143 | "$(SIGNTOOL)" verify /pa /q $(1) &>/dev/null && break ;\ 144 | "$(SIGNTOOL)" sign \ 145 | /d "$(3)" \ 146 | /du "$(4)" \ 147 | /f "$(CODESIGN_PFX)" \ 148 | /q \ 149 | /t "$(TIMESTAMP_URL)" \ 150 | $(1) ;\ 151 | sleep $$$$(( 2 ** $$$${try} )) ;\ 152 | done 153 | cp $(1) $(2) 154 | 155 | SIGNED_FILES+=$(2) 156 | 157 | endef 158 | 159 | ####################################################################### 160 | 161 | UPLOADED_FILES= 162 | 163 | define UPLOAD_FILE 164 | 165 | .$(1).uploaded: $(1) $(RELEASED) 166 | $(CURL) $(CURL_OPTS) \ 167 | --write-out "%{http_code}" \ 168 | --output /tmp/$(1).tmp \ 169 | --include \ 170 | "$(RELEASE_URL)/tags/$(TAG)" |\ 171 | grep -q ^2 || (cat /tmp/$(1).tmp ; echo ; exit 1) 172 | sed -nr -e 's/.*upload_url": "(.*)\{.*/url=\1?name=$(1)/p' /tmp/$(1).tmp >/tmp/$(1).curlrc 173 | $(CURL) $(CURL_OPTS) \ 174 | --request POST \ 175 | --data-binary @$(1) \ 176 | -H "Content-Type:$(2)" \ 177 | --write-out %{http_code} \ 178 | --output /tmp/$(1)-2.tmp \ 179 | --include \ 180 | --config /tmp/$(1).curlrc | \ 181 | grep -q ^2 || (cat /tmp/$(1)*.tmp ; echo ; exit 1) 182 | -rm -f /tmp/$(1).tmp /tmp/$(1)-2.tmp 183 | @-echo $(1) uploaded to Github 184 | touch .$(1).uploaded 185 | 186 | UPLOADED_FILES+=.$(1).uploaded 187 | 188 | endef 189 | 190 | ####################################################################### 191 | 192 | SCANNED_FILES= 193 | 194 | define SCAN_FILE 195 | 196 | .$(2)-$(1).scanned: $(1) 197 | test -n "$(VIRUSTOTAL_API_KEY)" || (echo VIRUSTOTAL_API_KEY not set >&2 ; exit 1) 198 | $(CURL) $(CURL_OPTS) \ 199 | -X POST \ 200 | --form apikey=$(VIRUSTOTAL_API_KEY) \ 201 | --form file=@$(1) \ 202 | --write-out "%{http_code}" \ 203 | --output /tmp/$(1).tmp \ 204 | --include \ 205 | $(VIRUSTOTAL_URL) | \ 206 | grep -q ^2 || (cat /tmp/$(1).tmp ; echo ; exit 1) 207 | -rm -f /tmp/$(1).tmp 208 | touch .$(2)-$(1).scanned 209 | 210 | SCANNED_FILES+=.$(2)-$(1).scanned 211 | 212 | endef 213 | 214 | ####################################################################### 215 | 216 | ifneq ("$(wildcard local.mk)", "") 217 | include local.mk 218 | endif 219 | 220 | ####################################################################### 221 | 222 | .PHONY: help 223 | help: 224 | @echo "make all # build Release/.exe" 225 | @echo "make upx # compress Release/.exe (implies all)" 226 | @echo "make sign # sign .exe (implies upx)" 227 | @echo "make hashes # create hash files (implies all)" 228 | @echo "make zip # build .zip (implies sign)" 229 | @echo "make tag # create tag $(TAG) on Github (implies zip)" 230 | @echo "make release # create release $(TAG) on Github (implies tag)" 231 | @echo "make sig # create .asc (implies zip)" 232 | @echo "make sum # create .sha256 (implies zip)" 233 | @echo "make upload # upload .zip/.asc/.sha256 to Github (implies release/sig/sum)" 234 | @echo "make scan # upload .exe & .zip to Virustotal (implies zip)" 235 | @echo "make publish # same as 'make upload scan'" 236 | @echo 237 | @echo "make clean # remove Release/.exe and related build files" 238 | @echo "make distclean # remove .zip/.asc/.sha256 (implies clean)" 239 | @echo "make tidy # remove .exe & hash .txt's (implies clean)" 240 | @echo "make help # display this help text" 241 | 242 | ####################################################################### 243 | 244 | ifdef NMAKER 245 | include $(NMAKER) 246 | else 247 | include $(CMAKER) 248 | $(RELEASE_APP_EXE): all 249 | 250 | endif 251 | 252 | ####################################################################### 253 | 254 | RELEASE_UPX_EXE:=$(dir $(RELEASE_APP_EXE))upxed/$(notdir $(RELEASE_APP_EXE)) 255 | 256 | $(eval $(call UPX_FILE,$(RELEASE_APP_EXE),$(RELEASE_UPX_EXE))) 257 | 258 | .PHONY: upx 259 | upx: $(RELEASE_UPX_EXE) 260 | 261 | ####################################################################### 262 | 263 | $(CODESIGN_PFX): 264 | @echo The file $(CODESIGN_PFX) is required to sign code with. >&2 265 | exit 1 266 | 267 | $(eval $(call SIGN_FILE,$(RELEASE_UPX_EXE),$(APP_EXE),$(APP_DESC),$(APP_URL))) 268 | 269 | .PHONY: sign 270 | sign: $(SIGNED_FILES) 271 | 272 | ####################################################################### 273 | 274 | md5s.txt: $(APP_EXE) 275 | md5sum $^ >$@ 276 | 277 | sha1s.txt: $(APP_EXE) 278 | sha1sum $^ >$@ 279 | 280 | sha256s.txt: $(APP_EXE) 281 | sha256sum $^ >$@ 282 | 283 | .PHONY: hashes 284 | hashes: $(HASH_FILES) 285 | 286 | ####################################################################### 287 | 288 | $(APP_ZIP): $(APP_FILES) 289 | -rm -f $@ 290 | zip $(ZIP_OPTS) $@ $^ 291 | 292 | .PHONY: zip 293 | zip: $(APP_ZIP) 294 | 295 | .PHONY: dist 296 | dist: zip 297 | 298 | ####################################################################### 299 | 300 | TAGGED:=.$(TAG).tagged 301 | 302 | $(TAGGED): $(APP_ZIP) 303 | if ! git tag | grep -q -P "\b$(TAG)\b"; then \ 304 | git tag -a $(TAG) -m "Version $(VER)" ;\ 305 | fi 306 | git push origin --tags 307 | touch $@ 308 | @-echo Tag $(TAG) created on Github 309 | 310 | .PHONY: tag 311 | tag: $(TAGGED) 312 | 313 | ####################################################################### 314 | 315 | $(RELEASED): $(TAGGED) 316 | $(CURL) $(CURL_OPTS) \ 317 | --request POST \ 318 | --data "{\"tag_name\": \"$(TAG)\",\"name\": \"$(TAG)\", \"body\": \"Release $(TAG)\"}" \ 319 | --write-out "%{http_code}" \ 320 | --output /tmp/$(RELEASED).tmp \ 321 | --include \ 322 | "$(RELEASE_URL)" | grep -q ^2 || (cat /tmp/$(RELEASED).tmp ; echo ; exit 1) 323 | touch $@ 324 | @-echo Release $(TAG) created on Github 325 | 326 | .PHONY: release 327 | release: $(RELEASED) 328 | 329 | ####################################################################### 330 | 331 | APP_ZIP_ASC:=$(APP_ZIP).asc 332 | 333 | $(APP_ZIP_ASC): $(APP_ZIP) 334 | gpg $(GPG_OPTS) --yes --armor --detach-sign --output $@ $^ 335 | 336 | .PHONY: sig 337 | sig: $(APP_ZIP_ASC) 338 | 339 | ####################################################################### 340 | 341 | APP_ZIP_SHA:=$(APP_ZIP).sha256 342 | 343 | $(APP_ZIP_SHA): $(APP_ZIP) 344 | sha256sum $^ >$@ 345 | 346 | .PHONY: sum 347 | sum: $(APP_ZIP_SHA) 348 | 349 | ####################################################################### 350 | 351 | $(eval $(call UPLOAD_FILE,$(APP_ZIP),application/zip)) 352 | 353 | $(eval $(call UPLOAD_FILE,$(APP_ZIP_ASC),text/plain)) 354 | 355 | $(eval $(call UPLOAD_FILE,$(APP_ZIP_SHA),text/plain)) 356 | 357 | .PHONY: upload 358 | upload: $(UPLOADED_FILES) 359 | 360 | ####################################################################### 361 | 362 | $(eval $(call SCAN_FILE,$(APP_EXE),$(TAG))) 363 | 364 | $(eval $(call SCAN_FILE,$(APP_ZIP),$(TAG))) 365 | 366 | .PHONY: scan 367 | scan: $(SCANNED_FILES) 368 | 369 | ####################################################################### 370 | 371 | .PHONY: publish 372 | publish: $(UPLOADED_FILES) $(SCANNED_FILES) 373 | 374 | ####################################################################### 375 | 376 | .PHONY: tidy 377 | tidy: clean 378 | -rm -f $(CLEAN_FILES) \ 379 | $(HASH_FILES) \ 380 | $(SIGNED_FILES) \ 381 | $(UPXED_FILES) 382 | 383 | ####################################################################### 384 | 385 | .PHONY: distclean 386 | distclean: tidy 387 | -rm -f $(APP_ZIP) \ 388 | $(APP_ZIP_ASC) \ 389 | $(APP_ZIP_SHA) 390 | 391 | ####################################################################### 392 | 393 | .PHONY: debug 394 | debug: 395 | @echo APP=$(APP) 396 | @echo APP_DESC=$(APP_DESC) 397 | @echo APP_EXE=$(APP_EXE) 398 | @echo APP_FILES=$(APP_FILES) 399 | @echo APP_URL=$(APP_URL) 400 | @echo APP_ZIP=$(APP_ZIP) 401 | @echo APP_ZIP_ASC=$(APP_ZIP_ASC) 402 | @echo APP_ZIP_SHA=$(APP_ZIP_SHA) 403 | @echo CMAKER=$(CMAKER) 404 | @echo CODESIGN_PFX=$(CODESIGN_PFX) 405 | @echo CURL=$(CURL) 406 | @echo CURL_OPTS=$(CURL_OPTS) 407 | @echo FLAVOR=$(FLAVOR) 408 | @echo GPG_OPTS=$(GPG_OPTS) 409 | @echo HASH_FILES=$(HASH_FILES) 410 | @echo NMAKER=$(NMAKER) 411 | @echo RELEASED=$(RELEASED) 412 | @echo RELEASE_APP_EXE=$(RELEASE_APP_EXE) 413 | @echo RELEASE_UPX_EXE=$(RELEASE_UPX_EXE) 414 | @echo RELEASE_URL=$(RELEASE_URL) 415 | @echo REPO=$(REPO) 416 | @echo SCANNED_FILES=$(SCANNED_FILES) 417 | @echo SIGNED_FILES=$(SIGNED_FILES) 418 | @echo TAG=$(TAG) 419 | @echo TAGGED=$(TAGGED) 420 | @echo TIMESTAMP_URL=$(TIMESTAMP_URL) 421 | @echo UPLOADED_FILES=$(UPLOADED_FILES) 422 | @echo UPXED_FILES=$(UPXED_FILES) 423 | @echo VER=$(VER) 424 | @echo VIRUSTOTAL_URL=$(VIRUSTOTAL_URL) 425 | @echo ZIP_OPTS=$(ZIP_OPTS) 426 | -------------------------------------------------------------------------------- /dskwipe.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2005-2016 Ross Smith II. See Mit LICENSE in /LICENSE 2 | 3 | /* 4 | todo/wishlist 5 | handle bad sectors without failing 6 | scramble the MFT/FAT tables first 7 | catch ctrl-C to report where to start over 8 | Implement HAVE_CRYPTOGRAPHIC using TrueCrypt's RNG 9 | */ 10 | 11 | #ifdef _MSC_VER 12 | #pragma warning(disable:4996) 13 | #pragma comment(lib, "advapi32.lib") 14 | #pragma comment(lib, "user32.lib") 15 | #endif 16 | 17 | #include 18 | 19 | #include 20 | #include // time() 21 | #include // _getpid() 22 | #include 23 | #include 24 | 25 | #include "getopt.h" 26 | 27 | #include "version.h" 28 | 29 | #define APPNAME VER_INTERNAL_NAME 30 | #define APPVERSION VER_STRING2 31 | #define APPCOPYRIGHT VER_LEGAL_COPYRIGHT 32 | 33 | static char *progname = APPNAME; 34 | 35 | #undef HAVE_CRYPTOGRAPHIC 36 | 37 | //#define DUMMY_WRITE 1 38 | 39 | #define BYTES_PER_ELEMENT (3) 40 | 41 | #define SECTORS_PER_READ (64) 42 | 43 | // \todo convert separate wipe arrays to one array 44 | 45 | int dod_bytes[] = {0x00, 0xff, -1}; 46 | 47 | int dod_elements = sizeof(dod_bytes) / sizeof(dod_bytes[0]); 48 | 49 | // source: BCWipe-1.6-5/bcwipe/wipe.h 50 | int dod7_bytes[] = {0x35, 0xca, 0x97, 0x68, 0xac, 0x53, -1}; 51 | 52 | int dod7_elements = sizeof(dod7_bytes) / sizeof(dod7_bytes[0]); 53 | 54 | int bci_bytes[] = {0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xaa}; 55 | 56 | int bci_elements = sizeof(bci_bytes) / sizeof(bci_bytes[0]); 57 | 58 | int doe_bytes[] = {-1, -1, 0x00}; 59 | 60 | int doe_elements = sizeof(doe_bytes) / sizeof(doe_bytes[0]); 61 | 62 | int schneier_bytes[] = {0xff, 0x00, -1, -1, -1, -1, -1}; 63 | 64 | int schneier_elements = sizeof(schneier_bytes) / sizeof(schneier_bytes[0]); 65 | 66 | // source: http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html 67 | int gutmann_bytes[][BYTES_PER_ELEMENT] = { 68 | {-1, -1, -1}, // 1 69 | {-1, -1, -1}, // 2 70 | {-1, -1, -1}, // 3 71 | {-1, -1, -1}, // 4 72 | {0x55, 0x55, 0x55}, // 5 73 | {0xAA, 0xAA, 0xAA}, // 6 74 | {0x92, 0x49, 0x24}, // 7 75 | {0x49, 0x24, 0x92}, // 8 76 | {0x24, 0x92, 0x49}, // 9 77 | {0x00, 0x00, 0x00}, // 10 78 | {0x11, 0x11, 0x11}, // 11 79 | {0x22, 0x22, 0x22}, // 12 80 | {0x33, 0x33, 0x33}, // 13 81 | {0x44, 0x44, 0x44}, // 14 82 | {0x55, 0x55, 0x55}, // 15 83 | {0x66, 0x66, 0x66}, // 16 84 | {0x77, 0x77, 0x77}, // 17 85 | {0x88, 0x88, 0x88}, // 18 86 | {0x99, 0x99, 0x99}, // 19 87 | {0xAA, 0xAA, 0xAA}, // 20 88 | {0xBB, 0xBB, 0xBB}, // 21 89 | {0xCC, 0xCC, 0xCC}, // 22 90 | {0xDD, 0xDD, 0xDD}, // 23 91 | {0xEE, 0xEE, 0xEE}, // 24 92 | {0xFF, 0xFF, 0xFF}, // 25 93 | {0x92, 0x49, 0x24}, // 26 94 | {0x49, 0x24, 0x92}, // 27 95 | {0x24, 0x92, 0x49}, // 28 96 | {0x6D, 0xB6, 0xDB}, // 29 97 | {0xB6, 0xDB, 0x6D}, // 30 98 | {0xDB, 0x6D, 0xB6}, // 31 99 | {-1, -1, -1}, // 32 100 | {-1, -1, -1}, // 33 101 | {-1, -1, -1}, // 34 102 | {-1, -1, -1} // 35 103 | }; 104 | 105 | int gutmann_elements = sizeof(gutmann_bytes) / sizeof(gutmann_bytes[0]); 106 | 107 | // 1 2 3 4 5 6 7 108 | // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 109 | #define HEADER " This All All All \n" \ 110 | "Pass No. of Pass Passes Passes Passes Est. %s/\n" \ 111 | " No. Passes Byte Complete Complete Elapsed Remain. Start Finish Second\n" \ 112 | "---- ------ ---- -------- -------- -------- -------- -------- -------- --------\n" 113 | // 1234 123456 0xff 100.000% 100.000% 00:00:00 00:00:00 00:00:00 00:00:00 12345.67 114 | 115 | #define FORMAT_STRING "%4d %6d %4s %7.3f%% %7.3f%%%9s%9s %8s %8s%9.2f\r" 116 | 117 | static char *short_options = "12bde:Efgikln:p:qrs:Svx:yz:D?" 118 | 119 | #ifdef HAVE_CRYPTOGRAPHIC 120 | "3" 121 | #endif 122 | ; 123 | 124 | static struct option long_options[] = { 125 | {"bci", no_argument, 0, 'b'}, 126 | {"bruce", no_argument, 0, 'S'}, 127 | {"dod", no_argument, 0, 'd'}, 128 | {"dod3", no_argument, 0, 'd'}, 129 | {"dod7", no_argument, 0, 'D'}, 130 | {"doe", no_argument, 0, 'E'}, 131 | {"end", required_argument, 0, 'e'}, 132 | {"exit", required_argument, 0, 'x'}, 133 | {"force", no_argument, 0, 'f'}, 134 | {"gutmann", no_argument, 0, 'g'}, 135 | {"help", no_argument, 0, '?'}, 136 | {"ignore", no_argument, 0, 'i'}, 137 | {"ignore-errors", no_argument, 0, 'i'}, 138 | {"kilo", no_argument, 0, 'k'}, 139 | {"kilobyte", no_argument, 0, 'k'}, 140 | {"list", no_argument, 0, 'l'}, 141 | {"passes", required_argument, 0, 'p'}, 142 | {"pseudo", no_argument, 0, '1'}, 143 | {"quiet", no_argument, 0, 'q'}, 144 | {"read", no_argument, 0, 'r'}, 145 | {"refresh", required_argument, 0, 'z'}, 146 | {"schneier", no_argument, 0, 'S'}, 147 | {"sectors", required_argument, 0, 'n'}, 148 | {"start", required_argument, 0, 's'}, 149 | {"version", no_argument, 0, 'v'}, 150 | {"vsitr", no_argument, 0, 'b'}, 151 | {"windows", no_argument, 0, '2'}, 152 | {"yes", no_argument, 0, 'y'}, 153 | 154 | {"customwipe",required_argument, 0, 'p'}, // gdisk compatible 155 | {"dodwipe", no_argument, 0, 'd'}, // gdisk compatible 156 | {"sure", no_argument, 0, 'y'}, // gdisk compatible 157 | #ifdef HAVE_CRYPTOGRAPHIC 158 | {"crypto", no_argument, 0, '3'}, 159 | #endif 160 | /* 161 | {"poweroff", no_argument, 0, 'P'}, 162 | {"shutdown", no_argument, 0, 'S'}, 163 | {"hibernate", no_argument, 0, 'H'}, 164 | {"logoff", no_argument, 0, 'L'}, 165 | {"reboot", no_argument, 0, 'R'}, 166 | {"standby", no_argument, 0, 'T'}, 167 | */ 168 | {NULL, 0, 0, 0} 169 | }; 170 | 171 | void version() { 172 | printf(APPNAME " " APPVERSION " - " __DATE__ "\n"); 173 | printf(APPCOPYRIGHT "\n"); 174 | } 175 | 176 | typedef enum { 177 | EXIT_NONE, 178 | EXIT_POWEROFF, 179 | EXIT_SHUTDOWN, 180 | EXIT_HIBERNATE, 181 | EXIT_LOGOFF, 182 | EXIT_REBOOT, 183 | EXIT_STANDBY 184 | } ExitMode; 185 | 186 | char *exit_mode[] = { 187 | "none", 188 | "poweroff", 189 | "shutdown", 190 | "hibernate", 191 | "logoff", 192 | "reboot", 193 | "standby" 194 | }; 195 | 196 | int exit_modes = sizeof(exit_mode) / sizeof(exit_mode[0]); 197 | 198 | void _usage() { 199 | fprintf(stderr, "Usage: %s [options] device(s) [byte(s)]\n" 200 | " bytes can be one or more numbers between 0 to 255, use 0xNN for hexidecimal,\n" 201 | " 0NNN for octal, r for random bytes, default is 0\n" 202 | "\nOptions:\n" 203 | " -l | --list List available devices and exit\n" 204 | " -p | --passes n Wipe device n times (default is 1)\n" 205 | " -d | --dod Wipe device using US DoD 5220.22-M method (3 passes)\n" 206 | " -E | --doe Wipe device using US DoE method (3 passes)\n" 207 | " -D | --dod7 Wipe device using US DoD 5200.28-STD method (7 passes)\n" 208 | " -S | --schneier Wipe device using Bruce Schneier's method (7 passes)\n" 209 | " -b | --bci Wipe device using German BCI/VSITR method (7 passes)\n" 210 | " -g | --gutmann Wipe device using Peter Gutmann's method (35 passes)\n" 211 | " -1 | --pseudo Use pseudo RNG (fast, not secure, this is the default)\n" 212 | " -2 | --windows Use Windows RNG (slower, more secure)\n" 213 | #ifdef HAVE_CRYPTOGRAPHIC 214 | " -3 | --crypto Use cryptographically secure RNG (slowest, secure)\n" 215 | #endif 216 | " -k | --kilobyte Use 1024 for kilobyte (default is 1000)\n" 217 | " -y | --yes Start processing without waiting for confirmation\n" 218 | // 1 2 3 4 5 6 7 219 | // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 220 | 221 | " -x | --exit mode Exit Windows. mode can be: poweroff, shutdown, hibernate, \n" 222 | " logoff, reboot, or standby.\n" 223 | /* 224 | " -P | --poweroff Power off computer when finished\n" 225 | " -S | --shutdown Shutdown computer when finished\n" 226 | " -H | --hibernate Hibernate computer when finished\n" 227 | " -L | --logoff Log off computer when finished\n" 228 | " -R | --reboot Reboot computer when finished\n" 229 | " -T | --standby Standby computer when finished\n" 230 | */ 231 | " -f | --force Force poweroff/shutdown/logoff/reboot (WARNING: DATA LOSS!)\n" 232 | " -q | --quiet Display less information (-qq = quieter, etc.)\n" 233 | " -z | --refresh n Refresh display every n seconds (default is 1)\n" 234 | " -n | --sectors n Write n sectors at once (1-65535, default is %d)\n" 235 | " -s | --start n Start at relative sector n (default is 0)\n" 236 | " -e | --end n End at relative sector n (default is last sector)\n" 237 | " -r | --read Only read the data on the device (DOES NOT WIPE!)\n" 238 | " -i | --ignore Ignore certain read/write errors\n" 239 | " -v | --version Show version and copyright information and quit\n" 240 | " -? | --help Show this help message and quit (-?? = more help, etc.)\n", 241 | progname, SECTORS_PER_READ); 242 | } 243 | 244 | void examples() { 245 | fprintf(stderr, 246 | "\nExamples:\n" 247 | " %s -l & lists devices, and exit\n" 248 | " %s \\\\.\\PhysicalDrive1 & erase disk once using the byte 0\n" 249 | " %s \\Device\\Ramdisk 1 & erase disk once using the byte 1\n" 250 | " %s \\Device\\Ramdisk 0 255 & erase disk twice using bytes 0 then 255\n" 251 | " %s --dod \\Device\\Ramdisk & erase disk using DoD 5220.22-M method\n" 252 | " %s \\Device\\Ramdisk 0 0xff r & same as --dod (bytes 0, 255, weak random)\n" 253 | " %s -p 2 \\Device\\Ramdisk 0 1 & erase disk 4 times using bytes 0/1/0/1\n" 254 | " %s -p 2 --dod \\Device\\Ramdisk & erase disk twice using DoD method\n" 255 | " %s -1 \\Device\\Ramdisk r r & erase disk twice using weak RNG\n" 256 | " %s -2 \\Device\\Ramdisk r r r r & erase disk four times using strong RNG\n", 257 | progname, 258 | progname, 259 | progname, 260 | progname, 261 | progname, 262 | progname, 263 | progname, 264 | progname, 265 | progname, 266 | progname); 267 | } 268 | 269 | void usage(int exit_code) { 270 | _usage(); 271 | exit(exit_code); 272 | } 273 | 274 | typedef enum { 275 | WIPEMODE_NORMAL, 276 | WIPEMODE_DOD, 277 | WIPEMODE_DOD7, 278 | WIPEMODE_GUTMANN, 279 | WIPEMODE_DOE, 280 | WIPEMODE_SCHNEIER, 281 | WIPEMODE_BCI 282 | } WipeMode; 283 | 284 | char *wipe_methods[] = { 285 | "standard wiping method (1 pass per iteration)", 286 | "US DoD 5220.22-M wiping method (3 passes per iteration)", 287 | "US DoD 5200.28-STD wiping method (7 passes per iteration)", 288 | "Peter Gutmann's wiping method (35 passes per iteration)", 289 | "US DoE wiping method (3 passes per iteration)", 290 | "Bruce Schneier's wiping method (7 passes per iteration)", 291 | "German BCI/VSITR wiping method (7 passes per iteration)" 292 | }; 293 | 294 | typedef enum { 295 | RANDOM_NONE, 296 | RANDOM_PSEUDO, 297 | RANDOM_WINDOWS, 298 | #ifdef HAVE_CRYPTOGRAPHIC 299 | RANDOM_CRYPTOGRAPHIC 300 | #endif 301 | } RandomMode; 302 | 303 | struct _opt { 304 | bool list; 305 | unsigned int passes; 306 | WipeMode mode; 307 | bool yes; 308 | RandomMode random; 309 | ExitMode restart; 310 | bool force; 311 | unsigned int quiet; 312 | unsigned int sectors; 313 | ULONGLONG start; 314 | ULONGLONG end; 315 | bool read; 316 | unsigned int help; 317 | bool kilobyte; 318 | unsigned int refresh; 319 | bool ignore; 320 | }; 321 | 322 | typedef struct _opt t_opt; 323 | 324 | static t_opt opt = { 325 | false, /* list */ 326 | 0, /* passes */ 327 | WIPEMODE_NORMAL, /* normal, dod, dod7, gutmann */ 328 | false, /* yes */ 329 | RANDOM_NONE, /* pseudo, windows, cryptographic */ 330 | EXIT_NONE, /* none, poweroff, shutdown, hibernate, logoff, reboot, standby */ 331 | false, /* force */ 332 | 0, /* quiet */ 333 | SECTORS_PER_READ, /* sectors */ 334 | 0ui64, /* start */ 335 | 0ui64, /* end */ 336 | false, /* read */ 337 | 0, /* help */ 338 | false, /* kilobyte */ 339 | 1, /* refresh */ 340 | false, /* ignore */ 341 | }; 342 | 343 | /* per http://www.scit.wlv.ac.uk/cgi-bin/mansec?3C+basename */ 344 | static char* basename(char* s) { 345 | char* rv; 346 | 347 | if (!s || !*s) 348 | return "."; 349 | 350 | rv = s + strlen(s) - 1; 351 | 352 | do { 353 | if (*rv == '/' || *rv == '\\') 354 | return rv + 1; 355 | --rv; 356 | } while (rv >= s); 357 | 358 | return s; 359 | } 360 | 361 | static void Warning(char *str) { 362 | LPVOID lpMsgBuf; 363 | DWORD err = GetLastError(); 364 | FormatMessage( 365 | FORMAT_MESSAGE_ALLOCATE_BUFFER | 366 | FORMAT_MESSAGE_FROM_SYSTEM | 367 | FORMAT_MESSAGE_IGNORE_INSERTS, 368 | NULL, 369 | err, 370 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 371 | (LPTSTR) &lpMsgBuf, 372 | 0, 373 | NULL); 374 | fprintf(stderr, "\n%s: %s (0x%x)\n", str, (char *) lpMsgBuf, err); 375 | } 376 | 377 | static void Error(char *str) { 378 | DWORD err = GetLastError(); 379 | Warning(str); 380 | if (opt.ignore) { 381 | return; 382 | } 383 | exit(err ? err : 1); 384 | } 385 | 386 | static void FatalError(char *str) { 387 | DWORD err = GetLastError(); 388 | Warning(str); 389 | exit(err ? err : 1); 390 | } 391 | 392 | static BOOL add_seconds(SYSTEMTIME *st, DWORD seconds, SYSTEMTIME *rv) { 393 | FILETIME ft; 394 | SystemTimeToFileTime(st, &ft); 395 | 396 | ULARGE_INTEGER uli; 397 | uli.HighPart = ft.dwHighDateTime; 398 | uli.LowPart = ft.dwLowDateTime; 399 | uli.QuadPart += (seconds * 10000000ui64); 400 | 401 | ft.dwHighDateTime = uli.HighPart; 402 | ft.dwLowDateTime = uli.LowPart; 403 | 404 | return (BOOL) FileTimeToSystemTime(&ft, rv); 405 | }; 406 | 407 | static char *systemtime_to_hhmmss(SYSTEMTIME *st, char *rv, int bufsiz) { 408 | _snprintf(rv, bufsiz, "%02d:%02d:%02d", st->wHour, st->wMinute, st->wSecond); 409 | 410 | return rv; 411 | } 412 | 413 | static char *seconds_to_hhmmss(DWORD seconds, char *rv, int bufsiz) { 414 | DWORD hours = seconds / 3600; 415 | seconds -= hours * 3600; 416 | 417 | DWORD minutes = seconds / 60; 418 | seconds -= minutes * 60; 419 | 420 | if (hours > 99) { 421 | DWORD days = hours / 24; 422 | hours -= days * 24; 423 | if (days > 99) { 424 | _snprintf(rv, bufsiz, "%03dd %02dh", days, hours); 425 | return rv; 426 | } 427 | _snprintf(rv, bufsiz, "%02dd%02d%02d", days, hours, minutes); 428 | return rv; 429 | } 430 | 431 | _snprintf(rv, bufsiz, "%02d:%02d:%02d", hours, minutes, seconds); 432 | 433 | return rv; 434 | } 435 | 436 | struct _stats { 437 | char *device_name; 438 | DWORD bytes_per_sector; 439 | ULONGLONG tick_frequency; /* ticks to seconds divisor */ 440 | 441 | ULONGLONG start_ticks; 442 | SYSTEMTIME lpStartTime; 443 | char start_time[20]; 444 | ULONGLONG wiping_ticks; 445 | 446 | ULONGLONG all_start_ticks; 447 | ULONGLONG all_wiping_ticks; 448 | }; 449 | 450 | typedef struct _stats t_stats; 451 | 452 | static ULONGLONG get_ticks(t_stats *stats) { 453 | typedef enum {STATE_UNINITIALIZED, STATE_USE_FREQUENCY, STATE_USE_TICKCOUNT} t_state; 454 | static t_state state = STATE_UNINITIALIZED; 455 | 456 | static DWORD last_ticks; 457 | static ULONGLONG overflow_ticks = 0; 458 | 459 | if (state == STATE_UNINITIALIZED) { 460 | LARGE_INTEGER frequency; 461 | QueryPerformanceFrequency(&frequency); 462 | if (frequency.QuadPart >= 1000) { 463 | state = STATE_USE_FREQUENCY; 464 | stats->tick_frequency = frequency.QuadPart; 465 | } else { 466 | state = STATE_USE_TICKCOUNT; 467 | stats->tick_frequency = 1000; 468 | last_ticks = GetTickCount(); 469 | } 470 | } 471 | 472 | if (state == STATE_USE_FREQUENCY) { 473 | LARGE_INTEGER now; 474 | QueryPerformanceCounter(&now); 475 | return now.QuadPart; 476 | } 477 | 478 | DWORD ticks = GetTickCount(); 479 | if (ticks < last_ticks) { 480 | overflow_ticks += 0x100000000; 481 | } 482 | 483 | return overflow_ticks + (ULONGLONG) ticks; 484 | } 485 | 486 | static void print_stats(unsigned int pass, char *s_byte, ULONGLONG sector, t_stats *stats) { 487 | ULONGLONG starting_sector = opt.start; 488 | ULONGLONG ending_sector = opt.end; 489 | 490 | ULONGLONG done_sectors = (ending_sector * ((ULONGLONG) pass - 1)) + sector; 491 | ULONGLONG total_sectors = ending_sector * opt.passes; 492 | 493 | double all_pct = (double) (LONGLONG) done_sectors / (double) (LONGLONG) total_sectors * 100.0; 494 | 495 | ULONGLONG remaining_ticks = 0; 496 | 497 | ULONGLONG elapsed_ticks = get_ticks(stats) - stats->start_ticks; 498 | 499 | if (done_sectors) { 500 | remaining_ticks = (total_sectors - done_sectors) * elapsed_ticks / done_sectors; 501 | } 502 | 503 | static double kilo = opt.kilobyte ? 1024 : 1000; 504 | 505 | double mb_sec = 0; 506 | 507 | if (stats->wiping_ticks) { 508 | ULONGLONG bytes = done_sectors * stats->bytes_per_sector; 509 | double megabytes = (double) (LONGLONG) bytes / (kilo * kilo); 510 | double seconds = (double) (LONGLONG) stats->wiping_ticks / (double) (LONGLONG) stats->tick_frequency; 511 | //printf("\nsector=%20I64d done_sectors=%20I64d bytes=%20I64d megabytes=%20.10f seconds=%20.10f\n", sector, done_sectors, bytes, megabytes, seconds); 512 | if (seconds > 0) { 513 | mb_sec = megabytes / seconds; 514 | } 515 | } 516 | 517 | sector -= starting_sector; 518 | ending_sector -= starting_sector; 519 | 520 | double this_pct = (double) (LONGLONG) sector / (double) (LONGLONG) ending_sector * 100.0; 521 | 522 | if (sector >= ending_sector) { 523 | this_pct = 100.0; 524 | all_pct = (double) (pass) * 100.0 / (double) opt.passes; 525 | if (pass >= opt.passes) { 526 | this_pct = 100.0; 527 | all_pct = 100.0; 528 | remaining_ticks = 0; 529 | } 530 | } 531 | 532 | DWORD remaining_seconds = (DWORD) (remaining_ticks / stats->tick_frequency); 533 | 534 | char remaining_time[255]; 535 | seconds_to_hhmmss(remaining_seconds, remaining_time, sizeof(remaining_time)); 536 | 537 | DWORD elapsed_seconds = (DWORD) (elapsed_ticks / stats->tick_frequency); 538 | 539 | char elapsed_time[255]; 540 | seconds_to_hhmmss(elapsed_seconds, elapsed_time, sizeof(elapsed_time)); 541 | 542 | SYSTEMTIME lpEndTime; 543 | add_seconds(&stats->lpStartTime, elapsed_seconds + remaining_seconds, &lpEndTime); 544 | 545 | char finish_time[255]; 546 | systemtime_to_hhmmss(&lpEndTime, finish_time, sizeof(finish_time)); 547 | 548 | char buf[255]; 549 | _snprintf(buf, sizeof(buf), "%.3f%% - %s - %s - %s", all_pct, remaining_time, stats->device_name, progname); 550 | SetConsoleTitle(buf); 551 | 552 | if (opt.quiet == 1) { 553 | _snprintf(buf, sizeof(buf), "%s - %.3f%% complete - %s remaining\r", stats->device_name, all_pct, remaining_time); 554 | printf("%s\r", buf); 555 | fflush(stdout); 556 | return; 557 | } 558 | 559 | printf(FORMAT_STRING, 560 | pass, 561 | opt.passes, 562 | s_byte, 563 | this_pct, 564 | all_pct, 565 | elapsed_time, 566 | remaining_time, 567 | stats->start_time, 568 | finish_time, 569 | mb_sec); 570 | fflush(stdout); 571 | } 572 | 573 | // 574 | 575 | static int FakeDosNameForDevice (char *lpszDiskFile, char *lpszDosDevice, char *lpszCFDevice, BOOL bNameOnly) { 576 | if (strncmp(lpszDiskFile, "\\\\", 2) == 0) { 577 | strcpy(lpszCFDevice, lpszDiskFile); 578 | return 1; 579 | } 580 | 581 | BOOL bDosLinkCreated = TRUE; 582 | _snprintf(lpszDosDevice, MAX_PATH, "dskwipe%lu", GetCurrentProcessId()); 583 | 584 | if (bNameOnly == FALSE) 585 | bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); 586 | 587 | if (bDosLinkCreated == FALSE) { 588 | return 1; 589 | } else { 590 | _snprintf(lpszCFDevice, MAX_PATH, "\\\\.\\%s", lpszDosDevice); 591 | } 592 | 593 | return 0; 594 | } 595 | 596 | static int RemoveFakeDosName (char *lpszDiskFile, char *lpszDosDevice) { 597 | BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | 598 | DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); 599 | if (bDosLinkRemoved == FALSE) { 600 | return 1; 601 | } 602 | 603 | return 0; 604 | } 605 | 606 | static void GetSizeString (LONGLONG size, wchar_t *str) { 607 | static wchar_t *b, *kb, *mb, *gb, *tb, *pb; 608 | 609 | if (b == NULL) { 610 | if (opt.kilobyte) { 611 | kb = L"KiB"; 612 | mb = L"MiB"; 613 | gb = L"GiB"; 614 | tb = L"TiB"; 615 | pb = L"PiB"; 616 | } else { 617 | kb = L"KB"; 618 | mb = L"MB"; 619 | gb = L"GB"; 620 | tb = L"TB"; 621 | pb = L"PB"; 622 | } 623 | b = L"bytes"; 624 | } 625 | 626 | DWORD kilo = opt.kilobyte ? 1024 : 1000; 627 | LONGLONG kiloI64 = kilo; 628 | double kilod = kilo; 629 | 630 | if (size > kiloI64 * kilo * kilo * kilo * kilo * 99) 631 | swprintf (str, L"%I64d %s", size/ kilo / kilo /kilo/kilo/kilo, pb); 632 | else if (size > kiloI64*kilo*kilo*kilo*kilo) 633 | swprintf (str, L"%.1f %s",(double)(size/kilod/kilo/kilo/kilo/kilo), pb); 634 | else if (size > kiloI64*kilo*kilo*kilo*99) 635 | swprintf (str, L"%I64d %s",size/kilo/kilo/kilo/kilo, tb); 636 | else if (size > kiloI64*kilo*kilo*kilo) 637 | swprintf (str, L"%.1f %s",(double)(size/kilod/kilo/kilo/kilo), tb); 638 | else if (size > kiloI64*kilo*kilo*99) 639 | swprintf (str, L"%I64d %s",size/kilo/kilo/kilo, gb); 640 | else if (size > kiloI64*kilo*kilo) 641 | swprintf (str, L"%.1f %s",(double)(size/kilod/kilo/kilo), gb); 642 | else if (size > kiloI64*kilo*99) 643 | swprintf (str, L"%I64d %s", size/kilo/kilo, mb); 644 | else if (size > kiloI64*kilo) 645 | swprintf (str, L"%.1f %s",(double)(size/kilod/kilo), mb); 646 | else if (size > kiloI64) 647 | swprintf (str, L"%I64d %s", size/kilo, kb); 648 | else 649 | swprintf (str, L"%I64d %s", size, b); 650 | } 651 | 652 | static void list_device(char *format_str, char *szTmp, int n) { 653 | int nDosLinkCreated; 654 | HANDLE dev; 655 | DWORD dwResult; 656 | BOOL bResult; 657 | PARTITION_INFORMATION diskInfo; 658 | DISK_GEOMETRY driveInfo; 659 | char szDosDevice[MAX_PATH], szCFDevice[MAX_PATH]; 660 | static LONGLONG deviceSize = 0; 661 | wchar_t size[100] = {0}, partTypeStr[1024] = {0}, *partType = partTypeStr; 662 | 663 | BOOL drivePresent = FALSE; 664 | BOOL removable = FALSE; 665 | 666 | drivePresent = TRUE; 667 | 668 | nDosLinkCreated = FakeDosNameForDevice (szTmp, szDosDevice, 669 | szCFDevice, FALSE); 670 | 671 | dev = CreateFile (szCFDevice, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE , NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 672 | 673 | bResult = DeviceIoControl (dev, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, 674 | &diskInfo, sizeof (diskInfo), &dwResult, NULL); 675 | 676 | // Test if device is removable 677 | if (/* n == 0 && */ DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, 678 | &driveInfo, sizeof (driveInfo), &dwResult, NULL)) 679 | removable = driveInfo.MediaType == RemovableMedia; 680 | 681 | RemoveFakeDosName(szTmp, szDosDevice); 682 | CloseHandle(dev); 683 | 684 | if (!bResult) 685 | return; 686 | 687 | // System creates a virtual partition1 for some storage devices without 688 | // partition table. We try to detect this case by comparing sizes of 689 | // partition0 and partition1. If they match, no partition of the device 690 | // is displayed to the user to avoid confusion. Drive letter assigned by 691 | // system to partition1 is displayed as subitem of partition0 692 | 693 | if (n == 0) { 694 | deviceSize = diskInfo.PartitionLength.QuadPart; 695 | } 696 | 697 | if (n > 0 && diskInfo.PartitionLength.QuadPart == deviceSize) { 698 | return; 699 | } 700 | 701 | switch(diskInfo.PartitionType) { 702 | case PARTITION_ENTRY_UNUSED: partType = L""; break; 703 | case PARTITION_XINT13_EXTENDED: 704 | case PARTITION_EXTENDED: partType = L"Extended"; break; 705 | case PARTITION_HUGE: wsprintfW (partTypeStr, L"%s (0x%02X)", L"Unformatted", diskInfo.PartitionType); partType = partTypeStr; break; 706 | case PARTITION_FAT_12: partType = L"FAT12"; break; 707 | case PARTITION_FAT_16: partType = L"FAT16"; break; 708 | case PARTITION_FAT32: 709 | case PARTITION_FAT32_XINT13: partType = L"FAT32"; break; 710 | case 0x08: partType = L"DELL (spanning)"; break; 711 | case 0x12: partType = L"Config/diagnostics"; break; 712 | case 0x11: 713 | case 0x14: 714 | case 0x16: 715 | case 0x1b: 716 | case 0x1c: 717 | case 0x1e: partType = L"Hidden FAT"; break; 718 | case PARTITION_IFS: partType = L"NTFS"; break; 719 | case 0x17: partType = L"Hidden NTFS"; break; 720 | case 0x3c: partType = L"PMagic recovery"; break; 721 | case 0x3d: partType = L"Hidden NetWare"; break; 722 | case 0x41: partType = L"Linux/MINIX"; break; 723 | case 0x42: partType = L"SFS/LDM/Linux Swap"; break; 724 | case 0x51: 725 | case 0x64: 726 | case 0x65: 727 | case 0x66: 728 | case 0x67: 729 | case 0x68: 730 | case 0x69: partType = L"Novell"; break; 731 | case 0x55: partType = L"EZ-Drive"; break; 732 | case PARTITION_OS2BOOTMGR: partType = L"OS/2 BM"; break; 733 | case PARTITION_XENIX_1: 734 | case PARTITION_XENIX_2: partType = L"Xenix"; break; 735 | case PARTITION_UNIX: partType = L"UNIX"; break; 736 | case 0x74: partType = L"Scramdisk"; break; 737 | case 0x78: partType = L"XOSL FS"; break; 738 | case 0x80: 739 | case 0x81: partType = L"MINIX"; break; 740 | case 0x82: partType = L"Linux Swap"; break; 741 | case 0x43: 742 | case 0x83: partType = L"Linux"; break; 743 | case 0xc2: 744 | case 0x93: partType = L"Hidden Linux"; break; 745 | case 0x86: 746 | case 0x87: partType = L"NTFS volume set"; break; 747 | case 0x9f: partType = L"BSD/OS"; break; 748 | case 0xa0: 749 | case 0xa1: partType = L"Hibernation"; break; 750 | case 0xa5: partType = L"BSD"; break; 751 | case 0xa8: partType = L"Mac OS-X"; break; 752 | case 0xa9: partType = L"NetBSD"; break; 753 | case 0xab: partType = L"Mac OS-X Boot"; break; 754 | case 0xb8: partType = L"BSDI BSD/386 swap"; break; 755 | case 0xc3: partType = L"Hidden Linux swap"; break; 756 | case 0xfb: partType = L"VMware"; break; 757 | case 0xfc: partType = L"VMware swap"; break; 758 | case 0xfd: partType = L"Linux RAID"; break; 759 | case 0xfe: partType = L"WinNT hidden"; break; 760 | default: wsprintfW(partTypeStr, L"0x%02X", diskInfo.PartitionType); partType = partTypeStr; break; 761 | } 762 | 763 | GetSizeString(diskInfo.PartitionLength.QuadPart, size); 764 | char *s_type = removable ? "Removable" : "Fixed"; 765 | printf(format_str, szTmp, size, s_type, partType); 766 | } 767 | 768 | // 769 | 770 | void print_ticks(char *fmt, ULONGLONG ticks, ULONGLONG tick_frequency) { 771 | char wiping_time[255]; 772 | DWORD seconds = (DWORD) (ticks / tick_frequency); 773 | seconds_to_hhmmss(seconds, wiping_time, sizeof(wiping_time)); 774 | printf(fmt, wiping_time); 775 | } 776 | 777 | static void list_devices() { 778 | printf( 779 | "Device Name Size Type Partition Type\n" 780 | "------------------------------ --------- --------- --------------------\n" 781 | // 123456789012345678901234567890 123456789 123456789 12345678901234567890 782 | // \Device\Harddisk30\Partition03 1234.1 GB Removable SFS/LDM/Linux Swap 783 | ); 784 | 785 | 786 | char *format_str = "%-30s %9S %-9s %-20S\n"; 787 | 788 | char szTmp[MAX_PATH]; 789 | int i; 790 | 791 | for (i = 0; i < 64; i++) { 792 | _snprintf(szTmp, sizeof(szTmp), "\\\\.\\PhysicalDrive%d", i); 793 | list_device(format_str, szTmp, 0); 794 | } 795 | 796 | for (i = 0; i < 64; i++) { 797 | for (int n = 0; n <= 32; n++) { 798 | _snprintf(szTmp, sizeof(szTmp), "\\Device\\Harddisk%d\\Partition%d", i, n); 799 | list_device(format_str, szTmp, n); 800 | } 801 | } 802 | 803 | for (i = 0; i < 8; i++) { 804 | _snprintf(szTmp, sizeof(szTmp), "\\Device\\Floppy%d", i); 805 | list_device(format_str, szTmp, 0); 806 | } 807 | 808 | list_device(format_str, "\\Device\\Ramdisk", 0); 809 | 810 | for (i = 0; i < 26; i++) { 811 | _snprintf(szTmp, sizeof(szTmp), "\\\\.\\%c:", 'A' + i); 812 | list_device(format_str, szTmp, 0); 813 | } 814 | } 815 | 816 | void print_device_info(char *device_name) { 817 | char szCFDevice[MAX_PATH]; 818 | char szDosDevice[MAX_PATH]; 819 | int nDosLinkCreated = FakeDosNameForDevice(device_name, szDosDevice, szCFDevice, FALSE); 820 | char err[256]; 821 | 822 | printf("Device: %s\n", device_name); 823 | SetErrorMode(SEM_NOOPENFILEERRORBOX); 824 | 825 | HANDLE hnd = CreateFile( 826 | szCFDevice, 827 | GENERIC_READ, 828 | 0, 829 | NULL, 830 | OPEN_EXISTING, 831 | 0, 832 | NULL); 833 | 834 | if (hnd == INVALID_HANDLE_VALUE) { 835 | _snprintf(err, sizeof(err), "Cannot open '%s'", device_name); 836 | FatalError(err); 837 | } 838 | 839 | DISK_GEOMETRY driveInfo; 840 | //PARTITION_INFORMATION diskInfo; 841 | DWORD dwResult; 842 | BOOL bResult; 843 | 844 | dwResult = 0; 845 | 846 | bResult = DeviceIoControl( 847 | hnd, 848 | IOCTL_DISK_GET_DRIVE_GEOMETRY, 849 | NULL, 850 | 0, 851 | &driveInfo, 852 | sizeof(driveInfo), 853 | &dwResult, 854 | NULL); 855 | 856 | if (!bResult) { 857 | _snprintf(err, sizeof(err), "Cannot query '%s'", device_name); 858 | FatalError(err); 859 | } 860 | 861 | CloseHandle(hnd); 862 | 863 | ULONGLONG last_sector = driveInfo.Cylinders.QuadPart * driveInfo.TracksPerCylinder * driveInfo.SectorsPerTrack; 864 | ULONGLONG total_sectors = last_sector + 1; 865 | ULONGLONG total_bytes = total_sectors * driveInfo.BytesPerSector; 866 | 867 | wchar_t size[512]; 868 | GetSizeString(total_bytes, size); 869 | 870 | printf("Cylinders: %I64d\n", driveInfo.Cylinders.QuadPart); 871 | printf("Tracks/cylinder: %d\n", driveInfo.TracksPerCylinder); 872 | printf("Sectors/track: %d\n", driveInfo.SectorsPerTrack); 873 | printf("Bytes/sector: %d\n", driveInfo.BytesPerSector); 874 | printf("Total Sectors: %I64d\n", total_sectors); 875 | printf("Total Bytes: %I64d\n", total_bytes); 876 | printf("Size: %S\n", size); 877 | } 878 | 879 | int wipe_device(char *device_name, int bytes, int *byte, t_stats *stats, HCRYPTPROV hProv) { 880 | stats->start_ticks = get_ticks(stats); 881 | stats->wiping_ticks = 0; 882 | stats->start_ticks = get_ticks(stats); 883 | 884 | stats->device_name = device_name; 885 | 886 | char err[256]; 887 | 888 | char szCFDevice[MAX_PATH]; 889 | char szDosDevice[MAX_PATH]; 890 | int nDosLinkCreated = FakeDosNameForDevice(device_name, szDosDevice, szCFDevice, FALSE); 891 | 892 | switch (opt.quiet) { 893 | case 0: 894 | printf("Device: %s\n", device_name); 895 | break; 896 | case 1: 897 | printf("%s\r", device_name); 898 | break; 899 | } 900 | 901 | SetErrorMode(SEM_NOOPENFILEERRORBOX); 902 | 903 | HANDLE hnd = CreateFile( 904 | szCFDevice, 905 | GENERIC_READ | GENERIC_WRITE, 906 | FILE_SHARE_READ | FILE_SHARE_WRITE, 907 | NULL, 908 | OPEN_EXISTING, 909 | 0, 910 | NULL); 911 | 912 | if (hnd == INVALID_HANDLE_VALUE) { 913 | _snprintf(err, sizeof(err), "Cannot open '%s'", device_name); 914 | FatalError(err); 915 | } 916 | 917 | ULONGLONG last_sector = 0; 918 | 919 | DISK_GEOMETRY driveInfo; 920 | PARTITION_INFORMATION diskInfo; 921 | DWORD dwResult; 922 | BOOL bResult; 923 | 924 | dwResult = 0; 925 | 926 | bResult = DeviceIoControl( 927 | hnd, // handle to a volume 928 | FSCTL_LOCK_VOLUME, // dwIoControlCode 929 | NULL, // lpInBuffer 930 | 0, // nInBufferSize 931 | NULL, // lpOutBuffer 932 | 0, // nOutBufferSize 933 | &dwResult, // number of bytes returned 934 | NULL 935 | ); 936 | 937 | if (!bResult) { 938 | _snprintf(err, sizeof(err), "Cannot lock volume '%s'", device_name); 939 | FatalError(err); 940 | } 941 | 942 | dwResult = 0; 943 | 944 | bResult = DeviceIoControl( 945 | hnd, 946 | IOCTL_DISK_GET_DRIVE_GEOMETRY, 947 | NULL, 948 | 0, 949 | &driveInfo, 950 | sizeof(driveInfo), 951 | &dwResult, 952 | NULL); 953 | 954 | if (!bResult) { 955 | _snprintf(err, sizeof(err), "Cannot query '%s'", device_name); 956 | FatalError(err); 957 | } 958 | 959 | last_sector = driveInfo.Cylinders.QuadPart * driveInfo.TracksPerCylinder * driveInfo.SectorsPerTrack; 960 | 961 | stats->bytes_per_sector = driveInfo.BytesPerSector; 962 | 963 | if (opt.quiet == 0) { 964 | ULONGLONG total_sectors = last_sector + 1; 965 | ULONGLONG total_bytes = total_sectors * stats->bytes_per_sector; 966 | 967 | wchar_t size[512]; 968 | GetSizeString(total_bytes, size); 969 | 970 | printf("Cylinders: %I64d\n", driveInfo.Cylinders.QuadPart); 971 | printf("Tracks/cylinder: %d\n", driveInfo.TracksPerCylinder); 972 | printf("Sectors/track: %d\n", driveInfo.SectorsPerTrack); 973 | printf("Bytes/sector: %d\n", driveInfo.BytesPerSector); 974 | printf("Total Sectors: %I64d\n", total_sectors); 975 | printf("Total Bytes: %I64d\n", total_bytes); 976 | printf("Size: %S\n", size); 977 | } 978 | 979 | bResult = DeviceIoControl( 980 | hnd, 981 | IOCTL_DISK_GET_PARTITION_INFO, 982 | NULL, 983 | 0, 984 | &diskInfo, 985 | sizeof(diskInfo), 986 | &dwResult, 987 | NULL); 988 | 989 | if (bResult) { 990 | last_sector = diskInfo.PartitionLength.QuadPart / stats->bytes_per_sector; 991 | } 992 | 993 | if (opt.end > last_sector) { 994 | _snprintf(err, sizeof(err), "Ending sector must be less than or equal to %I64d for %s", last_sector, device_name); 995 | FatalError(err); 996 | } 997 | 998 | if (opt.end == 0) { 999 | opt.end = last_sector; 1000 | } 1001 | 1002 | if (opt.start > opt.end) { 1003 | _snprintf(err, sizeof(err), "Ending sector must be greater than starting sector"); 1004 | FatalError(err); 1005 | } 1006 | 1007 | if (opt.quiet < 2) { 1008 | if (opt.start != 0 || opt.end != last_sector) { 1009 | if (opt.quiet == 1) { 1010 | printf("\n"); 1011 | } 1012 | ULONGLONG bytes = (opt.end - opt.start) * stats->bytes_per_sector; 1013 | wchar_t size[512]; 1014 | GetSizeString(bytes, size); 1015 | printf("Processing sectors %I64d to %I64d (%I64d bytes) (%S)\n", opt.start, opt.end, bytes, size); 1016 | } 1017 | } 1018 | 1019 | if (opt.quiet < 1) { 1020 | printf("\n"); 1021 | } 1022 | 1023 | unsigned int bytes_to_process = opt.sectors * stats->bytes_per_sector; 1024 | 1025 | unsigned char *sector_data = (unsigned char *) malloc(bytes_to_process + BYTES_PER_ELEMENT); 1026 | 1027 | if (opt.quiet == 0) { 1028 | printf(HEADER, opt.kilobyte ? " MiB" : "MB"); 1029 | } 1030 | 1031 | for (unsigned int pass = 1; pass <= opt.passes; ++pass) { 1032 | int byte_to_write = 0; 1033 | 1034 | GetLocalTime(&stats->lpStartTime); 1035 | systemtime_to_hhmmss(&stats->lpStartTime, stats->start_time, sizeof(stats->start_time)); 1036 | 1037 | unsigned char chars[3]; 1038 | 1039 | unsigned int n; 1040 | int j; 1041 | 1042 | RandomMode random = (bytes == 0) ? opt.random : RANDOM_NONE; 1043 | 1044 | switch (opt.mode) { 1045 | case WIPEMODE_NORMAL: 1046 | if (bytes == 0) { 1047 | byte_to_write = 0; 1048 | } else { 1049 | int n = (pass - 1) % bytes; 1050 | byte_to_write = byte[n]; 1051 | if (byte_to_write < 0) { 1052 | if (random == RANDOM_NONE) { 1053 | random = opt.random ? opt.random : RANDOM_PSEUDO; 1054 | } 1055 | } 1056 | } 1057 | 1058 | for (j = 0; j < BYTES_PER_ELEMENT; ++j) { 1059 | chars[j] = (unsigned char) byte_to_write; 1060 | } 1061 | break; 1062 | 1063 | case WIPEMODE_DOD: 1064 | n = (pass - 1) % dod_elements; 1065 | byte_to_write = dod_bytes[n]; 1066 | if (byte_to_write < 0) { 1067 | if (random == RANDOM_NONE) { 1068 | random = opt.random ? opt.random : RANDOM_PSEUDO; 1069 | } 1070 | } else { 1071 | random = RANDOM_NONE; 1072 | } 1073 | for (j = 0; j < BYTES_PER_ELEMENT; ++j) { 1074 | chars[j] = (unsigned char) byte_to_write; 1075 | } 1076 | break; 1077 | 1078 | case WIPEMODE_DOD7: 1079 | n = (pass - 1) % dod7_elements; 1080 | byte_to_write = dod7_bytes[n]; 1081 | if (byte_to_write < 0) { 1082 | if (random == RANDOM_NONE) { 1083 | random = opt.random ? opt.random : RANDOM_PSEUDO; 1084 | } 1085 | } else { 1086 | random = RANDOM_NONE; 1087 | } 1088 | for (j = 0; j < BYTES_PER_ELEMENT; ++j) { 1089 | chars[j] = (unsigned char) byte_to_write; 1090 | } 1091 | break; 1092 | 1093 | case WIPEMODE_GUTMANN: 1094 | n = (pass - 1) % gutmann_elements; 1095 | byte_to_write = gutmann_bytes[n][0]; 1096 | if (byte_to_write < 0) { 1097 | if (random == RANDOM_NONE) { 1098 | random = opt.random ? opt.random : RANDOM_PSEUDO; 1099 | } 1100 | } else { 1101 | random = RANDOM_NONE; 1102 | } 1103 | for (j = 0; j < BYTES_PER_ELEMENT; ++j) { 1104 | chars[j] = (unsigned char) gutmann_bytes[n][j]; 1105 | } 1106 | break; 1107 | 1108 | case WIPEMODE_DOE: 1109 | n = (pass - 1) % doe_elements; 1110 | byte_to_write = doe_bytes[n]; 1111 | if (byte_to_write < 0) { 1112 | if (random == RANDOM_NONE) { 1113 | random = opt.random ? opt.random : RANDOM_PSEUDO; 1114 | } 1115 | } else { 1116 | random = RANDOM_NONE; 1117 | } 1118 | for (j = 0; j < BYTES_PER_ELEMENT; ++j) { 1119 | chars[j] = (unsigned char) byte_to_write; 1120 | } 1121 | break; 1122 | 1123 | case WIPEMODE_SCHNEIER: 1124 | n = (pass - 1) % schneier_elements; 1125 | byte_to_write = schneier_bytes[n]; 1126 | if (byte_to_write < 0) { 1127 | if (random == RANDOM_NONE) { 1128 | random = opt.random ? opt.random : RANDOM_PSEUDO; 1129 | } 1130 | } else { 1131 | random = RANDOM_NONE; 1132 | } 1133 | for (j = 0; j < BYTES_PER_ELEMENT; ++j) { 1134 | chars[j] = (unsigned char) byte_to_write; 1135 | } 1136 | break; 1137 | 1138 | case WIPEMODE_BCI: 1139 | n = (pass - 1) % bci_elements; 1140 | byte_to_write = bci_bytes[n]; 1141 | if (byte_to_write < 0) { 1142 | if (random == RANDOM_NONE) { 1143 | random = opt.random ? opt.random : RANDOM_PSEUDO; 1144 | } 1145 | } else { 1146 | random = RANDOM_NONE; 1147 | } 1148 | for (j = 0; j < BYTES_PER_ELEMENT; ++j) { 1149 | chars[j] = (unsigned char) byte_to_write; 1150 | } 1151 | break; 1152 | 1153 | } 1154 | 1155 | char s_byte[5]; 1156 | 1157 | switch (random) { 1158 | case RANDOM_PSEUDO: 1159 | sprintf(s_byte, "prnd"); 1160 | break; 1161 | case RANDOM_WINDOWS: 1162 | sprintf(s_byte, "wrnd"); 1163 | break; 1164 | #ifdef HAVE_CRYPTOGRAPHIC 1165 | case RANDOM_CRYPTOGRAPHIC: 1166 | sprintf(s_byte, "crnd"); 1167 | break; 1168 | #endif 1169 | default: 1170 | sprintf(s_byte, "0x%02x", byte_to_write); 1171 | for (unsigned int i = 0; i <= stats->bytes_per_sector * opt.sectors - BYTES_PER_ELEMENT; i += BYTES_PER_ELEMENT) { 1172 | for (int j = 0; j < BYTES_PER_ELEMENT; ++j) { 1173 | sector_data[i + j] = chars[j]; 1174 | } 1175 | } 1176 | } 1177 | 1178 | ULONGLONG starting_byte = opt.start * stats->bytes_per_sector; 1179 | 1180 | LARGE_INTEGER li; 1181 | 1182 | li.QuadPart = starting_byte; 1183 | 1184 | SetLastError(0); 1185 | DWORD dw = SetFilePointer(hnd, li.LowPart, &li.HighPart, FILE_BEGIN); 1186 | 1187 | if (GetLastError() != NO_ERROR) { 1188 | _snprintf(err, sizeof(err), "Failed to seek to sector %I64d", opt.start); 1189 | Error(err); 1190 | } 1191 | 1192 | ULONGLONG last_ticks = get_ticks(stats); 1193 | 1194 | #ifdef _DEBUG 1195 | fprintf(stderr, "\n************************************************************"); 1196 | fprintf(stderr, "\n************************************************************"); 1197 | fprintf(stderr, "\n************************************************************"); 1198 | fprintf(stderr, "\n************************************************************"); 1199 | fprintf(stderr, "\n************************************************************"); 1200 | fprintf(stderr, "\n************************************************************\n"); 1201 | fprintf(stderr, "pass =%u\n", pass); 1202 | fprintf(stderr, "starting_byte =%I64u\n", starting_byte); 1203 | fprintf(stderr, "li.QuadPart =%I64u\n", li.QuadPart); 1204 | fprintf(stderr, "li.HighPart =%lu\n", li.HighPart); 1205 | fprintf(stderr, "li.LowPart =%lu\n", li.LowPart); 1206 | fprintf(stderr, "last_ticks =%I64u\n", last_ticks); 1207 | #endif 1208 | 1209 | char *action = opt.read ? "read" : "write"; 1210 | 1211 | unsigned long sectors_to_process = opt.sectors; 1212 | 1213 | for (ULONGLONG sector = opt.start; sector <= opt.end; sector += opt.sectors) { 1214 | if (sector + sectors_to_process > opt.end) { 1215 | sectors_to_process = (unsigned long) (opt.end - sector); 1216 | bytes_to_process = sectors_to_process * stats->bytes_per_sector; 1217 | if (bytes_to_process == 0) { 1218 | break; 1219 | } 1220 | } 1221 | 1222 | #ifdef _DEBUG 1223 | fprintf(stderr, "sector =%I64u\n", sector); 1224 | fprintf(stderr, "sectors_to_process =%lu\n", sectors_to_process); 1225 | #endif 1226 | 1227 | if (!opt.read) { 1228 | unsigned int i; 1229 | 1230 | switch (random) { 1231 | case RANDOM_PSEUDO: 1232 | for (i = 0; i < bytes_to_process; ++i) { 1233 | sector_data[i] = (unsigned char) rand(); 1234 | } 1235 | break; 1236 | 1237 | case RANDOM_WINDOWS: 1238 | if (!CryptGenRandom(hProv, bytes_to_process, sector_data)) { 1239 | _snprintf(err, sizeof(err), "CryptGenRandom error"); 1240 | FatalError(err); 1241 | } 1242 | break; 1243 | 1244 | #ifdef HAVE_CRYPTOGRAPHIC 1245 | case RANDOM_CRYPTOGRAPHIC: 1246 | #error "RANDOM_CRYPTOGRAPHIC has not been implemented yet" 1247 | break; 1248 | #endif 1249 | } 1250 | } 1251 | 1252 | DWORD dwBytes = 0; 1253 | 1254 | ULONGLONG before_ticks = get_ticks(stats); 1255 | 1256 | SetLastError(0); 1257 | BOOL rv; 1258 | if (opt.read) { 1259 | rv = ReadFile(hnd, sector_data, bytes_to_process, &dwBytes, NULL); 1260 | } else { 1261 | #ifdef DUMMY_WRITE 1262 | rv = true; 1263 | dwBytes = bytes_to_process; 1264 | #else 1265 | rv = WriteFile(hnd, sector_data, bytes_to_process, &dwBytes, NULL); 1266 | #endif 1267 | } 1268 | 1269 | ULONGLONG after_ticks = get_ticks(stats); 1270 | stats->wiping_ticks += after_ticks - before_ticks; 1271 | 1272 | if (!rv || GetLastError()) { 1273 | _snprintf(err, sizeof(err), "Failed to %s %d bytes at sectors %I64d-%I64d", action, bytes_to_process - dwBytes, sector, sector + sectors_to_process); 1274 | Error(err); 1275 | } 1276 | 1277 | if (opt.quiet < 2) { 1278 | ULONGLONG seconds = (after_ticks - last_ticks) / stats->tick_frequency; 1279 | 1280 | if (seconds >= opt.refresh) { 1281 | last_ticks = after_ticks; 1282 | print_stats(pass, s_byte, sector, stats); 1283 | } 1284 | } 1285 | } 1286 | 1287 | if (opt.quiet == 0) { 1288 | print_stats(pass, s_byte, opt.end, stats); 1289 | } 1290 | 1291 | if (opt.quiet < 2) { 1292 | printf("\n"); 1293 | fflush(stdout); 1294 | } 1295 | } 1296 | 1297 | stats->all_wiping_ticks += stats->wiping_ticks; 1298 | 1299 | if (opt.quiet < 2) { 1300 | printf("\n"); 1301 | print_ticks("Wiping time: %s\n", stats->wiping_ticks, stats->tick_frequency); 1302 | 1303 | ULONGLONG elapsed_ticks = get_ticks(stats) - stats->start_ticks; 1304 | print_ticks("Elapsed time: %s\n", elapsed_ticks, stats->tick_frequency); 1305 | printf("\n"); 1306 | 1307 | // printf("\n\nThe operation completed successfully!\n"); 1308 | } 1309 | 1310 | free(sector_data); 1311 | 1312 | CloseHandle(hnd); 1313 | 1314 | if (nDosLinkCreated == 0) { 1315 | RemoveFakeDosName(device_name, szDosDevice); 1316 | } 1317 | 1318 | return 0; 1319 | } 1320 | 1321 | int main(int argc, char * argv[]) { 1322 | int i; 1323 | 1324 | time_t t; 1325 | time(&t); 1326 | 1327 | srand((unsigned int) t ^ _getpid()); 1328 | 1329 | progname = basename(argv[0]); 1330 | 1331 | if (progname) { 1332 | int len = strlen(progname); 1333 | if (len > 4 && _stricmp(progname + len - 4, ".exe") == 0) 1334 | progname[len - 4] = '\0'; 1335 | } 1336 | 1337 | opterr = 0; 1338 | int option_index = 0; 1339 | optind = 1; 1340 | 1341 | while (true) { 1342 | int i; 1343 | if (optind < argc && argv[optind] && argv[optind][0] == '/') 1344 | argv[optind][0] = '-'; 1345 | 1346 | int c = getopt_long(argc, argv, short_options, long_options, &option_index); 1347 | 1348 | if (c == -1) 1349 | break; 1350 | 1351 | switch (c) { 1352 | case 'l': 1353 | opt.list = true; 1354 | break; 1355 | case 'p': /* -p | --passes n Wipe device n times (default is 1) */ 1356 | opt.passes = atoi(optarg); 1357 | if (opt.passes == 0 || opt.passes >= 10000) 1358 | usage(1); 1359 | break; 1360 | case 'd': /* -d | --dod Wipe device using DoD 5220.22-M method (3 passes) */ 1361 | opt.mode = WIPEMODE_DOD; 1362 | break; 1363 | case 'D': /* -D | --dod7 Wipe device using DoD 5200.28-STD method (7 passes) */ 1364 | opt.mode = WIPEMODE_DOD7; 1365 | break; 1366 | case 'g': /* -g | --gutmann Wipe device using Gutmann method (35 passes) */ 1367 | opt.mode = WIPEMODE_GUTMANN; 1368 | break; 1369 | case 'E': /* -E | --doe Wipe device using US DoE method (3 passes) */ 1370 | opt.mode = WIPEMODE_DOE; 1371 | break; 1372 | case 'S': /* -S | --schneier Wipe device using Bruce Schneier's method (7 passes) */ 1373 | opt.mode = WIPEMODE_SCHNEIER; 1374 | break; 1375 | case 'b': /* -b | --bci Wipe device using German BCI/VSITR method (7 passes) */ 1376 | opt.mode = WIPEMODE_BCI; 1377 | break; 1378 | case 'y': 1379 | opt.yes = true; 1380 | break; 1381 | case '1': 1382 | opt.random = RANDOM_PSEUDO; 1383 | break; 1384 | case '2': 1385 | opt.random = RANDOM_WINDOWS; 1386 | break; 1387 | #ifdef HAVE_CRYPTOGRAPHIC 1388 | case '3': 1389 | opt.random = RANDOM_CRYPTOGRAPHIC; 1390 | break; 1391 | #endif 1392 | case 'i': 1393 | opt.ignore = true; 1394 | break; 1395 | case 'k': 1396 | opt.kilobyte = true; 1397 | break; 1398 | case 'z': 1399 | opt.refresh = atoi(optarg); 1400 | break; 1401 | case 'x': 1402 | opt.restart = EXIT_NONE; 1403 | for (i = 0; i < exit_modes; ++i) { 1404 | if (strnicmp(exit_mode[i], optarg, strlen(optarg)) == 0) { 1405 | opt.restart = (ExitMode) i; 1406 | break; 1407 | } 1408 | } 1409 | if (opt.restart == EXIT_NONE) { 1410 | usage(1); 1411 | } 1412 | /* 1413 | case 'P': 1414 | opt.restart = EXIT_POWEROFF; 1415 | break; 1416 | case 'S': 1417 | opt.restart = EXIT_SHUTDOWN; 1418 | break; 1419 | case 'H': 1420 | opt.restart = EXIT_HIBERNATE; 1421 | break; 1422 | case 'L': 1423 | opt.restart = EXIT_LOGOFF; 1424 | break; 1425 | case 'R': 1426 | opt.restart = EXIT_REBOOT; 1427 | break; 1428 | case 'T': 1429 | opt.restart = EXIT_STANDBY; 1430 | break; 1431 | */ 1432 | case 'f': 1433 | opt.force = true; 1434 | break; 1435 | case 'q': /* -q | --quiet Display less information */ 1436 | ++opt.quiet; 1437 | break; 1438 | case 'n': /* -n | --sectors n Write n sectors at once (default is %d) */ 1439 | opt.sectors = atoi(optarg); 1440 | if (opt.sectors == 0) 1441 | usage(1); 1442 | if (opt.sectors >= 65536) 1443 | usage(1); 1444 | break; 1445 | case 's': // -s | --start n Start at sector n (default is first sector) 1446 | opt.start = _atoi64(optarg); 1447 | if (opt.start == (ULONGLONG) -1) 1448 | usage(1); 1449 | break; 1450 | case 'e': // -e | --end n End at sector n (default is last sector) 1451 | opt.end = _atoi64(optarg); 1452 | if (opt.end == 0) 1453 | usage(1); 1454 | break; 1455 | case 'r': /* -r | --read Only read the data on the device (DOES NOT WIPE!) */ 1456 | opt.read = true; 1457 | break; 1458 | case 'v': /* -v | --version Show version and copyright information and quit */ 1459 | version(); 1460 | exit(0); 1461 | break; 1462 | case '?': /* -? | --help Show this help message and quit */ 1463 | ++opt.help; 1464 | break; 1465 | case ':': 1466 | fprintf(stderr, "Option -%c requires an operand\n", optopt); 1467 | // fallthrough 1468 | default: 1469 | usage(1); 1470 | } 1471 | } 1472 | 1473 | if (opt.help) { 1474 | _usage(); 1475 | if (opt.help > 1) { 1476 | examples(); 1477 | } 1478 | exit(0); 1479 | } 1480 | 1481 | if (opt.list) { 1482 | list_devices(); 1483 | exit(0); 1484 | } 1485 | 1486 | int devices = 0; 1487 | int bytes = 0; 1488 | 1489 | for (i = optind; i < argc; ++i) { 1490 | #ifdef _DEBUG 1491 | printf("argv[%d]=%s\n", i, argv[i]); 1492 | #endif 1493 | if (strlen(argv[i]) == 2 && tolower(argv[i][0]) >= 'a' && tolower(argv[i][0]) <= 'z' && argv[i][1] == ':') { 1494 | ++devices; 1495 | continue; 1496 | } 1497 | if (argv[i][0] == '\\') { 1498 | ++devices; 1499 | continue; 1500 | } 1501 | ++bytes; 1502 | } 1503 | 1504 | if (devices == 0) { 1505 | fprintf(stderr, "%s: No devices specified\n", progname); 1506 | usage(1); 1507 | } 1508 | 1509 | char **device = (char **) malloc(sizeof(char *) * devices); 1510 | int *byte = NULL; 1511 | 1512 | if (bytes) { 1513 | byte = (int *) malloc(sizeof(int) * bytes); 1514 | } 1515 | 1516 | devices = 0; 1517 | bytes = 0; 1518 | for (i = optind; i < argc; ++i) { 1519 | device[devices] = (char *) malloc((strlen(argv[i]) + 6) * sizeof(char)); 1520 | 1521 | if (strlen(argv[i]) == 2 && tolower(argv[i][0]) >= 'a' && tolower(argv[i][0]) <= 'z' && argv[i][1] == ':') { 1522 | sprintf(device[devices++], "\\\\.\\%c:", argv[i][0]); 1523 | continue; 1524 | } 1525 | 1526 | if (argv[i][0] == '\\') { 1527 | strcpy(device[devices++], argv[i]); 1528 | continue; 1529 | } 1530 | 1531 | int byte_to_write = 0; 1532 | while (1) { 1533 | if (strnicmp(argv[i], "0x", 2) == 0) { 1534 | if (sscanf(argv[i], "%x", &byte_to_write) == 0) { 1535 | usage(1); 1536 | } 1537 | break; 1538 | } 1539 | 1540 | if (argv[i][0] == '0') { 1541 | if (sscanf(argv[i], "%o", &byte_to_write) == 0) { 1542 | usage(1); 1543 | } 1544 | break; 1545 | } 1546 | 1547 | if (toupper(argv[i][0]) == 'R') { 1548 | byte_to_write = -1; 1549 | break; 1550 | } 1551 | 1552 | byte_to_write = atoi(argv[i]); 1553 | 1554 | if (byte_to_write > 0) { 1555 | byte_to_write &= 0xff; 1556 | } 1557 | break; 1558 | } 1559 | byte[bytes++] = byte_to_write; 1560 | } 1561 | 1562 | if (bytes == 0) { 1563 | bytes = 1; 1564 | byte = (int *) malloc(sizeof(int) * bytes); 1565 | byte[0] = 0; 1566 | } 1567 | 1568 | if (opt.passes == 0) { 1569 | opt.passes = 1; 1570 | } 1571 | 1572 | if (!opt.read && !opt.yes) { 1573 | version(); 1574 | printf( 1575 | // 1 2 3 4 5 6 7 1576 | // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 1577 | "\n" 1578 | "WARNING! You are about to permentently and irretrievably erase all data on the\n" 1579 | "following device(s):\n\n"); 1580 | 1581 | for (int i = 0; i < devices; ++i) { 1582 | print_device_info(device[i]); 1583 | // printf("%2d: %s\n", i + 1, device[i]); 1584 | } 1585 | 1586 | printf("\nUsing %d iteration%s of the %s\n", opt.passes, opt.passes > 1 ? "s" : "", wipe_methods[opt.mode]); 1587 | 1588 | printf( 1589 | "\n" 1590 | "Once this process starts, the device%s will be unrecognizable by the Operating\n" 1591 | "System, and will need to be reinitialized to again be usable.\n" 1592 | "\n" 1593 | "Are you sure you want to wipe %s (yes/no)? ", 1594 | ((devices > 1) ? "s" : ""), 1595 | ((devices > 1) ? "these devices" : "this device") 1596 | ); 1597 | char buf[256]; 1598 | fgets(buf, sizeof(buf), stdin); 1599 | if (strlen(buf) != 4 || strnicmp(buf, "yes", 3) != 0) { 1600 | printf("Processing aborted"); 1601 | exit(0); 1602 | } 1603 | } 1604 | 1605 | switch (opt.mode) { 1606 | case WIPEMODE_NORMAL: 1607 | opt.passes *= bytes; 1608 | break; 1609 | case WIPEMODE_DOD: 1610 | opt.passes *= dod_elements; 1611 | break; 1612 | case WIPEMODE_DOD7: 1613 | opt.passes *= dod7_elements; 1614 | break; 1615 | case WIPEMODE_GUTMANN: 1616 | opt.passes *= gutmann_elements; 1617 | break; 1618 | case WIPEMODE_DOE: 1619 | opt.passes *= doe_elements; 1620 | break; 1621 | case WIPEMODE_SCHNEIER: 1622 | opt.passes *= schneier_elements; 1623 | break; 1624 | case WIPEMODE_BCI: 1625 | opt.passes *= bci_elements; 1626 | break; 1627 | default: 1628 | FatalError("Unimplemented wipe mode"); 1629 | } 1630 | 1631 | if (opt.passes >= 10000) { 1632 | usage(1); 1633 | } 1634 | 1635 | HCRYPTPROV hProv = 0; 1636 | HCRYPTKEY hKey = 0; 1637 | 1638 | LPCSTR KeyContainerName = "MyKeyContainer"; 1639 | 1640 | if (opt.random == RANDOM_WINDOWS) { 1641 | // Get a handle to the user default provider. 1642 | if (!CryptAcquireContext(&hProv, KeyContainerName, NULL, PROV_RSA_FULL, 0)) { 1643 | if (GetLastError() != NTE_BAD_KEYSET) { 1644 | FatalError("CryptAcquireContext error"); 1645 | } 1646 | 1647 | if (!CryptAcquireContext( 1648 | &hProv, 1649 | KeyContainerName, 1650 | NULL, 1651 | PROV_RSA_FULL, 1652 | CRYPT_NEWKEYSET)) { 1653 | FatalError("CryptAcquireContext error"); 1654 | } 1655 | } 1656 | 1657 | // Create a random block cipher session key. 1658 | if (!CryptGenKey(hProv, CALG_RC2, CRYPT_EXPORTABLE, &hKey)) { 1659 | FatalError("CryptGenKey error"); 1660 | } 1661 | 1662 | // Set the cipher mode. 1663 | DWORD dwMode = CRYPT_MODE_ECB; 1664 | if (!CryptSetKeyParam(hKey, KP_MODE, (BYTE *) &dwMode, 0)) { 1665 | FatalError("CryptSetKeyParam error"); 1666 | } 1667 | 1668 | BYTE pbData[16]; 1669 | 1670 | // Generate a random initialization vector. 1671 | if (!CryptGenRandom(hProv, 8, pbData)) { 1672 | FatalError("CryptGenRandom error"); 1673 | } 1674 | 1675 | // Set the initialization vector. 1676 | if (!CryptSetKeyParam(hKey, KP_IV, pbData, 0)) { 1677 | FatalError("CryptSetKeyParam error"); 1678 | } 1679 | } 1680 | 1681 | t_stats stats = { 1682 | 0, 1683 | 0, 1684 | 0, 1685 | 0, 1686 | NULL 1687 | }; 1688 | 1689 | stats.all_start_ticks = get_ticks(&stats); 1690 | 1691 | for (i = 0; i < devices; ++i) { 1692 | wipe_device(device[i], bytes, byte, &stats, hProv); 1693 | } 1694 | 1695 | if (opt.quiet < 2 && devices > 1) { 1696 | print_ticks("Total wiping time: %s\n", stats.all_wiping_ticks, stats.tick_frequency); 1697 | 1698 | ULONGLONG elapsed_ticks = get_ticks(&stats) - stats.all_start_ticks; 1699 | print_ticks("Total elapsed time: %s\n", elapsed_ticks, stats.tick_frequency); 1700 | } 1701 | 1702 | for (i = 0; i < devices; ++i) { 1703 | free(device[i]); 1704 | } 1705 | 1706 | free(device); 1707 | free(byte); 1708 | 1709 | if (opt.random == RANDOM_WINDOWS) { 1710 | CryptDestroyKey(hKey); 1711 | CryptReleaseContext(hProv, 0); 1712 | } 1713 | 1714 | switch (opt.restart) { 1715 | case EXIT_NONE: 1716 | return 0; 1717 | 1718 | case EXIT_HIBERNATE: 1719 | if (SetSystemPowerState(FALSE, opt.force) == 0) { 1720 | FatalError("Unable to hibernate"); 1721 | } 1722 | return 0; 1723 | 1724 | case EXIT_STANDBY: 1725 | if (SetSystemPowerState(TRUE, opt.force) == 0) { 1726 | FatalError("Unable to enter standby"); 1727 | } 1728 | return 0; 1729 | } 1730 | 1731 | HANDLE hToken; 1732 | TOKEN_PRIVILEGES tkp; 1733 | ZeroMemory(&tkp, sizeof(tkp)); 1734 | 1735 | // Get a token for this process. 1736 | if (!OpenProcessToken(GetCurrentProcess(), 1737 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 1738 | FatalError("Unable to get shutdown privileges"); 1739 | } 1740 | 1741 | // Get the LUID for the shutdown privilege. 1742 | LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); 1743 | 1744 | tkp.PrivilegeCount = 1; // one privilege to set 1745 | tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 1746 | 1747 | // Get the shutdown privilege for this process. 1748 | AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); 1749 | 1750 | if (GetLastError() != ERROR_SUCCESS) { 1751 | FatalError("Unable to get shutdown privileges"); 1752 | } 1753 | 1754 | DWORD options = 0; 1755 | char *cmd; 1756 | 1757 | switch (opt.restart) { 1758 | case EXIT_POWEROFF: 1759 | cmd = "poweroff"; 1760 | options |= EWX_SHUTDOWN | EWX_POWEROFF; 1761 | break; 1762 | 1763 | case EXIT_SHUTDOWN: 1764 | cmd = "shutdown"; 1765 | options |= EWX_SHUTDOWN; 1766 | break; 1767 | 1768 | case EXIT_LOGOFF: 1769 | cmd = "logoff"; 1770 | options |= EWX_LOGOFF; 1771 | break; 1772 | 1773 | case EXIT_REBOOT: 1774 | cmd = "reboot"; 1775 | options |= EWX_REBOOT; 1776 | break; 1777 | } 1778 | 1779 | if (opt.force) { 1780 | options |= EWX_FORCE; 1781 | } 1782 | 1783 | if (!ExitWindowsEx(options, 1784 | SHTDN_REASON_MAJOR_OPERATINGSYSTEM | 1785 | SHTDN_REASON_MINOR_OTHER | 1786 | SHTDN_REASON_FLAG_PLANNED)) { 1787 | char err[255]; 1788 | _snprintf(err, sizeof(err), "Unable to %s", cmd); 1789 | FatalError(err); 1790 | } 1791 | 1792 | return 0; 1793 | } 1794 | --------------------------------------------------------------------------------