(input: &str)
| 13 | use crate::windows_update::types::{UpdateList, UpdateInfo, extract_update_info}; |
| 14 | |
| 15 | pub fn handle_export(input: &str) -> Result<String> { |
| 16 | // Parse optional filter input as UpdateList |
| 17 | let update_list: UpdateList = if input.trim().is_empty() { |
| 18 | UpdateList { |
| 19 | restart_required: None, |
| 20 | updates: vec![UpdateInfo { |
| 21 | description: None, |
| 22 | id: None, |
| 23 | installation_behavior: None, |
| 24 | is_installed: None, |
| 25 | is_uninstallable: None, |
| 26 | kb_article_ids: None, |
| 27 | recommended_hard_disk_space: None, |
| 28 | msrc_severity: None, |
| 29 | security_bulletin_ids: None, |
| 30 | title: None, |
| 31 | update_type: None, |
| 32 | }] |
| 33 | } |
| 34 | } else { |
| 35 | serde_json::from_str(input) |
| 36 | .map_err(|e| Error::new(E_INVALIDARG, t!("export.failedParseInput", err = e.to_string())))? |
| 37 | }; |
| 38 | |
| 39 | let filters = &update_list.updates; |
| 40 | |
| 41 | // Initialize COM |
| 42 | let com_initialized = unsafe { |
| 43 | CoInitializeEx(Some(std::ptr::null()), COINIT_MULTITHREADED).is_ok() |
| 44 | }; |
| 45 | |
| 46 | let result = unsafe { |
| 47 | // Create update session |
| 48 | let update_session: IUpdateSession = CoCreateInstance( |
| 49 | &UpdateSession, |
| 50 | None, |
| 51 | CLSCTX_INPROC_SERVER, |
| 52 | )?; |
| 53 | |
| 54 | // Create update searcher |
| 55 | let searcher = update_session.CreateUpdateSearcher()?; |
| 56 | |
| 57 | // Use the broadest search criteria to get all updates once |
| 58 | // We'll filter in-memory for each filter in the array |
| 59 | let search_result = searcher.Search(&BSTR::from("IsInstalled=0 or IsInstalled=1"))?; |
| 60 | |
| 61 | // Get updates collection |
| 62 | let updates = search_result.Updates()?; |
| 63 | let count = updates.Count()?; |
| 64 | |
| 65 | // Use HashSet to track unique update IDs (for OR logic across filters) |
| 66 | let mut matched_update_ids: HashSet<String> = HashSet::new(); |
| 67 | let mut all_found_updates: Vec<UpdateInfo> = Vec::new(); |
| 68 | |
| 69 | // Process each filter in the array (OR logic between filters) |
| 70 | for (filter_index, filter) in filters.iter().enumerate() { |
| 71 | let mut filter_found_match = false; |
| 72 |
no test coverage detected