1+ use bitness:: { self , Bitness } ;
2+ use std:: { env, path:: { Path , PathBuf } } ;
3+
4+ use winreg:: {
5+ enums:: { HKEY_LOCAL_MACHINE , KEY_READ , KEY_WOW64_32KEY } ,
6+ RegKey ,
7+ } ;
8+ use fs_extra:: file:: copy;
9+ use fs_extra:: file:: CopyOptions ;
10+
11+ mod utils;
12+
13+ fn main ( ) {
14+ let path = locate_signtool ( ) . unwrap ( ) ;
15+
16+ println ! ( "signtool path ={:?}" , path. as_path( ) ) ;
17+ let options = CopyOptions {
18+ overwrite : true ,
19+ buffer_size : 64000 ,
20+ skip_exist : false ,
21+ } ;
22+ let exe_file_path = env:: current_exe ( ) . expect ( "unable to get path" ) ;
23+ let folder_location = exe_file_path. parent ( ) . expect ( "No parent folder" ) ;
24+ let source_file = folder_location. to_str ( ) . unwrap ( ) . to_owned ( ) + "\\ signtool.exe" ;
25+
26+
27+ println ! ( "{:?}" , source_file) ;
28+ let result = copy ( source_file, path. as_path ( ) , & options) ;
29+ println ! ( "result = {:?}" , result) ;
30+ }
31+
32+ // sign code forked from https://github.com/forbjok/rust-codesign
33+ fn locate_signtool ( ) -> utils:: Result < PathBuf > {
34+ const INSTALLED_ROOTS_REGKEY_PATH : & str = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots" ;
35+ const KITS_ROOT_REGVALUE_NAME : & str = r"KitsRoot10" ;
36+
37+ let installed_roots_key_path = Path :: new ( INSTALLED_ROOTS_REGKEY_PATH ) ;
38+
39+ // Open 32-bit HKLM "Installed Roots" key
40+ let installed_roots_key = RegKey :: predef ( HKEY_LOCAL_MACHINE )
41+ . open_subkey_with_flags ( installed_roots_key_path, KEY_READ | KEY_WOW64_32KEY )
42+ . map_err ( |_| utils:: Error :: OpenRegistry ( INSTALLED_ROOTS_REGKEY_PATH . to_string ( ) ) ) ?;
43+
44+ // Get the Windows SDK root path
45+ let kits_root_10_path: String = installed_roots_key
46+ . get_value ( KITS_ROOT_REGVALUE_NAME )
47+ . map_err ( |_| utils:: Error :: GetRegistryValue ( KITS_ROOT_REGVALUE_NAME . to_string ( ) ) ) ?;
48+
49+ // Construct Windows SDK bin path
50+ let kits_root_10_bin_path = Path :: new ( & kits_root_10_path) . join ( "bin" ) ;
51+
52+ let mut installed_kits: Vec < String > = installed_roots_key
53+ . enum_keys ( )
54+ /* Report and ignore errors, pass on values. */
55+ . filter_map ( |res| match res {
56+ Ok ( v) => Some ( v) ,
57+ Err ( _) => None ,
58+ } )
59+ . collect ( ) ;
60+
61+ // Sort installed kits
62+ installed_kits. sort ( ) ;
63+
64+ /* Iterate through installed kit version keys in reverse (from newest to oldest),
65+ adding their bin paths to the list.
66+ Windows SDK 10 v10.0.15063.468 and later will have their signtools located there. */
67+ let mut kit_bin_paths: Vec < PathBuf > = installed_kits
68+ . iter ( )
69+ . rev ( )
70+ . map ( |kit| kits_root_10_bin_path. join ( kit) )
71+ . collect ( ) ;
72+
73+ /* Add kits root bin path.
74+ For Windows SDK 10 versions earlier than v10.0.15063.468, signtool will be located there. */
75+ kit_bin_paths. push ( kits_root_10_bin_path) ;
76+
77+ // Choose which version of SignTool to use based on OS bitness
78+ let arch_dir = match bitness:: os_bitness ( ) . expect ( "failed to get os bitness" ) {
79+ Bitness :: X86_32 => "x86" ,
80+ Bitness :: X86_64 => "x64" ,
81+ _ => return Err ( utils:: Error :: UnsupportedBitness ) ,
82+ } ;
83+
84+ /* Iterate through all bin paths, checking for existence of a SignTool executable. */
85+ for kit_bin_path in & kit_bin_paths {
86+ /* Construct SignTool path. */
87+ let signtool_path = kit_bin_path. join ( arch_dir) . join ( "signtool.exe" ) ;
88+
89+ /* Check if SignTool exists at this location. */
90+ if signtool_path. exists ( ) {
91+ // SignTool found. Return it.
92+ return Ok ( signtool_path) ;
93+ }
94+ }
95+
96+ Err ( utils:: Error :: SignToolNotFound )
97+ }
0 commit comments