mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-17 10:09:05 +02:00
Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
174 lines
6.2 KiB
Go
174 lines
6.2 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
// Copyright The Prometheus Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//go:build windows && (amd64 || arm64)
|
|
|
|
// Package wuapi provides the Windows Update COM interfaces needed for update searches and metadata.
|
|
package wuapi
|
|
|
|
import (
|
|
"iter"
|
|
|
|
"github.com/prometheus-community/windows_exporter/internal/ole"
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
// Native method slots from wuapi.h, including inherited IDispatch methods.
|
|
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/
|
|
const (
|
|
updateSessionPutApplicationID = 8
|
|
updateSessionCreateSearcher = 12
|
|
updateSessionPutLocale = 16 // IUpdateSession2
|
|
updateSearcherSearch = 19
|
|
updateSearcherPutOnline = 21
|
|
updateSearcherHistoryCount = 22
|
|
searchResultUpdates = 9
|
|
updateCollectionItem = 7
|
|
updateCollectionCount = 10
|
|
updateTitle = 7
|
|
updateCategories = 11
|
|
updateIdentity = 19
|
|
updateDeploymentTime = 30
|
|
updateSeverity = 34
|
|
updateDeploymentAction = 48
|
|
identityRevision = 7
|
|
identityUpdateID = 8
|
|
categoryCollectionItem = 7
|
|
categoryCollectionCount = 9
|
|
categoryName = 7
|
|
categoryOrder = 12
|
|
)
|
|
|
|
type (
|
|
UpdateSession struct{ ole.Object } // IUpdateSession2
|
|
UpdateSearcher struct{ ole.Object }
|
|
SearchResult struct{ ole.Object }
|
|
Update struct{ ole.Object }
|
|
UpdateIdentity struct{ ole.Object }
|
|
Category struct{ ole.Object }
|
|
)
|
|
|
|
func NewUpdateSession() (*UpdateSession, error) {
|
|
return ole.Create[UpdateSession](
|
|
windows.GUID{Data1: 0x4cb43d7f, Data2: 0x7eee, Data3: 0x4906, Data4: [8]byte{0x86, 0x98, 0x60, 0xda, 0x1c, 0x38, 0xf2, 0xfe}},
|
|
windows.GUID{Data1: 0x91caf7b0, Data2: 0xeb23, Data3: 0x49ed, Data4: [8]byte{0x99, 0x37, 0xc5, 0x2d, 0x81, 0x7f, 0x46, 0xf7}},
|
|
)
|
|
}
|
|
|
|
func (s *UpdateSession) SetUserLocale(locale uint32) error {
|
|
return s.Put(updateSessionPutLocale, uintptr(locale))
|
|
}
|
|
|
|
func (s *UpdateSession) SetClientApplicationID(id string) error {
|
|
return s.PutString(updateSessionPutApplicationID, id)
|
|
}
|
|
|
|
func (s *UpdateSession) CreateUpdateSearcher() (*UpdateSearcher, error) {
|
|
return s.GetObject[UpdateSearcher](updateSessionCreateSearcher)
|
|
}
|
|
|
|
func (s *UpdateSearcher) SetOnline(online bool) error {
|
|
var value uintptr
|
|
// VARIANT_TRUE is a signed 16-bit -1.
|
|
if online {
|
|
value = 0xffff
|
|
}
|
|
|
|
return s.Put(updateSearcherPutOnline, value)
|
|
}
|
|
|
|
func (s *UpdateSearcher) GetTotalHistoryCount() (int32, error) {
|
|
return s.Get[int32](updateSearcherHistoryCount)
|
|
}
|
|
|
|
func (s *UpdateSearcher) Search(criteria string) (*SearchResult, error) {
|
|
return s.GetObjectStringArg[SearchResult](updateSearcherSearch, criteria)
|
|
}
|
|
|
|
func (s *SearchResult) Updates() (*UpdateCollection, error) {
|
|
return s.GetObject[UpdateCollection](searchResultUpdates)
|
|
}
|
|
|
|
func (u *Update) Title() (string, error) { return u.String(updateTitle) }
|
|
func (u *Update) MsrcSeverity() (string, error) { return u.String(updateSeverity) }
|
|
func (u *Update) Categories() (*CategoryCollection, error) {
|
|
return u.GetObject[CategoryCollection](updateCategories)
|
|
}
|
|
|
|
func (u *Update) Identity() (*UpdateIdentity, error) {
|
|
return u.GetObject[UpdateIdentity](updateIdentity)
|
|
}
|
|
|
|
func (u *Update) LastDeploymentChangeTime() (ole.DATE, error) {
|
|
return u.Get[ole.DATE](updateDeploymentTime)
|
|
}
|
|
|
|
// DeploymentAction is the WUA DeploymentAction enumeration.
|
|
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-deploymentaction
|
|
type DeploymentAction int32
|
|
|
|
const (
|
|
DeploymentActionNone DeploymentAction = 0
|
|
DeploymentActionInstallation DeploymentAction = 1
|
|
DeploymentActionUninstallation DeploymentAction = 2
|
|
DeploymentActionDetection DeploymentAction = 3
|
|
DeploymentActionOptionalInstallation DeploymentAction = 4
|
|
)
|
|
|
|
func (u *Update) DeploymentAction() (DeploymentAction, error) {
|
|
return u.Get[DeploymentAction](updateDeploymentAction)
|
|
}
|
|
|
|
func (i *UpdateIdentity) UpdateID() (string, error) { return i.String(identityUpdateID) }
|
|
func (i *UpdateIdentity) RevisionNumber() (int32, error) { return i.Get[int32](identityRevision) }
|
|
func (c *Category) Name() (string, error) { return c.String(categoryName) }
|
|
func (c *Category) Order() (int32, error) { return c.Get[int32](categoryOrder) }
|
|
|
|
// UpdateCollection uses IUpdateCollection's native layout and zero-based indices.
|
|
type UpdateCollection struct{ ole.Object }
|
|
|
|
func (c *UpdateCollection) count() (int32, error) {
|
|
return c.Get[int32](updateCollectionCount)
|
|
}
|
|
|
|
func (c *UpdateCollection) item(index int32) (*Update, error) {
|
|
return c.GetObjectArg[Update](updateCollectionItem, uintptr(index))
|
|
}
|
|
|
|
// All yields borrowed updates, valid only in the loop body. Callers must not
|
|
// release or retain them. Item errors can be skipped by continuing the loop.
|
|
// The collection itself remains owned by the caller and must be released.
|
|
func (c *UpdateCollection) All() iter.Seq2[*Update, error] {
|
|
return ole.BorrowedItems(c.count, c.item, func(item *Update) { item.Release() })
|
|
}
|
|
|
|
// CategoryCollection uses ICategoryCollection's distinct native count slot.
|
|
type CategoryCollection struct{ ole.Object }
|
|
|
|
func (c *CategoryCollection) count() (int32, error) {
|
|
return c.Get[int32](categoryCollectionCount)
|
|
}
|
|
|
|
func (c *CategoryCollection) item(index int32) (*Category, error) {
|
|
return c.GetObjectArg[Category](categoryCollectionItem, uintptr(index))
|
|
}
|
|
|
|
// All yields borrowed categories, valid only in the loop body. Callers must not
|
|
// release or retain them. Item errors can be skipped by continuing the loop.
|
|
// The collection itself remains owned by the caller and must be released.
|
|
func (c *CategoryCollection) All() iter.Seq2[*Category, error] {
|
|
return ole.BorrowedItems(c.count, c.item, func(item *Category) { item.Release() })
|
|
}
|