Skip to content

Commit 3c5e1fa

Browse files
author
Steve Lee (POWERSHELL HE/HIM) (from Dev Box)
committed
code quality fixes
1 parent 4fb96b5 commit 3c5e1fa

File tree

4 files changed

+214
-330
lines changed

4 files changed

+214
-330
lines changed

resources/WindowsUpdate/src/windows_update/export.rs

Lines changed: 53 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use windows::{
99
};
1010

1111
use std::collections::HashSet;
12-
use crate::windows_update::types::{UpdateList, UpdateInfo, MsrcSeverity, UpdateType};
12+
use crate::windows_update::types::{UpdateList, UpdateInfo, extract_update_info};
1313

1414
pub fn handle_export(input: &str) -> Result<String> {
1515
// Parse optional filter input as UpdateList
@@ -36,9 +36,9 @@ pub fn handle_export(input: &str) -> Result<String> {
3636
let filters = &update_list.updates;
3737

3838
// Initialize COM
39-
unsafe {
40-
CoInitializeEx(Some(std::ptr::null()), COINIT_MULTITHREADED).ok()?;
41-
}
39+
let com_initialized = unsafe {
40+
CoInitializeEx(Some(std::ptr::null()), COINIT_MULTITHREADED).is_ok()
41+
};
4242

4343
let result = unsafe {
4444
// Create update session
@@ -68,7 +68,6 @@ pub fn handle_export(input: &str) -> Result<String> {
6868
// Collect matching updates for this specific filter
6969
for i in 0..count {
7070
let update = updates.get_Item(i)?;
71-
let title = update.Title()?.to_string();
7271
let identity = update.Identity()?;
7372
let update_id = identity.UpdateID()?.to_string();
7473

@@ -77,141 +76,111 @@ pub fn handle_export(input: &str) -> Result<String> {
7776
continue;
7877
}
7978

80-
// Extract all update information first for filtering
81-
let is_installed = update.IsInstalled()?.as_bool();
82-
let description = update.Description()?.to_string();
83-
let is_uninstallable = update.IsUninstallable()?.as_bool();
84-
85-
// Get KB Article IDs
86-
let kb_articles = update.KBArticleIDs()?;
87-
let kb_count = kb_articles.Count()?;
88-
let mut kb_article_ids = Vec::new();
89-
for j in 0..kb_count {
90-
if let Ok(kb_str) = kb_articles.get_Item(j) {
91-
kb_article_ids.push(kb_str.to_string());
92-
}
93-
}
94-
95-
let min_download_size = 0i64;
96-
97-
// Get MSRC Severity
98-
let msrc_severity = if let Ok(severity_str) = update.MsrcSeverity() {
99-
match severity_str.to_string().as_str() {
100-
"Critical" => Some(MsrcSeverity::Critical),
101-
"Important" => Some(MsrcSeverity::Important),
102-
"Moderate" => Some(MsrcSeverity::Moderate),
103-
"Low" => Some(MsrcSeverity::Low),
104-
_ => None,
105-
}
106-
} else {
107-
None
108-
};
109-
110-
// Get Security Bulletin IDs
111-
let security_bulletins = update.SecurityBulletinIDs()?;
112-
let bulletin_count = security_bulletins.Count()?;
113-
let mut security_bulletin_ids = Vec::new();
114-
for j in 0..bulletin_count {
115-
if let Ok(bulletin_str) = security_bulletins.get_Item(j) {
116-
security_bulletin_ids.push(bulletin_str.to_string());
117-
}
118-
}
119-
120-
// Determine update type
121-
let update_type = {
122-
use windows::Win32::System::UpdateAgent::UpdateType as WinUpdateType;
123-
match update.Type()? {
124-
WinUpdateType(2) => UpdateType::Driver,
125-
_ => UpdateType::Software,
126-
}
127-
};
79+
// Extract all update information for filtering
80+
let update_info = extract_update_info(&update)?;
12881

12982
// Apply all filters (AND logic within a single filter)
13083
let mut matches = true;
13184

13285
// Filter by is_installed
13386
if let Some(installed_filter) = filter.is_installed {
134-
matches = matches && (is_installed == installed_filter);
87+
matches = matches && (update_info.is_installed == Some(installed_filter));
13588
}
13689

13790
// Filter by title with wildcard support
13891
if let Some(title_filter) = &filter.title {
139-
matches = matches && matches_wildcard(&title, title_filter);
92+
if let Some(ref title) = update_info.title {
93+
matches = matches && matches_wildcard(title, title_filter);
94+
} else {
95+
matches = false;
96+
}
14097
}
14198

14299
// Filter by id
143100
if let Some(id_filter) = &filter.id {
144-
matches = matches && update_id.eq_ignore_ascii_case(id_filter);
101+
if let Some(ref id) = update_info.id {
102+
matches = matches && id.eq_ignore_ascii_case(id_filter);
103+
} else {
104+
matches = false;
105+
}
145106
}
146107

147108
// Filter by description with wildcard support
148109
if let Some(desc_filter) = &filter.description {
149-
matches = matches && matches_wildcard(&description, desc_filter);
110+
if let Some(ref description) = update_info.description {
111+
matches = matches && matches_wildcard(description, desc_filter);
112+
} else {
113+
matches = false;
114+
}
150115
}
151116

152117
// Filter by is_uninstallable
153118
if let Some(uninstallable_filter) = filter.is_uninstallable {
154-
matches = matches && (is_uninstallable == uninstallable_filter);
119+
matches = matches && (update_info.is_uninstallable == Some(uninstallable_filter));
155120
}
156121

157122
// Filter by KB article IDs (match if any KB ID in the filter is present)
158123
if let Some(kb_filter) = &filter.kb_article_ids {
159124
if !kb_filter.is_empty() {
160-
let kb_matches = kb_filter.iter().any(|filter_kb| {
161-
kb_article_ids.iter().any(|update_kb| update_kb.eq_ignore_ascii_case(filter_kb))
162-
});
163-
matches = matches && kb_matches;
125+
if let Some(ref kb_article_ids) = update_info.kb_article_ids {
126+
let kb_matches = kb_filter.iter().any(|filter_kb| {
127+
kb_article_ids.iter().any(|update_kb| update_kb.eq_ignore_ascii_case(filter_kb))
128+
});
129+
matches = matches && kb_matches;
130+
} else {
131+
matches = false;
132+
}
164133
}
165134
}
166135

167136
// Filter by min_download_size (if specified, update size must be >= filter size)
168137
if let Some(size_filter) = filter.min_download_size {
169-
matches = matches && (min_download_size >= size_filter);
138+
if let Some(min_download_size) = update_info.min_download_size {
139+
matches = matches && (min_download_size >= size_filter);
140+
} else {
141+
matches = false;
142+
}
170143
}
171144

172145
// Filter by MSRC severity
173146
if let Some(severity_filter) = &filter.msrc_severity {
174-
matches = matches && (msrc_severity.as_ref() == Some(severity_filter));
147+
matches = matches && (update_info.msrc_severity.as_ref() == Some(severity_filter));
175148
}
176149

177150
// Filter by security bulletin IDs (match if any bulletin ID in the filter is present)
178151
if let Some(bulletin_filter) = &filter.security_bulletin_ids {
179152
if !bulletin_filter.is_empty() {
180-
let bulletin_matches = bulletin_filter.iter().any(|filter_bulletin| {
181-
security_bulletin_ids.iter().any(|update_bulletin| update_bulletin.eq_ignore_ascii_case(filter_bulletin))
182-
});
183-
matches = matches && bulletin_matches;
153+
if let Some(ref security_bulletin_ids) = update_info.security_bulletin_ids {
154+
let bulletin_matches = bulletin_filter.iter().any(|filter_bulletin| {
155+
security_bulletin_ids.iter().any(|update_bulletin| update_bulletin.eq_ignore_ascii_case(filter_bulletin))
156+
});
157+
matches = matches && bulletin_matches;
158+
} else {
159+
matches = false;
160+
}
184161
}
185162
}
186163

187164
// Filter by update type
188165
if let Some(type_filter) = &filter.update_type {
189-
matches = matches && (&update_type == type_filter);
166+
matches = matches && (update_info.update_type.as_ref() == Some(type_filter));
190167
}
191168

192169
if matches {
193-
matched_update_ids.insert(update_id.clone());
194-
all_found_updates.push(UpdateInfo {
195-
title: Some(title),
196-
is_installed: Some(is_installed),
197-
description: Some(description),
198-
id: Some(update_id),
199-
is_uninstallable: Some(is_uninstallable),
200-
kb_article_ids: Some(kb_article_ids),
201-
min_download_size: Some(min_download_size),
202-
msrc_severity,
203-
security_bulletin_ids: Some(security_bulletin_ids),
204-
update_type: Some(update_type),
205-
});
170+
matched_update_ids.insert(update_id);
171+
all_found_updates.push(update_info);
206172
}
207173
}
208174
}
209175

210176
Ok(all_found_updates)
211177
};
212178

213-
unsafe {
214-
CoUninitialize();
179+
// Ensure COM is uninitialized if it was initialized
180+
if com_initialized {
181+
unsafe {
182+
CoUninitialize();
183+
}
215184
}
216185

217186
match result {

resources/WindowsUpdate/src/windows_update/get.rs

Lines changed: 21 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use windows::{
88
Win32::System::UpdateAgent::*,
99
};
1010

11-
use crate::windows_update::types::{UpdateList, UpdateInfo, MsrcSeverity, UpdateType};
11+
use crate::windows_update::types::{UpdateList, extract_update_info};
1212

1313
pub fn handle_get(input: &str) -> Result<String> {
1414
// Parse input as UpdateList
@@ -22,10 +22,15 @@ pub fn handle_get(input: &str) -> Result<String> {
2222
// Get the first filter
2323
let update_input = &update_list.updates[0];
2424

25-
// Initialize COM
26-
unsafe {
27-
CoInitializeEx(Some(std::ptr::null()), COINIT_MULTITHREADED).ok()?;
25+
// Validate that at least one search criterion is provided
26+
if update_input.title.is_none() && update_input.id.is_none() {
27+
return Err(Error::new(E_INVALIDARG, "At least one of 'title' or 'id' must be specified for get operation"));
2828
}
29+
30+
// Initialize COM
31+
let com_initialized = unsafe {
32+
CoInitializeEx(Some(std::ptr::null()), COINIT_MULTITHREADED).is_ok()
33+
};
2934

3035
let result = unsafe {
3136
// Create update session using the proper interface
@@ -46,7 +51,7 @@ pub fn handle_get(input: &str) -> Result<String> {
4651
let count = updates.Count()?;
4752

4853
// Find the update by title or id
49-
let mut found_update: Option<UpdateInfo> = None;
54+
let mut found_update = None;
5055
for i in 0..count {
5156
let update = updates.get_Item(i)?;
5257
let title = update.Title()?.to_string();
@@ -66,93 +71,31 @@ pub fn handle_get(input: &str) -> Result<String> {
6671
};
6772

6873
// Both must match if both are provided
69-
let matches = title_match && id_match;
70-
71-
if matches {
72-
// Extract update information
73-
let is_installed = update.IsInstalled()?.as_bool();
74-
let description = update.Description()?.to_string();
75-
let id = update_id;
76-
let is_uninstallable = update.IsUninstallable()?.as_bool();
77-
78-
// Get KB Article IDs
79-
let kb_articles = update.KBArticleIDs()?;
80-
let kb_count = kb_articles.Count()?;
81-
let mut kb_article_ids = Vec::new();
82-
for j in 0..kb_count {
83-
if let Ok(kb_str) = kb_articles.get_Item(j) {
84-
kb_article_ids.push(kb_str.to_string());
85-
}
86-
}
87-
88-
// Get min download size (DECIMAL type - complex to convert, using 0 for now)
89-
// Windows Update API returns DECIMAL which would require complex conversion
90-
let min_download_size = 0i64;
91-
92-
// Get MSRC Severity
93-
let msrc_severity = if let Ok(severity_str) = update.MsrcSeverity() {
94-
match severity_str.to_string().as_str() {
95-
"Critical" => Some(MsrcSeverity::Critical),
96-
"Important" => Some(MsrcSeverity::Important),
97-
"Moderate" => Some(MsrcSeverity::Moderate),
98-
"Low" => Some(MsrcSeverity::Low),
99-
_ => None,
100-
}
101-
} else {
102-
None
103-
};
104-
105-
// Get Security Bulletin IDs
106-
let security_bulletins = update.SecurityBulletinIDs()?;
107-
let bulletin_count = security_bulletins.Count()?;
108-
let mut security_bulletin_ids = Vec::new();
109-
for j in 0..bulletin_count {
110-
if let Ok(bulletin_str) = security_bulletins.get_Item(j) {
111-
security_bulletin_ids.push(bulletin_str.to_string());
112-
}
113-
}
114-
115-
// Determine update type
116-
let update_type = {
117-
use windows::Win32::System::UpdateAgent::UpdateType as WinUpdateType;
118-
match update.Type()? {
119-
WinUpdateType(2) => UpdateType::Driver, // utDriver = 2
120-
_ => UpdateType::Software,
121-
}
122-
};
123-
124-
found_update = Some(UpdateInfo {
125-
title: Some(title),
126-
is_installed: Some(is_installed),
127-
description: Some(description),
128-
id: Some(id),
129-
is_uninstallable: Some(is_uninstallable),
130-
kb_article_ids: Some(kb_article_ids),
131-
min_download_size: Some(min_download_size),
132-
msrc_severity,
133-
security_bulletin_ids: Some(security_bulletin_ids),
134-
update_type: Some(update_type),
135-
});
74+
if title_match && id_match {
75+
found_update = Some(extract_update_info(&update)?);
13676
break;
13777
}
13878
}
13979

140-
found_update
80+
Ok(found_update)
14181
};
14282

143-
unsafe {
144-
CoUninitialize();
83+
// Ensure COM is uninitialized if it was initialized
84+
if com_initialized {
85+
unsafe {
86+
CoUninitialize();
87+
}
14588
}
14689

14790
match result {
148-
Some(update_info) => {
91+
Ok(Some(update_info)) => {
14992
let result = UpdateList {
15093
updates: vec![update_info]
15194
};
15295
serde_json::to_string(&result)
15396
.map_err(|e| Error::new(E_FAIL, format!("Failed to serialize output: {}", e)))
15497
}
155-
None => {
98+
Ok(None) => {
15699
let search_criteria = if let Some(title) = &update_input.title {
157100
format!("title '{}'", title)
158101
} else if let Some(id) = &update_input.id {
@@ -162,5 +105,6 @@ pub fn handle_get(input: &str) -> Result<String> {
162105
};
163106
Err(Error::new(E_FAIL, format!("Update with {} not found", search_criteria)))
164107
}
108+
Err(e) => Err(e),
165109
}
166110
}

0 commit comments

Comments
 (0)