@@ -9,7 +9,7 @@ use windows::{
99} ;
1010
1111use 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
1414pub 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 {
0 commit comments