| 12 | use crate::windows_update::types::{UpdateList, extract_update_info}; |
| 13 | |
| 14 | pub fn handle_get(input: &str) -> Result<String> { |
| 15 | // Parse input as UpdateList |
| 16 | let update_list: UpdateList = serde_json::from_str(input) |
| 17 | .map_err(|e| Error::new(E_INVALIDARG, t!("get.failedParseInput", err = e.to_string())))?; |
| 18 | |
| 19 | if update_list.updates.is_empty() { |
| 20 | return Err(Error::new(E_INVALIDARG, t!("get.updatesArrayEmpty"))); |
| 21 | } |
| 22 | |
| 23 | // Initialize COM |
| 24 | let com_initialized = unsafe { |
| 25 | CoInitializeEx(Some(std::ptr::null()), COINIT_MULTITHREADED).is_ok() |
| 26 | }; |
| 27 | |
| 28 | let result = unsafe { |
| 29 | // Create update session using the proper interface |
| 30 | let update_session: IUpdateSession = CoCreateInstance( |
| 31 | &UpdateSession, |
| 32 | None, |
| 33 | CLSCTX_INPROC_SERVER, |
| 34 | )?; |
| 35 | |
| 36 | // Create update searcher |
| 37 | let searcher = update_session.CreateUpdateSearcher()?; |
| 38 | |
| 39 | // Search for updates |
| 40 | let search_result = searcher.Search(&BSTR::from("IsInstalled=0 or IsInstalled=1"))?; |
| 41 | |
| 42 | // Get updates collection |
| 43 | let all_updates = search_result.Updates()?; |
| 44 | let count = all_updates.Count()?; |
| 45 | |
| 46 | // Process each input filter |
| 47 | let mut matched_updates = Vec::new(); |
| 48 | |
| 49 | for update_input in &update_list.updates { |
| 50 | // Validate that at least one search criterion is provided |
| 51 | if update_input.title.is_none() |
| 52 | && update_input.id.is_none() |
| 53 | && update_input.kb_article_ids.is_none() |
| 54 | && update_input.is_installed.is_none() |
| 55 | && update_input.update_type.is_none() |
| 56 | && update_input.msrc_severity.is_none() { |
| 57 | return Err(Error::new(E_INVALIDARG, t!("get.atLeastOneCriterionRequired"))); |
| 58 | } |
| 59 | |
| 60 | // Find the update matching ALL provided criteria (logical AND) |
| 61 | let mut found_update = None; |
| 62 | let mut matching_updates: Vec<IUpdate> = Vec::new(); |
| 63 | for i in 0..count { |
| 64 | let update = all_updates.get_Item(i)?; |
| 65 | |
| 66 | // Check title match |
| 67 | if let Some(search_title) = &update_input.title { |
| 68 | let title = update.Title()?.to_string(); |
| 69 | if !title.eq_ignore_ascii_case(search_title) { |
| 70 | continue; // Title doesn't match, skip this update |
| 71 | } |