├── .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 |
--------------------------------------------------------------------------------