3
3
4
4
use registry:: { Data , Hive , RegKey , Security , key, value} ;
5
5
use utfx:: { U16CString , UCString } ;
6
- use crate :: config:: { Registry , RegistryValueData } ;
6
+ use crate :: config:: { Metadata , Registry , RegistryValueData } ;
7
7
use crate :: error:: RegistryError ;
8
8
9
9
pub struct RegistryHelper {
10
10
config : Registry ,
11
11
hive : Hive ,
12
12
subkey : String ,
13
+ what_if : bool ,
13
14
}
14
15
15
16
impl RegistryHelper {
@@ -26,10 +27,15 @@ impl RegistryHelper {
26
27
config : registry,
27
28
hive,
28
29
subkey : subkey. to_string ( ) ,
30
+ what_if : false
29
31
}
30
32
)
31
33
}
32
34
35
+ pub fn enable_what_if ( & mut self ) {
36
+ self . what_if = true ;
37
+ }
38
+
33
39
pub fn get ( & self ) -> Result < Registry , RegistryError > {
34
40
let exist: bool ;
35
41
let ( reg_key, _subkey) = match self . open ( Security :: Read ) {
@@ -40,9 +46,8 @@ impl RegistryHelper {
40
46
exist = false ;
41
47
return Ok ( Registry {
42
48
key_path : self . config . key_path . clone ( ) ,
43
- value_name : None ,
44
- value_data : None ,
45
49
exist : Some ( exist) ,
50
+ ..Default :: default ( )
46
51
} ) ;
47
52
} ,
48
53
Err ( e) => return Err ( e) ,
@@ -56,8 +61,8 @@ impl RegistryHelper {
56
61
return Ok ( Registry {
57
62
key_path : self . config . key_path . clone ( ) ,
58
63
value_name : Some ( value_name. clone ( ) ) ,
59
- value_data : None ,
60
64
exist : Some ( exist) ,
65
+ ..Default :: default ( )
61
66
} ) ;
62
67
} ,
63
68
Err ( e) => return Err ( RegistryError :: RegistryValue ( e) ) ,
@@ -67,21 +72,20 @@ impl RegistryHelper {
67
72
key_path : self . config . key_path . clone ( ) ,
68
73
value_name : Some ( value_name. clone ( ) ) ,
69
74
value_data : Some ( convert_reg_value ( & value) ?) ,
70
- exist : None ,
75
+ .. Default :: default ( )
71
76
} )
72
77
} else {
73
78
Ok ( Registry {
74
79
key_path : self . config . key_path . clone ( ) ,
75
- value_name : None ,
76
- value_data : None ,
77
- exist : None ,
80
+ ..Default :: default ( )
78
81
} )
79
82
}
80
83
}
81
84
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 ( ) ;
83
87
let reg_key = match self . open ( Security :: Write ) {
84
- Ok ( ( reg_key, _subkey) ) => reg_key,
88
+ Ok ( ( reg_key, _subkey) ) => Some ( reg_key) ,
85
89
// handle NotFound error
86
90
Err ( RegistryError :: RegistryKeyNotFound ( _) ) => {
87
91
// if the key doesn't exist, some of the parent keys may
@@ -91,58 +95,89 @@ impl RegistryHelper {
91
95
let mut reg_key = parent_key;
92
96
for subkey in subkeys {
93
97
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 ( ) ) ) ;
95
99
} ;
96
100
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 )
98
113
}
99
-
100
- self . open ( Security :: Write ) ?. 0
101
114
} ,
102
- Err ( e) => return Err ( e) ,
115
+ Err ( e) => return self . handle_error_or_what_if ( e)
103
116
} ;
104
117
105
118
if let Some ( value_data) = & self . config . value_data {
106
119
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 ( ) ) ) ;
108
121
} ;
109
122
110
- match value_data {
123
+ let data = match value_data {
111
124
RegistryValueData :: String ( s) => {
112
125
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 ( ) ) ) ;
114
127
} ;
115
- reg_key . set_value ( & value_name , & Data :: String ( utf16) ) ? ;
128
+ Data :: String ( utf16)
116
129
} ,
117
130
RegistryValueData :: ExpandString ( s) => {
118
131
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 ( ) ) ) ;
120
133
} ;
121
- reg_key . set_value ( & value_name , & Data :: ExpandString ( utf16) ) ? ;
134
+ Data :: ExpandString ( utf16)
122
135
} ,
123
136
RegistryValueData :: Binary ( b) => {
124
- reg_key . set_value ( & value_name , & Data :: Binary ( b. clone ( ) ) ) ? ;
137
+ Data :: Binary ( b. clone ( ) )
125
138
} ,
126
139
RegistryValueData :: DWord ( d) => {
127
- reg_key . set_value ( & value_name , & Data :: U32 ( * d) ) ? ;
140
+ Data :: U32 ( * d)
128
141
} ,
129
142
RegistryValueData :: MultiString ( m) => {
130
143
let mut m16: Vec < UCString < u16 > > = Vec :: < UCString < u16 > > :: new ( ) ;
131
144
for s in m {
132
145
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 ( ) ) ) ;
134
147
} ;
135
148
m16. push ( utf16) ;
136
149
}
137
- reg_key . set_value ( & value_name , & Data :: MultiString ( m16) ) ? ;
150
+ Data :: MultiString ( m16)
138
151
} ,
139
152
RegistryValueData :: QWord ( q) => {
140
- reg_key . set_value ( & value_name , & Data :: U64 ( * q) ) ? ;
153
+ Data :: U64 ( * q)
141
154
} ,
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
+ } ) ) ;
142
165
}
166
+
167
+ if let Some ( reg_key) = reg_key {
168
+ reg_key. set_value ( & value_name, & data) ?;
169
+ } ;
143
170
}
144
171
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 )
146
181
}
147
182
148
183
pub fn remove ( & self ) -> Result < ( ) , RegistryError > {
@@ -215,6 +250,17 @@ impl RegistryHelper {
215
250
216
251
Ok ( ( parent_key, subkeys) )
217
252
}
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
+ }
218
264
}
219
265
220
266
fn get_hive_from_path ( path : & str ) -> Result < ( Hive , & str ) , RegistryError > {
0 commit comments