3
3
4
4
use registry:: { Data , Hive , RegKey , Security , key, value} ;
5
5
use utfx:: { U16CString , UCString } ;
6
- use crate :: config:: { Registry , RegistryValueData , WhatIf } ;
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 {
16
- pub fn new ( config : & str ) -> Result < Self , RegistryError > {
17
+ pub fn new ( config : & str , what_if : bool ) -> Result < Self , RegistryError > {
17
18
let registry: Registry = match serde_json:: from_str ( config) {
18
19
Ok ( config) => config,
19
20
Err ( e) => return Err ( RegistryError :: Json ( e) ) ,
@@ -26,6 +27,7 @@ impl RegistryHelper {
26
27
config : registry,
27
28
hive,
28
29
subkey : subkey. to_string ( ) ,
30
+ what_if
29
31
}
30
32
)
31
33
}
@@ -76,49 +78,54 @@ impl RegistryHelper {
76
78
}
77
79
}
78
80
79
- pub fn set ( & self , is_what_if : bool ) -> Result < Option < Registry > , RegistryError > {
81
+ pub fn set ( & self ) -> Result < Option < Registry > , RegistryError > {
82
+ let mut what_if_metadata: Vec < String > = Vec :: new ( ) ;
80
83
let reg_key = match self . open ( Security :: Write ) {
81
84
Ok ( ( reg_key, _subkey) ) => Some ( reg_key) ,
82
85
// handle NotFound error
83
86
Err ( RegistryError :: RegistryKeyNotFound ( _) ) => {
84
87
// if the key doesn't exist, some of the parent keys may
85
88
// not exist either, so we need to find the valid parent key
86
89
// and then create the subkeys that don't exist
87
- if is_what_if {
88
- None
89
- }
90
- else {
91
- let ( parent_key, subkeys) = self . get_valid_parent_key_and_subkeys ( ) ?;
92
- let mut reg_key = parent_key;
93
- for subkey in subkeys {
94
- let Ok ( path) = UCString :: < u16 > :: from_str ( subkey) else {
95
- return Err ( RegistryError :: Utf16Conversion ( "subkey" . to_string ( ) ) ) ;
96
- } ;
90
+ let ( parent_key, subkeys) = self . get_valid_parent_key_and_subkeys ( ) ?;
91
+ let mut reg_key = parent_key;
92
+ for subkey in subkeys {
93
+ let Ok ( path) = UCString :: < u16 > :: from_str ( subkey) else {
94
+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "subkey" . to_string ( ) ) ) ;
95
+ } ;
97
96
97
+ if self . what_if {
98
+ what_if_metadata. push ( format ! ( "key: {subkey} not found, would create it" ) ) ;
99
+ }
100
+ else {
98
101
reg_key = reg_key. create ( path, Security :: CreateSubKey ) ?;
99
102
}
100
-
103
+ }
104
+ if self . what_if {
105
+ None
106
+ }
107
+ else {
101
108
Some ( self . open ( Security :: Write ) ?. 0 )
102
109
}
103
110
} ,
104
- Err ( e) => return self . handle_error_or_what_if ( e, is_what_if )
111
+ Err ( e) => return self . handle_error_or_what_if ( e)
105
112
} ;
106
113
107
114
if let Some ( value_data) = & self . config . value_data {
108
115
let Ok ( value_name) = U16CString :: from_str ( self . config . value_name . as_ref ( ) . unwrap ( ) ) else {
109
- return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueName" . to_string ( ) ) , is_what_if ) ;
116
+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueName" . to_string ( ) ) ) ;
110
117
} ;
111
118
112
119
let data = match value_data {
113
120
RegistryValueData :: String ( s) => {
114
121
let Ok ( utf16) = U16CString :: from_str ( s) else {
115
- return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) , is_what_if ) ;
122
+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
116
123
} ;
117
124
Data :: String ( utf16)
118
125
} ,
119
126
RegistryValueData :: ExpandString ( s) => {
120
127
let Ok ( utf16) = U16CString :: from_str ( s) else {
121
- return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) , is_what_if ) ;
128
+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
122
129
} ;
123
130
Data :: ExpandString ( utf16)
124
131
} ,
@@ -132,7 +139,7 @@ impl RegistryHelper {
132
139
let mut m16: Vec < UCString < u16 > > = Vec :: < UCString < u16 > > :: new ( ) ;
133
140
for s in m {
134
141
let Ok ( utf16) = U16CString :: from_str ( s) else {
135
- return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) , is_what_if ) ;
142
+ return self . handle_error_or_what_if ( RegistryError :: Utf16Conversion ( "valueData" . to_string ( ) ) ) ;
136
143
} ;
137
144
m16. push ( utf16) ;
138
145
}
@@ -143,12 +150,12 @@ impl RegistryHelper {
143
150
} ,
144
151
} ;
145
152
146
- if is_what_if {
153
+ if self . what_if {
147
154
return Ok ( Some ( Registry {
148
155
key_path : self . config . key_path . clone ( ) ,
149
156
value_data : Some ( convert_reg_value ( & data) ?) ,
150
157
value_name : self . config . value_name . clone ( ) ,
151
- what_if : Some ( WhatIf { error : None } ) ,
158
+ metadata : if what_if_metadata . is_empty ( ) { None } else { Some ( Metadata { what_if : Some ( what_if_metadata ) } ) } ,
152
159
..Default :: default ( )
153
160
} ) ) ;
154
161
}
@@ -158,10 +165,10 @@ impl RegistryHelper {
158
165
} ;
159
166
}
160
167
161
- if is_what_if {
168
+ if self . what_if {
162
169
return Ok ( Some ( Registry {
163
170
key_path : self . config . key_path . clone ( ) ,
164
- what_if : Some ( WhatIf { error : None } ) ,
171
+ metadata : if what_if_metadata . is_empty ( ) { None } else { Some ( Metadata { what_if : Some ( what_if_metadata ) } ) } ,
165
172
..Default :: default ( )
166
173
} ) ) ;
167
174
}
@@ -240,12 +247,12 @@ impl RegistryHelper {
240
247
Ok ( ( parent_key, subkeys) )
241
248
}
242
249
243
- fn handle_error_or_what_if ( & self , error : RegistryError , is_what_if : bool ) -> Result < Option < Registry > , RegistryError > {
250
+ fn handle_error_or_what_if ( & self , error : RegistryError ) -> Result < Option < Registry > , RegistryError > {
244
251
// TODO: return error message via metadata instead of as property within set state
245
- if is_what_if {
252
+ if self . what_if {
246
253
return Ok ( Some ( Registry {
247
254
key_path : self . config . key_path . clone ( ) ,
248
- what_if : Some ( WhatIf { error : Some ( error. to_string ( ) ) } ) ,
255
+ metadata : Some ( Metadata { what_if : Some ( vec ! [ error. to_string( ) ] ) } ) ,
249
256
..Default :: default ( )
250
257
} ) ) ;
251
258
}
@@ -310,7 +317,7 @@ fn convert_reg_value(value: &Data) -> Result<RegistryValueData, RegistryError> {
310
317
311
318
#[ test]
312
319
fn get_hklm_key ( ) {
313
- let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKEY_LOCAL_MACHINE"}"# ) . unwrap ( ) ;
320
+ let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKEY_LOCAL_MACHINE"}"# , false ) . unwrap ( ) ;
314
321
let reg_config = reg_helper. get ( ) . unwrap ( ) ;
315
322
assert_eq ! ( reg_config. key_path, r#"HKEY_LOCAL_MACHINE"# ) ;
316
323
assert_eq ! ( reg_config. value_name, None ) ;
@@ -319,7 +326,7 @@ fn get_hklm_key() {
319
326
320
327
#[ test]
321
328
fn get_product_name ( ) {
322
- let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion","valueName":"ProductName"}"# ) . unwrap ( ) ;
329
+ let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion","valueName":"ProductName"}"# , false ) . unwrap ( ) ;
323
330
let reg_config = reg_helper. get ( ) . unwrap ( ) ;
324
331
assert_eq ! ( reg_config. key_path, r#"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"# ) ;
325
332
assert_eq ! ( reg_config. value_name, Some ( "ProductName" . to_string( ) ) ) ;
@@ -328,7 +335,7 @@ fn get_product_name() {
328
335
329
336
#[ test]
330
337
fn get_nonexisting_key ( ) {
331
- let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DoesNotExist"}"# ) . unwrap ( ) ;
338
+ let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DoesNotExist"}"# , false ) . unwrap ( ) ;
332
339
let reg_config = reg_helper. get ( ) . unwrap ( ) ;
333
340
assert_eq ! ( reg_config. key_path, r#"HKCU\DoesNotExist"# ) ;
334
341
assert_eq ! ( reg_config. value_name, None ) ;
@@ -338,7 +345,7 @@ fn get_nonexisting_key() {
338
345
339
346
#[ test]
340
347
fn get_nonexisting_value ( ) {
341
- let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\Software","valueName":"DoesNotExist"}"# ) . unwrap ( ) ;
348
+ let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\Software","valueName":"DoesNotExist"}"# , false ) . unwrap ( ) ;
342
349
let reg_config = reg_helper. get ( ) . unwrap ( ) ;
343
350
assert_eq ! ( reg_config. key_path, r#"HKCU\Software"# ) ;
344
351
assert_eq ! ( reg_config. value_name, Some ( "DoesNotExist" . to_string( ) ) ) ;
@@ -348,8 +355,8 @@ fn get_nonexisting_value() {
348
355
349
356
#[ test]
350
357
fn set_and_remove_test_value ( ) {
351
- let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest\\DSCSubKey","valueName":"TestValue","valueData": { "String": "Hello"} }"# ) . unwrap ( ) ;
352
- reg_helper. set ( false ) . unwrap ( ) ;
358
+ let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest\\DSCSubKey","valueName":"TestValue","valueData": { "String": "Hello"} }"# , false ) . unwrap ( ) ;
359
+ reg_helper. set ( ) . unwrap ( ) ;
353
360
let result = reg_helper. get ( ) . unwrap ( ) ;
354
361
assert_eq ! ( result. key_path, r#"HKCU\DSCTest\DSCSubKey"# ) ;
355
362
assert_eq ! ( result. value_name, Some ( "TestValue" . to_string( ) ) ) ;
@@ -360,7 +367,7 @@ fn set_and_remove_test_value() {
360
367
assert_eq ! ( result. value_name, Some ( "TestValue" . to_string( ) ) ) ;
361
368
assert_eq ! ( result. value_data, None ) ;
362
369
assert_eq ! ( result. exist, Some ( false ) ) ;
363
- let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest"}"# ) . unwrap ( ) ;
370
+ let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest"}"# , false ) . unwrap ( ) ;
364
371
let result = reg_helper. get ( ) . unwrap ( ) ;
365
372
assert_eq ! ( result. key_path, r#"HKCU\DSCTest"# ) ;
366
373
assert_eq ! ( result. value_name, None ) ;
@@ -375,13 +382,13 @@ fn set_and_remove_test_value() {
375
382
376
383
#[ test]
377
384
fn delete_tree ( ) {
378
- let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest2\\DSCSubKey","valueName":"TestValue","valueData": { "String": "Hello"} }"# ) . unwrap ( ) ;
379
- reg_helper. set ( false ) . unwrap ( ) ;
385
+ let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest2\\DSCSubKey","valueName":"TestValue","valueData": { "String": "Hello"} }"# , false ) . unwrap ( ) ;
386
+ reg_helper. set ( ) . unwrap ( ) ;
380
387
let result = reg_helper. get ( ) . unwrap ( ) ;
381
388
assert_eq ! ( result. key_path, r#"HKCU\DSCTest2\DSCSubKey"# ) ;
382
389
assert_eq ! ( result. value_name, Some ( "TestValue" . to_string( ) ) ) ;
383
390
assert_eq ! ( result. value_data, Some ( RegistryValueData :: String ( "Hello" . to_string( ) ) ) ) ;
384
- let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest2"}"# ) . unwrap ( ) ;
391
+ let reg_helper = RegistryHelper :: new ( r#"{"keyPath":"HKCU\\DSCTest2"}"# , false ) . unwrap ( ) ;
385
392
reg_helper. remove ( ) . unwrap ( ) ;
386
393
let result = reg_helper. get ( ) . unwrap ( ) ;
387
394
assert_eq ! ( result. key_path, r#"HKCU\DSCTest2"# ) ;
0 commit comments