33
44use registry:: { Data , Hive , RegKey , Security , key, value} ;
55use utfx:: { U16CString , UCString } ;
6- use crate :: config:: { Registry , RegistryValueData } ;
6+ use crate :: config:: { Metadata , Registry , RegistryValueData } ;
77use crate :: error:: RegistryError ;
88
99pub struct RegistryHelper {
1010 config : Registry ,
1111 hive : Hive ,
1212 subkey : String ,
13+ what_if : bool ,
1314}
1415
1516impl RegistryHelper {
@@ -26,10 +27,15 @@ impl RegistryHelper {
2627 config : registry,
2728 hive,
2829 subkey : subkey. to_string ( ) ,
30+ what_if : false
2931 }
3032 )
3133 }
3234
35+ pub fn enable_what_if ( & mut self ) {
36+ self . what_if = true ;
37+ }
38+
3339 pub fn get ( & self ) -> Result < Registry , RegistryError > {
3440 let exist: bool ;
3541 let ( reg_key, _subkey) = match self . open ( Security :: Read ) {
@@ -40,9 +46,8 @@ impl RegistryHelper {
4046 exist = false ;
4147 return Ok ( Registry {
4248 key_path : self . config . key_path . clone ( ) ,
43- value_name : None ,
44- value_data : None ,
4549 exist : Some ( exist) ,
50+ ..Default :: default ( )
4651 } ) ;
4752 } ,
4853 Err ( e) => return Err ( e) ,
@@ -56,8 +61,8 @@ impl RegistryHelper {
5661 return Ok ( Registry {
5762 key_path : self . config . key_path . clone ( ) ,
5863 value_name : Some ( value_name. clone ( ) ) ,
59- value_data : None ,
6064 exist : Some ( exist) ,
65+ ..Default :: default ( )
6166 } ) ;
6267 } ,
6368 Err ( e) => return Err ( RegistryError :: RegistryValue ( e) ) ,
@@ -67,21 +72,20 @@ impl RegistryHelper {
6772 key_path : self . config . key_path . clone ( ) ,
6873 value_name : Some ( value_name. clone ( ) ) ,
6974 value_data : Some ( convert_reg_value ( & value) ?) ,
70- exist : None ,
75+ .. Default :: default ( )
7176 } )
7277 } else {
7378 Ok ( Registry {
7479 key_path : self . config . key_path . clone ( ) ,
75- value_name : None ,
76- value_data : None ,
77- exist : None ,
80+ ..Default :: default ( )
7881 } )
7982 }
8083 }
8184
82- pub fn set ( & self ) -> Result < ( ) , RegistryError > {
85+ pub fn set ( & self ) -> Result < Option < Registry > , RegistryError > {
86+ let mut what_if_metadata: Vec < String > = Vec :: new ( ) ;
8387 let reg_key = match self . open ( Security :: Write ) {
84- Ok ( ( reg_key, _subkey) ) => reg_key,
88+ Ok ( ( reg_key, _subkey) ) => Some ( reg_key) ,
8589 // handle NotFound error
8690 Err ( RegistryError :: RegistryKeyNotFound ( _) ) => {
8791 // if the key doesn't exist, some of the parent keys may
@@ -91,58 +95,89 @@ impl RegistryHelper {
9195 let mut reg_key = parent_key;
9296 for subkey in subkeys {
9397 let Ok ( path) = UCString :: < u16 > :: from_str ( subkey) else {
94- return Err ( RegistryError :: Utf16Conversion ( "subkey" . to_string ( ) ) ) ;
98+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "subkey" . to_string ( ) ) ) ;
9599 } ;
96100
97- reg_key = reg_key. create ( path, Security :: CreateSubKey ) ?;
101+ if self . what_if {
102+ what_if_metadata. push ( format ! ( "key: {subkey} not found, would create it" ) ) ;
103+ }
104+ else {
105+ reg_key = reg_key. create ( path, Security :: CreateSubKey ) ?;
106+ }
107+ }
108+ if self . what_if {
109+ None
110+ }
111+ else {
112+ Some ( self . open ( Security :: Write ) ?. 0 )
98113 }
99-
100- self . open ( Security :: Write ) ?. 0
101114 } ,
102- Err ( e) => return Err ( e) ,
115+ Err ( e) => return self . handle_error_or_what_if ( e)
103116 } ;
104117
105118 if let Some ( value_data) = & self . config . value_data {
106119 let Ok ( value_name) = U16CString :: from_str ( self . config . value_name . as_ref ( ) . unwrap ( ) ) else {
107- return Err ( RegistryError :: Utf16Conversion ( "valueName" . to_string ( ) ) ) ;
120+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueName" . to_string ( ) ) ) ;
108121 } ;
109122
110- match value_data {
123+ let data = match value_data {
111124 RegistryValueData :: String ( s) => {
112125 let Ok ( utf16) = U16CString :: from_str ( s) else {
113- return Err ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
126+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
114127 } ;
115- reg_key . set_value ( & value_name , & Data :: String ( utf16) ) ? ;
128+ Data :: String ( utf16)
116129 } ,
117130 RegistryValueData :: ExpandString ( s) => {
118131 let Ok ( utf16) = U16CString :: from_str ( s) else {
119- return Err ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
132+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
120133 } ;
121- reg_key . set_value ( & value_name , & Data :: ExpandString ( utf16) ) ? ;
134+ Data :: ExpandString ( utf16)
122135 } ,
123136 RegistryValueData :: Binary ( b) => {
124- reg_key . set_value ( & value_name , & Data :: Binary ( b. clone ( ) ) ) ? ;
137+ Data :: Binary ( b. clone ( ) )
125138 } ,
126139 RegistryValueData :: DWord ( d) => {
127- reg_key . set_value ( & value_name , & Data :: U32 ( * d) ) ? ;
140+ Data :: U32 ( * d)
128141 } ,
129142 RegistryValueData :: MultiString ( m) => {
130143 let mut m16: Vec < UCString < u16 > > = Vec :: < UCString < u16 > > :: new ( ) ;
131144 for s in m {
132145 let Ok ( utf16) = U16CString :: from_str ( s) else {
133- return Err ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
146+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
134147 } ;
135148 m16. push ( utf16) ;
136149 }
137- reg_key . set_value ( & value_name , & Data :: MultiString ( m16) ) ? ;
150+ Data :: MultiString ( m16)
138151 } ,
139152 RegistryValueData :: QWord ( q) => {
140- reg_key . set_value ( & value_name , & Data :: U64 ( * q) ) ? ;
153+ Data :: U64 ( * q)
141154 } ,
155+ } ;
156+
157+ if self . what_if {
158+ return Ok ( Some ( Registry {
159+ key_path : self . config . key_path . clone ( ) ,
160+ value_data : Some ( convert_reg_value ( & data) ?) ,
161+ value_name : self . config . value_name . clone ( ) ,
162+ metadata : if what_if_metadata. is_empty ( ) { None } else { Some ( Metadata { what_if : Some ( what_if_metadata) } ) } ,
163+ ..Default :: default ( )
164+ } ) ) ;
142165 }
166+
167+ if let Some ( reg_key) = reg_key {
168+ reg_key. set_value ( & value_name, & data) ?;
169+ } ;
143170 }
144171
145- Ok ( ( ) )
172+ if self . what_if {
173+ return Ok ( Some ( Registry {
174+ key_path : self . config . key_path . clone ( ) ,
175+ metadata : if what_if_metadata. is_empty ( ) { None } else { Some ( Metadata { what_if : Some ( what_if_metadata) } ) } ,
176+ ..Default :: default ( )
177+ } ) ) ;
178+ }
179+
180+ Ok ( None )
146181 }
147182
148183 pub fn remove ( & self ) -> Result < ( ) , RegistryError > {
@@ -215,6 +250,17 @@ impl RegistryHelper {
215250
216251 Ok ( ( parent_key, subkeys) )
217252 }
253+
254+ fn handle_error_or_what_if ( & self , error : RegistryError ) -> Result < Option < Registry > , RegistryError > {
255+ if self . what_if {
256+ return Ok ( Some ( Registry {
257+ key_path : self . config . key_path . clone ( ) ,
258+ metadata : Some ( Metadata { what_if : Some ( vec ! [ error. to_string( ) ] ) } ) ,
259+ ..Default :: default ( )
260+ } ) ) ;
261+ }
262+ Err ( error)
263+ }
218264}
219265
220266fn get_hive_from_path ( path : & str ) -> Result < ( Hive , & str ) , RegistryError > {
0 commit comments