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:: { Action , Registry , RegistryValueData , WhatIf } ;
7
7
use crate :: error:: RegistryError ;
8
8
9
9
pub struct RegistryHelper {
@@ -40,9 +40,8 @@ impl RegistryHelper {
40
40
exist = false ;
41
41
return Ok ( Registry {
42
42
key_path : self . config . key_path . clone ( ) ,
43
- value_name : None ,
44
- value_data : None ,
45
43
exist : Some ( exist) ,
44
+ ..Default :: default ( )
46
45
} ) ;
47
46
} ,
48
47
Err ( e) => return Err ( e) ,
@@ -56,8 +55,8 @@ impl RegistryHelper {
56
55
return Ok ( Registry {
57
56
key_path : self . config . key_path . clone ( ) ,
58
57
value_name : Some ( value_name. clone ( ) ) ,
59
- value_data : None ,
60
58
exist : Some ( exist) ,
59
+ ..Default :: default ( )
61
60
} ) ;
62
61
} ,
63
62
Err ( e) => return Err ( RegistryError :: RegistryValue ( e) ) ,
@@ -67,19 +66,18 @@ impl RegistryHelper {
67
66
key_path : self . config . key_path . clone ( ) ,
68
67
value_name : Some ( value_name. clone ( ) ) ,
69
68
value_data : Some ( convert_reg_value ( & value) ?) ,
70
- exist : None ,
69
+ .. Default :: default ( )
71
70
} )
72
71
} else {
73
72
Ok ( Registry {
74
73
key_path : self . config . key_path . clone ( ) ,
75
- value_name : None ,
76
- value_data : None ,
77
- exist : None ,
74
+ ..Default :: default ( )
78
75
} )
79
76
}
80
77
}
81
78
82
- pub fn set ( & self ) -> Result < ( ) , RegistryError > {
79
+ pub fn set ( & self , is_what_if : bool ) -> Result < Option < Registry > , RegistryError > {
80
+ let mut depth = None ;
83
81
let reg_key = match self . open ( Security :: Write ) {
84
82
Ok ( ( reg_key, _subkey) ) => reg_key,
85
83
// handle NotFound error
@@ -88,6 +86,7 @@ impl RegistryHelper {
88
86
// not exist either, so we need to find the valid parent key
89
87
// and then create the subkeys that don't exist
90
88
let ( parent_key, subkeys) = self . get_valid_parent_key_and_subkeys ( ) ?;
89
+ depth = Some ( subkeys. len ( ) ) ;
91
90
let mut reg_key = parent_key;
92
91
for subkey in subkeys {
93
92
let Ok ( path) = UCString :: < u16 > :: from_str ( subkey) else {
@@ -99,50 +98,84 @@ impl RegistryHelper {
99
98
100
99
self . open ( Security :: Write ) ?. 0
101
100
} ,
102
- Err ( e) => return Err ( e ) ,
101
+ Err ( e) => return self . handle_what_if_error ( e , is_what_if )
103
102
} ;
104
103
105
104
if let Some ( value_data) = & self . config . value_data {
106
105
let Ok ( value_name) = U16CString :: from_str ( self . config . value_name . as_ref ( ) . unwrap ( ) ) else {
107
- return Err ( RegistryError :: Utf16Conversion ( "valueName" . to_string ( ) ) ) ;
106
+ return self . handle_what_if_error ( RegistryError :: Utf16Conversion ( "valueName" . to_string ( ) ) , is_what_if ) ;
108
107
} ;
109
108
110
- match value_data {
109
+ let data = match value_data {
111
110
RegistryValueData :: String ( s) => {
112
111
let Ok ( utf16) = U16CString :: from_str ( s) else {
113
- return Err ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
112
+ return self . handle_what_if_error ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) , is_what_if ) ;
114
113
} ;
115
- reg_key . set_value ( & value_name , & Data :: String ( utf16) ) ? ;
114
+ Data :: String ( utf16)
116
115
} ,
117
116
RegistryValueData :: ExpandString ( s) => {
118
117
let Ok ( utf16) = U16CString :: from_str ( s) else {
119
- return Err ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
118
+ return self . handle_what_if_error ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) , is_what_if ) ;
120
119
} ;
121
- reg_key . set_value ( & value_name , & Data :: ExpandString ( utf16) ) ? ;
120
+ Data :: ExpandString ( utf16)
122
121
} ,
123
122
RegistryValueData :: Binary ( b) => {
124
- reg_key . set_value ( & value_name , & Data :: Binary ( b. clone ( ) ) ) ? ;
123
+ Data :: Binary ( b. clone ( ) )
125
124
} ,
126
125
RegistryValueData :: DWord ( d) => {
127
- reg_key . set_value ( & value_name , & Data :: U32 ( * d) ) ? ;
126
+ Data :: U32 ( * d)
128
127
} ,
129
128
RegistryValueData :: MultiString ( m) => {
130
129
let mut m16: Vec < UCString < u16 > > = Vec :: < UCString < u16 > > :: new ( ) ;
131
130
for s in m {
132
131
let Ok ( utf16) = U16CString :: from_str ( s) else {
133
- return Err ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
132
+ return self . handle_what_if_error ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) , is_what_if ) ;
134
133
} ;
135
134
m16. push ( utf16) ;
136
135
}
137
- reg_key . set_value ( & value_name , & Data :: MultiString ( m16) ) ? ;
136
+ Data :: MultiString ( m16)
138
137
} ,
139
138
RegistryValueData :: QWord ( q) => {
140
- reg_key . set_value ( & value_name , & Data :: U64 ( * q) ) ? ;
139
+ Data :: U64 ( * q)
141
140
} ,
141
+ } ;
142
+
143
+ if is_what_if {
144
+ let change_type = if let Some ( name_exists) = self . get ( ) ?. exist {
145
+ if name_exists { Action :: Clobber }
146
+ else { Action :: New }
147
+ } else { Action :: Clobber } ;
148
+ return Ok ( Some ( Registry {
149
+ key_path : self . config . key_path . clone ( ) ,
150
+ what_if : Some ( WhatIf {
151
+ change_type,
152
+ proposed_data : Some ( convert_reg_value ( & data) ?) ,
153
+ depth,
154
+ message : None
155
+ } ) ,
156
+ ..Default :: default ( )
157
+ } ) ) ;
142
158
}
159
+ reg_key. set_value ( & value_name, & data) ?;
143
160
}
144
161
145
- Ok ( ( ) )
162
+ if is_what_if {
163
+ let change_type = if let Some ( name_exists) = self . get ( ) ?. exist {
164
+ if name_exists { Action :: Clobber }
165
+ else { Action :: New }
166
+ } else { Action :: Clobber } ;
167
+ return Ok ( Some ( Registry {
168
+ key_path : self . config . key_path . clone ( ) ,
169
+ what_if : Some ( WhatIf {
170
+ change_type,
171
+ proposed_data : None ,
172
+ depth,
173
+ message : None
174
+ } ) ,
175
+ ..Default :: default ( )
176
+ } ) ) ;
177
+ }
178
+ Ok ( None )
146
179
}
147
180
148
181
pub fn remove ( & self ) -> Result < ( ) , RegistryError > {
@@ -215,6 +248,22 @@ impl RegistryHelper {
215
248
216
249
Ok ( ( parent_key, subkeys) )
217
250
}
251
+
252
+ fn handle_what_if_error ( & self , error : RegistryError , is_what_if : bool ) -> Result < Option < Registry > , RegistryError > {
253
+ if is_what_if {
254
+ return Ok ( Some ( Registry {
255
+ key_path : self . config . key_path . clone ( ) ,
256
+ what_if : Some ( WhatIf {
257
+ change_type : Action :: Error ,
258
+ depth : None ,
259
+ proposed_data : None ,
260
+ message : Some ( error. to_string ( ) )
261
+ } ) ,
262
+ ..Default :: default ( )
263
+ } ) ) ;
264
+ }
265
+ Err ( error)
266
+ }
218
267
}
219
268
220
269
fn get_hive_from_path ( path : & str ) -> Result < ( Hive , & str ) , RegistryError > {
@@ -313,7 +362,7 @@ fn get_nonexisting_value() {
313
362
#[ test]
314
363
fn set_and_remove_test_value ( ) {
315
364
let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest\\DSCSubKey","valueName":"TestValue","valueData": { "String": "Hello"} }"# ) . unwrap ( ) ;
316
- reg_helper. set ( ) . unwrap ( ) ;
365
+ reg_helper. set ( false ) . unwrap ( ) ;
317
366
let result = reg_helper. get ( ) . unwrap ( ) ;
318
367
assert_eq ! ( result. key_path, r#"HKCU\DSCTest\DSCSubKey"# ) ;
319
368
assert_eq ! ( result. value_name, Some ( "TestValue" . to_string( ) ) ) ;
@@ -340,7 +389,7 @@ fn set_and_remove_test_value() {
340
389
#[ test]
341
390
fn delete_tree ( ) {
342
391
let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest2\\DSCSubKey","valueName":"TestValue","valueData": { "String": "Hello"} }"# ) . unwrap ( ) ;
343
- reg_helper. set ( ) . unwrap ( ) ;
392
+ reg_helper. set ( false ) . unwrap ( ) ;
344
393
let result = reg_helper. get ( ) . unwrap ( ) ;
345
394
assert_eq ! ( result. key_path, r#"HKCU\DSCTest2\DSCSubKey"# ) ;
346
395
assert_eq ! ( result. value_name, Some ( "TestValue" . to_string( ) ) ) ;
0 commit comments