Watch
1
0
Fork
You've already forked RedFlag
0

chore: add windowsupdate COM interface stubs and update third-party licenses

This commit is contained in:
Fimeg 2026-05-21 13:48:42 -04:00
commit 3c510d51c0
29 changed files with 2200 additions and 35 deletions

View file

@ -5,11 +5,11 @@ This document lists the third-party components and their licenses that are inclu
## Windows Update Package (Apache 2.0)
**Package**: `github.com/ceshihao/windowsupdate`
**Version**: Included as vendored code in `aggregator-agent/pkg/windowsupdate/`
**Version**: Vendored from master branch (Jan 2026 refactor), in `agent/pkg/windowsupdate/`
**License**: Apache License 2.0
**Copyright**: Copyright 2022 Zheng Dayu
**Source**: https://github.com/ceshihao/windowsupdate
**License File**: https://github.com/ceshihao/windowsupdate/blob/main/LICENSE
**License File**: https://github.com/ceshihao/windowsupdate/blob/master/LICENSE
### License Text

View file

@ -23,3 +23,132 @@ const (
OperationResultCodeOrcFailed
OperationResultCodeOrcAborted
)
// DeploymentAction defines the action for which an update is eligible.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-deploymentaction
const (
DeploymentActionDaNone int32 = iota
DeploymentActionDaDetection
DeploymentActionDaInstallation
DeploymentActionDaUninstallation
DeploymentActionDaOptionalInstallation
)
// DownloadPriority defines the priority of a download.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-downloadpriority
const (
DownloadPriorityDpLow int32 = 1
DownloadPriorityDpNormal int32 = 2
DownloadPriorityDpHigh int32 = 3
)
// InstallationImpact defines the impact of installing an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-installationimpact
const (
InstallationImpactIiNormal int32 = iota
InstallationImpactIiMinor
InstallationImpactIiRequiresExclusiveHandling
)
// InstallationRebootBehavior defines the restart behavior of an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-installationrebootbehavior
const (
InstallationRebootBehaviorIrbNeverReboots int32 = iota
InstallationRebootBehaviorIrbAlwaysRequiresReboot
InstallationRebootBehaviorIrbCanRequestReboot
)
// UpdateOperation defines the operation for which an update is being installed or uninstalled.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-updateoperation
const (
UpdateOperationUoInstallation int32 = 1
UpdateOperationUoUninstallation int32 = 2
)
// UpdateExceptionContext defines the context in which an IUpdateException object can be provided.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-updateexceptioncontext
const (
UpdateExceptionContextUecGeneral int32 = iota + 1
UpdateExceptionContextUecWindowsDriver
UpdateExceptionContextUecWindowsInstaller
UpdateExceptionContextUecSearchIncomplete
)
// ServerSelection defines the update server that is used for a search or download operation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-serverselection
const (
ServerSelectionSsDefault int32 = iota // Use the default server.
ServerSelectionSsManagedServer // Use the managed server (WSUS).
ServerSelectionSsWindowsUpdate // Use Windows Update.
ServerSelectionSsOthers // Use a non-Microsoft server.
)
// AutomaticUpdatesNotificationLevel defines the notification level for automatic updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-automaticupdatesnotificationlevel
const (
AutomaticUpdatesNotificationLevelAunlNotConfigured int32 = iota // Not configured.
AutomaticUpdatesNotificationLevelAunlDisabled // Disabled.
AutomaticUpdatesNotificationLevelAunlNotifyBeforeDownload // Notify before download.
AutomaticUpdatesNotificationLevelAunlNotifyBeforeInstallation // Notify before installation.
AutomaticUpdatesNotificationLevelAunlScheduledInstallation // Scheduled installation.
)
// AutomaticUpdatesScheduledInstallationDay defines the days of the week for scheduled automatic updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-automaticupdatesscheduledinstallationday
const (
AutomaticUpdatesScheduledInstallationDayAuisdEveryDay int32 = iota // Every day.
AutomaticUpdatesScheduledInstallationDayAuisdEverySunday // Every Sunday.
AutomaticUpdatesScheduledInstallationDayAuisdEveryMonday // Every Monday.
AutomaticUpdatesScheduledInstallationDayAuisdEveryTuesday // Every Tuesday.
AutomaticUpdatesScheduledInstallationDayAuisdEveryWednesday // Every Wednesday.
AutomaticUpdatesScheduledInstallationDayAuisdEveryThursday // Every Thursday.
AutomaticUpdatesScheduledInstallationDayAuisdEveryFriday // Every Friday.
AutomaticUpdatesScheduledInstallationDayAuisdEverySaturday // Every Saturday.
)
// DownloadPhase defines the phase of the download.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-downloadphase
const (
DownloadPhaseInitializing int32 = iota + 1
DownloadPhaseDownloading
DownloadPhaseVerifying
)
// AutoDownload defines auto download behavior for IUpdate5.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-autodownloadmode
const (
AutoDownloadModeForbidAutoDownload int32 = iota
AutoDownloadModeAllowAutoDownload
)
// AutoSelection defines auto selection behavior for IUpdate5.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-autoselectionmode
const (
AutoSelectionModeLetWindowsUpdateDecide int32 = iota
AutoSelectionModeAutoSelectIfDownloaded
AutoSelectionModeNeverAutoSelect
AutoSelectionModeAlwaysAutoSelect
)
// UpdateServiceRegistrationState defines the state of a service registration.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-updateserviceregistrationstate
const (
UpdateServiceRegistrationStateNotRegistered int32 = iota + 1
UpdateServiceRegistrationStateRegistrationPending
UpdateServiceRegistrationStateRegistered
)
// AddServiceFlag defines flags for AddService2.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-addserviceflag
const (
AddServiceFlagAsfAllowPendingRegistration int32 = 1
AddServiceFlagAsfAllowOnlineRegistration int32 = 2
AddServiceFlagAsfRegisterServiceWithAU int32 = 4
)
// UpdateType defines the type of an update.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-updatetype
const (
UpdateTypeSoftware int32 = iota + 1
UpdateTypeDriver
)

View file

@ -0,0 +1,143 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"time"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IAutomaticUpdates contains the functionality of Automatic Updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iautomaticupdates
type IAutomaticUpdates struct {
disp *ole.IDispatch
ServiceEnabled bool
}
// NewAutomaticUpdates creates a new IAutomaticUpdates instance.
func NewAutomaticUpdates() (*IAutomaticUpdates, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.AutoUpdate")
if err != nil {
return nil, err
}
disp, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
return toIAutomaticUpdates(disp)
}
func toIAutomaticUpdates(autoUpdatesDisp *ole.IDispatch) (*IAutomaticUpdates, error) {
var err error
iAutoUpdates := &IAutomaticUpdates{
disp: autoUpdatesDisp,
}
if iAutoUpdates.ServiceEnabled, err = toBoolErr(oleutil.GetProperty(autoUpdatesDisp, "ServiceEnabled")); err != nil {
return nil, err
}
return iAutoUpdates, nil
}
// DetectNow begins detection of updates.
// The DetectNow method returns immediately without waiting for the detection to complete.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdates-detectnow
func (a *IAutomaticUpdates) DetectNow() error {
_, err := oleutil.CallMethod(a.disp, "DetectNow")
return err
}
// EnableService enables all the components that Automatic Updates requires.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdates-enableservice
func (a *IAutomaticUpdates) EnableService() error {
_, err := oleutil.CallMethod(a.disp, "EnableService")
if err != nil {
return err
}
a.ServiceEnabled = true
return nil
}
// Pause pauses automatic updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdates-pause
func (a *IAutomaticUpdates) Pause() error {
_, err := oleutil.CallMethod(a.disp, "Pause")
return err
}
// Resume restarts automatic updates if paused.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdates-resume
func (a *IAutomaticUpdates) Resume() error {
_, err := oleutil.CallMethod(a.disp, "Resume")
return err
}
// ShowSettingsDialog displays a dialog box that contains settings for Automatic Updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdates-showsettingsdialog
func (a *IAutomaticUpdates) ShowSettingsDialog() error {
_, err := oleutil.CallMethod(a.disp, "ShowSettingsDialog")
return err
}
// GetSettings retrieves the configuration settings for Automatic Updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdates-get_settings
func (a *IAutomaticUpdates) GetSettings() (*IAutomaticUpdatesSettings, error) {
settingsDisp, err := toIDispatchErr(oleutil.GetProperty(a.disp, "Settings"))
if err != nil {
return nil, err
}
return toIAutomaticUpdatesSettings(settingsDisp)
}
// GetResults retrieves the results of the last Automatic Updates search. (IAutomaticUpdates2)
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdates2-get_results
func (a *IAutomaticUpdates) GetResults() (*IAutomaticUpdatesResults, error) {
resultsDisp, err := toIDispatchErr(oleutil.GetProperty(a.disp, "Results"))
if err != nil {
return nil, err
}
return toIAutomaticUpdatesResults(resultsDisp)
}
// IAutomaticUpdatesResults contains the read-only properties that describe Automatic Updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iautomaticupdatesresults
type IAutomaticUpdatesResults struct {
disp *ole.IDispatch
LastInstallationSuccessDate *time.Time
LastSearchSuccessDate *time.Time
}
func toIAutomaticUpdatesResults(disp *ole.IDispatch) (*IAutomaticUpdatesResults, error) {
if disp == nil {
return nil, nil
}
var err error
r := &IAutomaticUpdatesResults{disp: disp}
if r.LastInstallationSuccessDate, err = toTimeErr(oleutil.GetProperty(disp, "LastInstallationSuccessDate")); err != nil {
return nil, err
}
if r.LastSearchSuccessDate, err = toTimeErr(oleutil.GetProperty(disp, "LastSearchSuccessDate")); err != nil {
return nil, err
}
return r, nil
}

View file

@ -0,0 +1,124 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IAutomaticUpdatesSettings contains the settings that are available in Automatic Updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iautomaticupdatessettings
type IAutomaticUpdatesSettings struct {
disp *ole.IDispatch
NotificationLevel int32 // AutomaticUpdatesNotificationLevel enum
ReadOnly bool
Required bool
ScheduledInstallationDay int32 // AutomaticUpdatesScheduledInstallationDay enum (not supported on Windows 8+)
ScheduledInstallationTime int32 // Hour of the day (0-23) (not supported on Windows 8+)
}
func toIAutomaticUpdatesSettings(settingsDisp *ole.IDispatch) (*IAutomaticUpdatesSettings, error) {
var err error
iSettings := &IAutomaticUpdatesSettings{
disp: settingsDisp,
}
if iSettings.NotificationLevel, err = toInt32Err(oleutil.GetProperty(settingsDisp, "NotificationLevel")); err != nil {
return nil, err
}
if iSettings.ReadOnly, err = toBoolErr(oleutil.GetProperty(settingsDisp, "ReadOnly")); err != nil {
return nil, err
}
if iSettings.Required, err = toBoolErr(oleutil.GetProperty(settingsDisp, "Required")); err != nil {
return nil, err
}
if iSettings.ScheduledInstallationDay, err = toInt32Err(oleutil.GetProperty(settingsDisp, "ScheduledInstallationDay")); err != nil {
return nil, err
}
if iSettings.ScheduledInstallationTime, err = toInt32Err(oleutil.GetProperty(settingsDisp, "ScheduledInstallationTime")); err != nil {
return nil, err
}
return iSettings, nil
}
// Refresh reads the latest Automatic Updates settings.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdatessettings-refresh
func (s *IAutomaticUpdatesSettings) Refresh() error {
_, err := oleutil.CallMethod(s.disp, "Refresh")
if err != nil {
return err
}
// Re-read properties after refresh
refreshed, err := toIAutomaticUpdatesSettings(s.disp)
if err != nil {
return err
}
s.NotificationLevel = refreshed.NotificationLevel
s.ReadOnly = refreshed.ReadOnly
s.Required = refreshed.Required
s.ScheduledInstallationDay = refreshed.ScheduledInstallationDay
s.ScheduledInstallationTime = refreshed.ScheduledInstallationTime
return nil
}
// Save applies the current Automatic Updates settings.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdatessettings-save
func (s *IAutomaticUpdatesSettings) Save() error {
_, err := oleutil.CallMethod(s.disp, "Save")
return err
}
// PutNotificationLevel sets the notification level for Automatic Updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdatessettings-put_notificationlevel
func (s *IAutomaticUpdatesSettings) PutNotificationLevel(level int32) error {
_, err := oleutil.PutProperty(s.disp, "NotificationLevel", level)
if err != nil {
return err
}
s.NotificationLevel = level
return nil
}
// PutScheduledInstallationDay sets the scheduled installation day.
// Note: Not supported on Windows 8 and later.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdatessettings-put_scheduledinstallationday
func (s *IAutomaticUpdatesSettings) PutScheduledInstallationDay(day int32) error {
_, err := oleutil.PutProperty(s.disp, "ScheduledInstallationDay", day)
if err != nil {
return err
}
s.ScheduledInstallationDay = day
return nil
}
// PutScheduledInstallationTime sets the scheduled installation time (hour of day, 0-23).
// Note: Not supported on Windows 8 and later.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iautomaticupdatessettings-put_scheduledinstallationtime
func (s *IAutomaticUpdatesSettings) PutScheduledInstallationTime(hour int32) error {
_, err := oleutil.PutProperty(s.disp, "ScheduledInstallationTime", hour)
if err != nil {
return err
}
s.ScheduledInstallationTime = hour
return nil
}

View file

@ -98,29 +98,33 @@ func toICategory(categoryDisp *ole.IDispatch) (*ICategory, error) {
return nil, err
}
// parentDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Parent"))
// if err != nil {
// return nil, err
// }
// if parentDisp != nil {
// if iCategory.Parent, err = toICategory(parentDisp); err != nil {
// return nil, err
// }
// }
/*
parentDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Parent"))
if err != nil {
return nil, err
}
if parentDisp != nil {
if iCategory.Parent, err = toICategory(parentDisp); err != nil {
return nil, err
}
}
*/
if iCategory.Type, err = toStringErr(oleutil.GetProperty(categoryDisp, "Type")); err != nil {
return nil, err
}
// updatesDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Updates"))
// if err != nil {
// return nil, err
// }
// if updatesDisp != nil {
// if iCategory.Updates, err = toIUpdates(updatesDisp); err != nil {
// return nil, err
// }
// }
/*
updatesDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Updates"))
if err != nil {
return nil, err
}
if updatesDisp != nil {
if iCategory.Updates, err = toIUpdates(updatesDisp); err != nil {
return nil, err
}
}
*/
return iCategory, nil
}

View file

@ -0,0 +1,77 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IDownloadJob contains properties and methods that are available to a download operation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-idownloadjob
type IDownloadJob struct {
disp *ole.IDispatch
AsyncState interface{}
IsCompleted bool
Updates []*IUpdate
}
func toIDownloadJob(disp *ole.IDispatch) (*IDownloadJob, error) {
if disp == nil {
return nil, nil
}
var err error
j := &IDownloadJob{disp: disp}
if j.IsCompleted, err = toBoolErr(oleutil.GetProperty(disp, "IsCompleted")); err != nil {
return nil, err
}
updatesDisp, err := toIDispatchErr(oleutil.GetProperty(disp, "Updates"))
if err != nil {
return nil, err
}
if updatesDisp != nil {
if j.Updates, err = toIUpdates(updatesDisp); err != nil {
return nil, err
}
}
return j, nil
}
// CleanUp releases the resources held by the download job.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-idownloadjob-cleanup
func (j *IDownloadJob) CleanUp() error {
_, err := oleutil.CallMethod(j.disp, "CleanUp")
return err
}
// RequestAbort requests that the download job be canceled.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-idownloadjob-requestabort
func (j *IDownloadJob) RequestAbort() error {
_, err := oleutil.CallMethod(j.disp, "RequestAbort")
return err
}
// GetProgress returns the current progress of the download.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-idownloadjob-getprogress
func (j *IDownloadJob) GetProgress() (*IDownloadProgress, error) {
progressDisp, err := toIDispatchErr(oleutil.CallMethod(j.disp, "GetProgress"))
if err != nil {
return nil, err
}
return toIDownloadProgress(progressDisp)
}

View file

@ -0,0 +1,86 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IDownloadProgress represents the progress of an asynchronous download operation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-idownloadprogress
type IDownloadProgress struct {
disp *ole.IDispatch
CurrentUpdateBytesDownloaded int64
CurrentUpdateBytesToDownload int64
CurrentUpdateDownloadPhase int32 // DownloadPhase enum
CurrentUpdateIndex int32
CurrentUpdatePercentComplete int32
PercentComplete int32
TotalBytesDownloaded int64
TotalBytesToDownload int64
}
func toIDownloadProgress(disp *ole.IDispatch) (*IDownloadProgress, error) {
if disp == nil {
return nil, nil
}
var err error
p := &IDownloadProgress{disp: disp}
if p.CurrentUpdateBytesDownloaded, err = toInt64Err(oleutil.GetProperty(disp, "CurrentUpdateBytesDownloaded")); err != nil {
return nil, err
}
if p.CurrentUpdateBytesToDownload, err = toInt64Err(oleutil.GetProperty(disp, "CurrentUpdateBytesToDownload")); err != nil {
return nil, err
}
if p.CurrentUpdateDownloadPhase, err = toInt32Err(oleutil.GetProperty(disp, "CurrentUpdateDownloadPhase")); err != nil {
return nil, err
}
if p.CurrentUpdateIndex, err = toInt32Err(oleutil.GetProperty(disp, "CurrentUpdateIndex")); err != nil {
return nil, err
}
if p.CurrentUpdatePercentComplete, err = toInt32Err(oleutil.GetProperty(disp, "CurrentUpdatePercentComplete")); err != nil {
return nil, err
}
if p.PercentComplete, err = toInt32Err(oleutil.GetProperty(disp, "PercentComplete")); err != nil {
return nil, err
}
if p.TotalBytesDownloaded, err = toInt64Err(oleutil.GetProperty(disp, "TotalBytesDownloaded")); err != nil {
return nil, err
}
if p.TotalBytesToDownload, err = toInt64Err(oleutil.GetProperty(disp, "TotalBytesToDownload")); err != nil {
return nil, err
}
return p, nil
}
// GetUpdateResult returns the result of the download for a specified update.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-idownloadprogress-getupdateresult
func (p *IDownloadProgress) GetUpdateResult(updateIndex int32) (*IUpdateDownloadResult, error) {
resultDisp, err := toIDispatchErr(oleutil.CallMethod(p.disp, "GetUpdateResult", updateIndex))
if err != nil {
return nil, err
}
return toIUpdateDownloadResult(resultDisp)
}

View file

@ -15,6 +15,7 @@ package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IImageInformation contains information about a localized image that is associated with an update or a category.
@ -28,6 +29,26 @@ type IImageInformation struct {
}
func toIImageInformation(imageInformationDisp *ole.IDispatch) (*IImageInformation, error) {
// TODO
return nil, nil
var err error
iImageInformation := &IImageInformation{
disp: imageInformationDisp,
}
if iImageInformation.AltText, err = toStringErr(oleutil.GetProperty(imageInformationDisp, "AltText")); err != nil {
return nil, err
}
if iImageInformation.Height, err = toInt64Err(oleutil.GetProperty(imageInformationDisp, "Height")); err != nil {
return nil, err
}
if iImageInformation.Source, err = toStringErr(oleutil.GetProperty(imageInformationDisp, "Source")); err != nil {
return nil, err
}
if iImageInformation.Width, err = toInt64Err(oleutil.GetProperty(imageInformationDisp, "Width")); err != nil {
return nil, err
}
return iImageInformation, nil
}

View file

@ -15,6 +15,7 @@ package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IInstallationBehavior represents the installation and uninstallation options of an update.
@ -28,6 +29,26 @@ type IInstallationBehavior struct {
}
func toIInstallationBehavior(installationBehaviorDisp *ole.IDispatch) (*IInstallationBehavior, error) {
// TODO
return nil, nil
var err error
iInstallationBehavior := &IInstallationBehavior{
disp: installationBehaviorDisp,
}
if iInstallationBehavior.CanRequestUserInput, err = toBoolErr(oleutil.GetProperty(installationBehaviorDisp, "CanRequestUserInput")); err != nil {
return nil, err
}
if iInstallationBehavior.Impact, err = toInt32Err(oleutil.GetProperty(installationBehaviorDisp, "Impact")); err != nil {
return nil, err
}
if iInstallationBehavior.RebootBehavior, err = toInt32Err(oleutil.GetProperty(installationBehaviorDisp, "RebootBehavior")); err != nil {
return nil, err
}
if iInstallationBehavior.RequiresNetworkConnectivity, err = toBoolErr(oleutil.GetProperty(installationBehaviorDisp, "RequiresNetworkConnectivity")); err != nil {
return nil, err
}
return iInstallationBehavior, nil
}

View file

@ -0,0 +1,77 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IInstallationJob contains properties and methods that are available to an installation operation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iinstallationjob
type IInstallationJob struct {
disp *ole.IDispatch
AsyncState interface{}
IsCompleted bool
Updates []*IUpdate
}
func toIInstallationJob(disp *ole.IDispatch) (*IInstallationJob, error) {
if disp == nil {
return nil, nil
}
var err error
j := &IInstallationJob{disp: disp}
if j.IsCompleted, err = toBoolErr(oleutil.GetProperty(disp, "IsCompleted")); err != nil {
return nil, err
}
updatesDisp, err := toIDispatchErr(oleutil.GetProperty(disp, "Updates"))
if err != nil {
return nil, err
}
if updatesDisp != nil {
if j.Updates, err = toIUpdates(updatesDisp); err != nil {
return nil, err
}
}
return j, nil
}
// CleanUp releases the resources held by the installation job.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iinstallationjob-cleanup
func (j *IInstallationJob) CleanUp() error {
_, err := oleutil.CallMethod(j.disp, "CleanUp")
return err
}
// RequestAbort requests that the installation job be canceled.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iinstallationjob-requestabort
func (j *IInstallationJob) RequestAbort() error {
_, err := oleutil.CallMethod(j.disp, "RequestAbort")
return err
}
// GetProgress returns the current progress of the installation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iinstallationjob-getprogress
func (j *IInstallationJob) GetProgress() (*IInstallationProgress, error) {
progressDisp, err := toIDispatchErr(oleutil.CallMethod(j.disp, "GetProgress"))
if err != nil {
return nil, err
}
return toIInstallationProgress(progressDisp)
}

View file

@ -0,0 +1,61 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IInstallationProgress represents the progress of an asynchronous installation operation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iinstallationprogress
type IInstallationProgress struct {
disp *ole.IDispatch
CurrentUpdateIndex int32
CurrentUpdatePercentComplete int32
PercentComplete int32
}
func toIInstallationProgress(disp *ole.IDispatch) (*IInstallationProgress, error) {
if disp == nil {
return nil, nil
}
var err error
p := &IInstallationProgress{disp: disp}
if p.CurrentUpdateIndex, err = toInt32Err(oleutil.GetProperty(disp, "CurrentUpdateIndex")); err != nil {
return nil, err
}
if p.CurrentUpdatePercentComplete, err = toInt32Err(oleutil.GetProperty(disp, "CurrentUpdatePercentComplete")); err != nil {
return nil, err
}
if p.PercentComplete, err = toInt32Err(oleutil.GetProperty(disp, "PercentComplete")); err != nil {
return nil, err
}
return p, nil
}
// GetUpdateResult returns the result of the installation for a specified update.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iinstallationprogress-getupdateresult
func (p *IInstallationProgress) GetUpdateResult(updateIndex int32) (*IUpdateInstallationResult, error) {
resultDisp, err := toIDispatchErr(oleutil.CallMethod(p.disp, "GetUpdateResult", updateIndex))
if err != nil {
return nil, err
}
return toIUpdateInstallationResult(resultDisp)
}

View file

@ -0,0 +1,56 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// ISearchJob contains properties and methods that are available to a search operation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-isearchjob
type ISearchJob struct {
disp *ole.IDispatch
AsyncState interface{}
IsCompleted bool
}
func toISearchJob(disp *ole.IDispatch) (*ISearchJob, error) {
if disp == nil {
return nil, nil
}
var err error
j := &ISearchJob{disp: disp}
if j.IsCompleted, err = toBoolErr(oleutil.GetProperty(disp, "IsCompleted")); err != nil {
return nil, err
}
return j, nil
}
// CleanUp releases the resources held by the search job.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-isearchjob-cleanup
func (j *ISearchJob) CleanUp() error {
_, err := oleutil.CallMethod(j.disp, "CleanUp")
return err
}
// RequestAbort requests that the search job be canceled.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-isearchjob-requestabort
func (j *ISearchJob) RequestAbort() error {
_, err := oleutil.CallMethod(j.disp, "RequestAbort")
return err
}

View file

@ -1,3 +1,16 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
@ -5,7 +18,104 @@ import (
"github.com/go-ole/go-ole/oleutil"
)
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-istringcollection
// IStringCollection represents a collection of strings.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-istringcollection
type IStringCollection struct {
disp *ole.IDispatch
Count int32
ReadOnly bool
}
// NewStringCollection creates a new empty IStringCollection.
func NewStringCollection() (*IStringCollection, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.StringColl")
if err != nil {
return nil, err
}
disp, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
return toIStringCollection(disp)
}
func toIStringCollection(disp *ole.IDispatch) (*IStringCollection, error) {
if disp == nil {
return nil, nil
}
var err error
sc := &IStringCollection{disp: disp}
if sc.Count, err = toInt32Err(oleutil.GetProperty(disp, "Count")); err != nil {
return nil, err
}
if sc.ReadOnly, err = toBoolErr(oleutil.GetProperty(disp, "ReadOnly")); err != nil {
return nil, err
}
return sc, nil
}
// Item gets a string from the collection at the specified index.
func (sc *IStringCollection) Item(index int32) (string, error) {
return toStringErr(oleutil.GetProperty(sc.disp, "Item", index))
}
// Add adds a string to the collection.
func (sc *IStringCollection) Add(value string) (int32, error) {
result, err := oleutil.CallMethod(sc.disp, "Add", value)
if err != nil {
return 0, err
}
sc.Count++
return variantToInt32(result), nil
}
// Clear removes all items from the collection.
func (sc *IStringCollection) Clear() error {
_, err := oleutil.CallMethod(sc.disp, "Clear")
if err == nil {
sc.Count = 0
}
return err
}
// Insert inserts a string at the specified position.
func (sc *IStringCollection) Insert(index int32, value string) error {
_, err := oleutil.CallMethod(sc.disp, "Insert", index, value)
if err == nil {
sc.Count++
}
return err
}
// RemoveAt removes the item at the specified index.
func (sc *IStringCollection) RemoveAt(index int32) error {
_, err := oleutil.CallMethod(sc.disp, "RemoveAt", index)
if err == nil {
sc.Count--
}
return err
}
// ToSlice converts the collection to a Go string slice.
func (sc *IStringCollection) ToSlice() ([]string, error) {
result := make([]string, sc.Count)
for i := int32(0); i < sc.Count; i++ {
str, err := sc.Item(i)
if err != nil {
return nil, err
}
result[i] = str
}
return result, nil
}
// iStringCollectionToStringArrayErr is a helper function for backward compatibility.
func iStringCollectionToStringArrayErr(disp *ole.IDispatch, err error) ([]string, error) {
if err != nil {
return nil, err

View file

@ -0,0 +1,59 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// ISystemInformation contains information about the specified computer.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-isysteminformation
type ISystemInformation struct {
disp *ole.IDispatch
OemHardwareSupportLink string
RebootRequired bool
}
// NewSystemInformation creates a new ISystemInformation instance.
func NewSystemInformation() (*ISystemInformation, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.SystemInfo")
if err != nil {
return nil, err
}
disp, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
return toISystemInformation(disp)
}
func toISystemInformation(systemInfoDisp *ole.IDispatch) (*ISystemInformation, error) {
var err error
iSystemInformation := &ISystemInformation{
disp: systemInfoDisp,
}
if iSystemInformation.OemHardwareSupportLink, err = toStringErr(oleutil.GetProperty(systemInfoDisp, "OemHardwareSupportLink")); err != nil {
return nil, err
}
if iSystemInformation.RebootRequired, err = toBoolErr(oleutil.GetProperty(systemInfoDisp, "RebootRequired")); err != nil {
return nil, err
}
return iSystemInformation, nil
}

View file

@ -65,6 +65,17 @@ type IUpdate struct {
UninstallationBehavior *IInstallationBehavior
UninstallationNotes string
UninstallationSteps []string
// IUpdate2 properties
CveIDs []string // CVE IDs associated with the update
IsPresent bool // Indicates if the update is present on the computer
RebootRequired bool // Indicates if a reboot is required
// IUpdate3 properties
BrowseOnly bool // Indicates whether update can be discovered only by browsing
// IUpdate4 properties
PerUser bool // Indicates whether this is a per-user update
// IUpdate5 properties
AutoDownload int32 // AutoDownload setting
AutoSelection int32 // AutoSelection setting
}
func toIUpdates(updatesDisp *ole.IDispatch) ([]*IUpdate, error) {
@ -334,6 +345,35 @@ func toIUpdate(updateDisp *ole.IDispatch) (*IUpdate, error) {
return nil, err
}
// IUpdate2 properties (may fail on older systems)
if cveIDs, err := iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateDisp, "CveIDs"))); err == nil {
iUpdate.CveIDs = cveIDs
}
if isPresent, err := toBoolErr(oleutil.GetProperty(updateDisp, "IsPresent")); err == nil {
iUpdate.IsPresent = isPresent
}
if rebootRequired, err := toBoolErr(oleutil.GetProperty(updateDisp, "RebootRequired")); err == nil {
iUpdate.RebootRequired = rebootRequired
}
// IUpdate3 properties
if browseOnly, err := toBoolErr(oleutil.GetProperty(updateDisp, "BrowseOnly")); err == nil {
iUpdate.BrowseOnly = browseOnly
}
// IUpdate4 properties
if perUser, err := toBoolErr(oleutil.GetProperty(updateDisp, "PerUser")); err == nil {
iUpdate.PerUser = perUser
}
// IUpdate5 properties
if autoDownload, err := toInt32Err(oleutil.GetProperty(updateDisp, "AutoDownload")); err == nil {
iUpdate.AutoDownload = autoDownload
}
if autoSelection, err := toInt32Err(oleutil.GetProperty(updateDisp, "AutoSelection")); err == nil {
iUpdate.AutoSelection = autoSelection
}
return iUpdate, nil
}
@ -361,3 +401,15 @@ func (iUpdate *IUpdate) AcceptEula() error {
_, err := oleutil.CallMethod(iUpdate.disp, "AcceptEula")
return err
}
// CopyToCache copies the contents of an update to the Windows Update Agent (WUA) cache. (IUpdate2)
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdate2-copytocache
func (iUpdate *IUpdate) CopyToCache(files *IStringCollection) error {
_, err := oleutil.CallMethod(iUpdate.disp, "CopyToCache", files.disp)
return err
}
// GetDispatch returns the underlying IDispatch interface.
func (iUpdate *IUpdate) GetDispatch() *ole.IDispatch {
return iUpdate.disp
}

View file

@ -0,0 +1,134 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateCollection represents a collection of updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatecollection
type IUpdateCollection struct {
disp *ole.IDispatch
Count int32
ReadOnly bool
}
// NewUpdateCollection creates a new empty IUpdateCollection.
func NewUpdateCollection() (*IUpdateCollection, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.UpdateColl")
if err != nil {
return nil, err
}
disp, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
return toIUpdateCollection2(disp)
}
func toIUpdateCollection2(disp *ole.IDispatch) (*IUpdateCollection, error) {
if disp == nil {
return nil, nil
}
var err error
uc := &IUpdateCollection{disp: disp}
if uc.Count, err = toInt32Err(oleutil.GetProperty(disp, "Count")); err != nil {
return nil, err
}
if uc.ReadOnly, err = toBoolErr(oleutil.GetProperty(disp, "ReadOnly")); err != nil {
return nil, err
}
return uc, nil
}
// Item gets an update from the collection at the specified index.
func (uc *IUpdateCollection) Item(index int32) (*IUpdate, error) {
itemDisp, err := toIDispatchErr(oleutil.GetProperty(uc.disp, "Item", index))
if err != nil {
return nil, err
}
return toIUpdate(itemDisp)
}
// Add adds an update to the collection.
func (uc *IUpdateCollection) Add(update *IUpdate) (int32, error) {
result, err := oleutil.CallMethod(uc.disp, "Add", update.disp)
if err != nil {
return 0, err
}
uc.Count++
return variantToInt32(result), nil
}
// Clear removes all items from the collection.
func (uc *IUpdateCollection) Clear() error {
_, err := oleutil.CallMethod(uc.disp, "Clear")
if err == nil {
uc.Count = 0
}
return err
}
// Copy creates a shallow copy of the collection.
func (uc *IUpdateCollection) Copy() (*IUpdateCollection, error) {
copyDisp, err := toIDispatchErr(oleutil.CallMethod(uc.disp, "Copy"))
if err != nil {
return nil, err
}
return toIUpdateCollection2(copyDisp)
}
// Insert inserts an update at the specified position.
func (uc *IUpdateCollection) Insert(index int32, update *IUpdate) error {
_, err := oleutil.CallMethod(uc.disp, "Insert", index, update.disp)
if err == nil {
uc.Count++
}
return err
}
// RemoveAt removes the item at the specified index.
func (uc *IUpdateCollection) RemoveAt(index int32) error {
_, err := oleutil.CallMethod(uc.disp, "RemoveAt", index)
if err == nil {
uc.Count--
}
return err
}
// ToSlice converts the collection to a Go slice.
func (uc *IUpdateCollection) ToSlice() ([]*IUpdate, error) {
result := make([]*IUpdate, uc.Count)
for i := int32(0); i < uc.Count; i++ {
update, err := uc.Item(i)
if err != nil {
return nil, err
}
result[i] = update
}
return result, nil
}
// GetDispatch returns the underlying IDispatch for use with other WUA methods.
func (uc *IUpdateCollection) GetDispatch() *ole.IDispatch {
return uc.disp
}

View file

@ -15,6 +15,7 @@ package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateDownloadContent represents the download content of an update.
@ -25,6 +26,37 @@ type IUpdateDownloadContent struct {
}
func toIUpdateDownloadContents(updateDownloadContentsDisp *ole.IDispatch) ([]*IUpdateDownloadContent, error) {
// TODO
return nil, nil
count, err := toInt32Err(oleutil.GetProperty(updateDownloadContentsDisp, "Count"))
if err != nil {
return nil, err
}
contents := make([]*IUpdateDownloadContent, 0, count)
for i := 0; i < int(count); i++ {
contentDisp, err := toIDispatchErr(oleutil.GetProperty(updateDownloadContentsDisp, "Item", i))
if err != nil {
return nil, err
}
content, err := toIUpdateDownloadContent(contentDisp)
if err != nil {
return nil, err
}
contents = append(contents, content)
}
return contents, nil
}
func toIUpdateDownloadContent(updateDownloadContentDisp *ole.IDispatch) (*IUpdateDownloadContent, error) {
var err error
iUpdateDownloadContent := &IUpdateDownloadContent{
disp: updateDownloadContentDisp,
}
if iUpdateDownloadContent.DownloadUrl, err = toStringErr(oleutil.GetProperty(updateDownloadContentDisp, "DownloadUrl")); err != nil {
return nil, err
}
return iUpdateDownloadContent, nil
}

View file

@ -76,3 +76,61 @@ func (iUpdateDownloader *IUpdateDownloader) Download(updates []*IUpdate) (*IDown
}
return toIDownloadResult(downloadResultDisp)
}
// BeginDownload begins an asynchronous download of the content files associated with the updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatedownloader-begindownload
func (iUpdateDownloader *IUpdateDownloader) BeginDownload(updates []*IUpdate) (*IDownloadJob, error) {
updatesDisp, err := toIUpdateCollection(updates)
if err != nil {
return nil, err
}
if _, err = oleutil.PutProperty(iUpdateDownloader.disp, "Updates", updatesDisp); err != nil {
return nil, err
}
jobDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateDownloader.disp, "BeginDownload", nil, nil, nil))
if err != nil {
return nil, err
}
return toIDownloadJob(jobDisp)
}
// EndDownload completes an asynchronous download.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatedownloader-enddownload
func (iUpdateDownloader *IUpdateDownloader) EndDownload(downloadJob *IDownloadJob) (*IDownloadResult, error) {
resultDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateDownloader.disp, "EndDownload", downloadJob.disp))
if err != nil {
return nil, err
}
return toIDownloadResult(resultDisp)
}
// PutClientApplicationID sets the identifier of the current client application.
func (iUpdateDownloader *IUpdateDownloader) PutClientApplicationID(value string) error {
_, err := oleutil.PutProperty(iUpdateDownloader.disp, "ClientApplicationID", value)
if err != nil {
return err
}
iUpdateDownloader.ClientApplicationID = value
return nil
}
// PutIsForced sets whether the download is forced.
func (iUpdateDownloader *IUpdateDownloader) PutIsForced(value bool) error {
_, err := oleutil.PutProperty(iUpdateDownloader.disp, "IsForced", value)
if err != nil {
return err
}
iUpdateDownloader.IsForced = value
return nil
}
// PutPriority sets the download priority.
func (iUpdateDownloader *IUpdateDownloader) PutPriority(value int32) error {
_, err := oleutil.PutProperty(iUpdateDownloader.disp, "Priority", value)
if err != nil {
return err
}
iUpdateDownloader.Priority = value
return nil
}

View file

@ -15,6 +15,7 @@ package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateDownloadResult contains the properties that indicate the status of a download operation for an update.
@ -26,6 +27,18 @@ type IUpdateDownloadResult struct {
}
func toIUpdateDownloadResult(iUpdateDownloadResultDisp *ole.IDispatch) (*IUpdateDownloadResult, error) {
// TODO
return nil, nil
var err error
iUpdateDownloadResult := &IUpdateDownloadResult{
disp: iUpdateDownloadResultDisp,
}
if iUpdateDownloadResult.HResult, err = toInt32Err(oleutil.GetProperty(iUpdateDownloadResultDisp, "HResult")); err != nil {
return nil, err
}
if iUpdateDownloadResult.ResultCode, err = toInt32Err(oleutil.GetProperty(iUpdateDownloadResultDisp, "ResultCode")); err != nil {
return nil, err
}
return iUpdateDownloadResult, nil
}

View file

@ -15,6 +15,7 @@ package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateException represents info about the aspects of search results returned in the ISearchResult object that were incomplete. For more info, see Remarks.
@ -27,6 +28,45 @@ type IUpdateException struct {
}
func toIUpdateExceptions(updateExceptionsDisp *ole.IDispatch) ([]*IUpdateException, error) {
// TODO
return nil, nil
count, err := toInt32Err(oleutil.GetProperty(updateExceptionsDisp, "Count"))
if err != nil {
return nil, err
}
exceptions := make([]*IUpdateException, 0, count)
for i := 0; i < int(count); i++ {
exceptionDisp, err := toIDispatchErr(oleutil.GetProperty(updateExceptionsDisp, "Item", i))
if err != nil {
return nil, err
}
exception, err := toIUpdateException(exceptionDisp)
if err != nil {
return nil, err
}
exceptions = append(exceptions, exception)
}
return exceptions, nil
}
func toIUpdateException(updateExceptionDisp *ole.IDispatch) (*IUpdateException, error) {
var err error
iUpdateException := &IUpdateException{
disp: updateExceptionDisp,
}
if iUpdateException.Context, err = toInt32Err(oleutil.GetProperty(updateExceptionDisp, "Context")); err != nil {
return nil, err
}
if iUpdateException.HResult, err = toInt64Err(oleutil.GetProperty(updateExceptionDisp, "HResult")); err != nil {
return nil, err
}
if iUpdateException.Message, err = toStringErr(oleutil.GetProperty(updateExceptionDisp, "Message")); err != nil {
return nil, err
}
return iUpdateException, nil
}

View file

@ -0,0 +1,51 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateInstallationResult represents the result of an installation or uninstallation for an update.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdateinstallationresult
type IUpdateInstallationResult struct {
disp *ole.IDispatch
HResult int32
RebootRequired bool
ResultCode int32 // OperationResultCode enum
}
func toIUpdateInstallationResult(disp *ole.IDispatch) (*IUpdateInstallationResult, error) {
if disp == nil {
return nil, nil
}
var err error
r := &IUpdateInstallationResult{disp: disp}
if r.HResult, err = toInt32Err(oleutil.GetProperty(disp, "HResult")); err != nil {
return nil, err
}
if r.RebootRequired, err = toBoolErr(oleutil.GetProperty(disp, "RebootRequired")); err != nil {
return nil, err
}
if r.ResultCode, err = toInt32Err(oleutil.GetProperty(disp, "ResultCode")); err != nil {
return nil, err
}
return r, nil
}

View file

@ -58,7 +58,7 @@ func toIUpdateInstaller(updateInstallerDisp *ole.IDispatch) (*IUpdateInstaller,
if iUpdateInstaller.ForceQuiet, err = toBoolErr(oleutil.GetProperty(updateInstallerDisp, "ForceQuiet")); err != nil {
return nil, err
}
if iUpdateInstaller.RebootRequiredBeforeInstallation, err = toBoolErr(oleutil.GetProperty(updateInstallerDisp, "RebootRequiredBeforeInstallation")); err != nil {
return nil, err
}
@ -125,3 +125,97 @@ func (iUpdateInstaller *IUpdateInstaller) PutIsForced(value bool) error {
iUpdateInstaller.IsForced = value
return nil
}
// Uninstall starts a synchronous uninstallation of the updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller-uninstall
func (iUpdateInstaller *IUpdateInstaller) Uninstall(updates []*IUpdate) (*IInstallationResult, error) {
updatesDisp, err := toIUpdateCollection(updates)
if err != nil {
return nil, err
}
if _, err = oleutil.PutProperty(iUpdateInstaller.disp, "Updates", updatesDisp); err != nil {
return nil, err
}
uninstallationResultDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateInstaller.disp, "Uninstall"))
if err != nil {
return nil, err
}
return toIInstallationResult(uninstallationResultDisp)
}
// BeginInstall begins an asynchronous installation of the updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller-begininstall
func (iUpdateInstaller *IUpdateInstaller) BeginInstall(updates []*IUpdate) (*IInstallationJob, error) {
updatesDisp, err := toIUpdateCollection(updates)
if err != nil {
return nil, err
}
if _, err = oleutil.PutProperty(iUpdateInstaller.disp, "Updates", updatesDisp); err != nil {
return nil, err
}
jobDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateInstaller.disp, "BeginInstall", nil, nil, nil))
if err != nil {
return nil, err
}
return toIInstallationJob(jobDisp)
}
// EndInstall completes an asynchronous installation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller-endinstall
func (iUpdateInstaller *IUpdateInstaller) EndInstall(installationJob *IInstallationJob) (*IInstallationResult, error) {
resultDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateInstaller.disp, "EndInstall", installationJob.disp))
if err != nil {
return nil, err
}
return toIInstallationResult(resultDisp)
}
// BeginUninstall begins an asynchronous uninstallation of the updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller-beginuninstall
func (iUpdateInstaller *IUpdateInstaller) BeginUninstall(updates []*IUpdate) (*IInstallationJob, error) {
updatesDisp, err := toIUpdateCollection(updates)
if err != nil {
return nil, err
}
if _, err = oleutil.PutProperty(iUpdateInstaller.disp, "Updates", updatesDisp); err != nil {
return nil, err
}
jobDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateInstaller.disp, "BeginUninstall", nil, nil, nil))
if err != nil {
return nil, err
}
return toIInstallationJob(jobDisp)
}
// EndUninstall completes an asynchronous uninstallation.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller-enduninstall
func (iUpdateInstaller *IUpdateInstaller) EndUninstall(installationJob *IInstallationJob) (*IInstallationResult, error) {
resultDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateInstaller.disp, "EndUninstall", installationJob.disp))
if err != nil {
return nil, err
}
return toIInstallationResult(resultDisp)
}
// PutAllowSourcePrompts sets whether prompts are allowed during installation.
func (iUpdateInstaller *IUpdateInstaller) PutAllowSourcePrompts(value bool) error {
_, err := oleutil.PutProperty(iUpdateInstaller.disp, "AllowSourcePrompts", value)
if err != nil {
return err
}
iUpdateInstaller.AllowSourcePrompts = value
return nil
}
// PutClientApplicationID sets the identifier of the current client application.
func (iUpdateInstaller *IUpdateInstaller) PutClientApplicationID(value string) error {
_, err := oleutil.PutProperty(iUpdateInstaller.disp, "ClientApplicationID", value)
if err != nil {
return err
}
iUpdateInstaller.ClientApplicationID = value
return nil
}

View file

@ -86,6 +86,8 @@ func (iUpdateSearcher *IUpdateSearcher) QueryHistory(startIndex int32, count int
// GetTotalHistoryCount returns the number of update events on the computer.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesearcher-gettotalhistorycount
func (iUpdateSearcher *IUpdateSearcher) GetTotalHistoryCount() (int32, error) {
// According to MSDN, this is a method with an [out, retval] parameter
// In COM automation through IDispatch, such methods return the value directly
return toInt32Err(oleutil.CallMethod(iUpdateSearcher.disp, "GetTotalHistoryCount"))
}
@ -97,3 +99,79 @@ func (iUpdateSearcher *IUpdateSearcher) QueryHistoryAll() ([]*IUpdateHistoryEntr
}
return iUpdateSearcher.QueryHistory(0, count)
}
// BeginSearch begins an asynchronous search for updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesearcher-beginsearch
func (iUpdateSearcher *IUpdateSearcher) BeginSearch(criteria string) (*ISearchJob, error) {
jobDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSearcher.disp, "BeginSearch", criteria, nil, nil))
if err != nil {
return nil, err
}
return toISearchJob(jobDisp)
}
// EndSearch completes an asynchronous search.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesearcher-endsearch
func (iUpdateSearcher *IUpdateSearcher) EndSearch(searchJob *ISearchJob) (*ISearchResult, error) {
resultDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSearcher.disp, "EndSearch", searchJob.disp))
if err != nil {
return nil, err
}
return toISearchResult(resultDisp)
}
// EscapeString converts a string into a string that can be used as a literal value in a search criteria string.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesearcher-escapestring
func (iUpdateSearcher *IUpdateSearcher) EscapeString(unescaped string) (string, error) {
return toStringErr(oleutil.CallMethod(iUpdateSearcher.disp, "EscapeString", unescaped))
}
// PutClientApplicationID sets the identifier of the current client application.
func (iUpdateSearcher *IUpdateSearcher) PutClientApplicationID(value string) error {
_, err := oleutil.PutProperty(iUpdateSearcher.disp, "ClientApplicationID", value)
if err != nil {
return err
}
iUpdateSearcher.ClientApplicationID = value
return nil
}
// PutServerSelection sets the server to search.
func (iUpdateSearcher *IUpdateSearcher) PutServerSelection(value int32) error {
_, err := oleutil.PutProperty(iUpdateSearcher.disp, "ServerSelection", value)
if err != nil {
return err
}
iUpdateSearcher.ServerSelection = value
return nil
}
// PutServiceID sets the ServiceID to search.
func (iUpdateSearcher *IUpdateSearcher) PutServiceID(value string) error {
_, err := oleutil.PutProperty(iUpdateSearcher.disp, "ServiceID", value)
if err != nil {
return err
}
iUpdateSearcher.ServiceID = value
return nil
}
// PutOnline sets whether to search online.
func (iUpdateSearcher *IUpdateSearcher) PutOnline(value bool) error {
_, err := oleutil.PutProperty(iUpdateSearcher.disp, "Online", value)
if err != nil {
return err
}
iUpdateSearcher.Online = value
return nil
}
// PutIncludePotentiallySupersededUpdates sets whether to include potentially superseded updates.
func (iUpdateSearcher *IUpdateSearcher) PutIncludePotentiallySupersededUpdates(value bool) error {
_, err := oleutil.PutProperty(iUpdateSearcher.disp, "IncludePotentiallySupersededUpdates", value)
if err != nil {
return err
}
iUpdateSearcher.IncludePotentiallySupersededUpdates = value
return nil
}

View file

@ -0,0 +1,133 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"time"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateService contains information about a service that is registered with Windows Update Agent (WUA).
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdateservice
type IUpdateService struct {
disp *ole.IDispatch
CanRegisterWithAU bool
ContentValidationCert []byte
ExpirationDate *time.Time
IsManaged bool
IsRegisteredWithAU bool
IsScanPackageService bool
IssueDate *time.Time
Name string
OffersWindowsUpdates bool
RedirectUrls []string
ServiceID string
ServiceUrl string
SetupPrefix string
// IUpdateService2 properties
IsDefaultAUService bool
}
func toIUpdateService(disp *ole.IDispatch) (*IUpdateService, error) {
if disp == nil {
return nil, nil
}
var err error
s := &IUpdateService{disp: disp}
if s.CanRegisterWithAU, err = toBoolErr(oleutil.GetProperty(disp, "CanRegisterWithAU")); err != nil {
return nil, err
}
if s.IsManaged, err = toBoolErr(oleutil.GetProperty(disp, "IsManaged")); err != nil {
return nil, err
}
if s.IsRegisteredWithAU, err = toBoolErr(oleutil.GetProperty(disp, "IsRegisteredWithAU")); err != nil {
return nil, err
}
if s.IsScanPackageService, err = toBoolErr(oleutil.GetProperty(disp, "IsScanPackageService")); err != nil {
return nil, err
}
if s.IssueDate, err = toTimeErr(oleutil.GetProperty(disp, "IssueDate")); err != nil {
return nil, err
}
if s.ExpirationDate, err = toTimeErr(oleutil.GetProperty(disp, "ExpirationDate")); err != nil {
return nil, err
}
if s.Name, err = toStringErr(oleutil.GetProperty(disp, "Name")); err != nil {
return nil, err
}
if s.OffersWindowsUpdates, err = toBoolErr(oleutil.GetProperty(disp, "OffersWindowsUpdates")); err != nil {
return nil, err
}
if s.RedirectUrls, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(disp, "RedirectUrls"))); err != nil {
return nil, err
}
if s.ServiceID, err = toStringErr(oleutil.GetProperty(disp, "ServiceID")); err != nil {
return nil, err
}
if s.ServiceUrl, err = toStringErr(oleutil.GetProperty(disp, "ServiceUrl")); err != nil {
return nil, err
}
if s.SetupPrefix, err = toStringErr(oleutil.GetProperty(disp, "SetupPrefix")); err != nil {
return nil, err
}
// IUpdateService2 property
if isDefault, err := toBoolErr(oleutil.GetProperty(disp, "IsDefaultAUService")); err == nil {
s.IsDefaultAUService = isDefault
}
return s, nil
}
func toIUpdateServices(disp *ole.IDispatch) ([]*IUpdateService, error) {
if disp == nil {
return nil, nil
}
count, err := toInt32Err(oleutil.GetProperty(disp, "Count"))
if err != nil {
return nil, err
}
services := make([]*IUpdateService, 0, count)
for i := int32(0); i < count; i++ {
serviceDisp, err := toIDispatchErr(oleutil.GetProperty(disp, "Item", i))
if err != nil {
return nil, err
}
service, err := toIUpdateService(serviceDisp)
if err != nil {
return nil, err
}
services = append(services, service)
}
return services, nil
}

View file

@ -0,0 +1,141 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateServiceManager adds or removes the registration of an update service with Windows Update Agent.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdateservicemanager
type IUpdateServiceManager struct {
disp *ole.IDispatch
Services []*IUpdateService
// IUpdateServiceManager2 properties
ClientApplicationID string
}
// NewUpdateServiceManager creates a new IUpdateServiceManager instance.
func NewUpdateServiceManager() (*IUpdateServiceManager, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.ServiceManager")
if err != nil {
return nil, err
}
disp, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
return toIUpdateServiceManager(disp)
}
func toIUpdateServiceManager(disp *ole.IDispatch) (*IUpdateServiceManager, error) {
if disp == nil {
return nil, nil
}
sm := &IUpdateServiceManager{disp: disp}
servicesDisp, err := toIDispatchErr(oleutil.GetProperty(disp, "Services"))
if err == nil && servicesDisp != nil {
services, err := toIUpdateServices(servicesDisp)
if err == nil {
sm.Services = services
} else {
// If we can't parse services, initialize to empty slice instead of nil
sm.Services = make([]*IUpdateService, 0)
}
} else {
// If Services property doesn't exist or fails, initialize to empty slice
sm.Services = make([]*IUpdateService, 0)
}
// IUpdateServiceManager2 property
if clientAppID, err := toStringErr(oleutil.GetProperty(disp, "ClientApplicationID")); err == nil {
sm.ClientApplicationID = clientAppID
}
return sm, nil
}
// AddService registers a service with Windows Update Agent (WUA).
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateservicemanager-addservice
func (sm *IUpdateServiceManager) AddService(serviceID string, authorizationCabPath string) (*IUpdateService, error) {
serviceDisp, err := toIDispatchErr(oleutil.CallMethod(sm.disp, "AddService", serviceID, authorizationCabPath))
if err != nil {
return nil, err
}
return toIUpdateService(serviceDisp)
}
// RegisterServiceWithAU registers a service with Automatic Updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateservicemanager-registerservicewithau
func (sm *IUpdateServiceManager) RegisterServiceWithAU(serviceID string) error {
_, err := oleutil.CallMethod(sm.disp, "RegisterServiceWithAU", serviceID)
return err
}
// RemoveService removes a service registration from Windows Update Agent (WUA).
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateservicemanager-removeservice
func (sm *IUpdateServiceManager) RemoveService(serviceID string) error {
_, err := oleutil.CallMethod(sm.disp, "RemoveService", serviceID)
return err
}
// UnregisterServiceWithAU unregisters a service with Automatic Updates.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateservicemanager-unregisterservicewithau
func (sm *IUpdateServiceManager) UnregisterServiceWithAU(serviceID string) error {
_, err := oleutil.CallMethod(sm.disp, "UnregisterServiceWithAU", serviceID)
return err
}
// SetOption sets options for the update service manager.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateservicemanager-setoption
func (sm *IUpdateServiceManager) SetOption(optionName string, optionValue interface{}) error {
_, err := oleutil.CallMethod(sm.disp, "SetOption", optionName, optionValue)
return err
}
// AddScanPackageService registers a scan package service.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateservicemanager-addscanpackageservice
func (sm *IUpdateServiceManager) AddScanPackageService(serviceName string, scanFileLocation string, flags int32) (*IUpdateService, error) {
serviceDisp, err := toIDispatchErr(oleutil.CallMethod(sm.disp, "AddScanPackageService", serviceName, scanFileLocation, flags))
if err != nil {
return nil, err
}
return toIUpdateService(serviceDisp)
}
// PutClientApplicationID sets the identifier of the current client application. (IUpdateServiceManager2)
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateservicemanager2-put_clientapplicationid
func (sm *IUpdateServiceManager) PutClientApplicationID(value string) error {
_, err := oleutil.PutProperty(sm.disp, "ClientApplicationID", value)
if err != nil {
return err
}
sm.ClientApplicationID = value
return nil
}
// AddService2 registers a service with Windows Update Agent (WUA). (IUpdateServiceManager2)
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateservicemanager2-addservice2
func (sm *IUpdateServiceManager) AddService2(serviceID string, flags int32, authorizationCabPath string) (*IUpdateServiceRegistration, error) {
regDisp, err := toIDispatchErr(oleutil.CallMethod(sm.disp, "AddService2", serviceID, flags, authorizationCabPath))
if err != nil {
return nil, err
}
return toIUpdateServiceRegistration(regDisp)
}

View file

@ -0,0 +1,57 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateServiceRegistration represents the registration status of an update service.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdateserviceregistration
type IUpdateServiceRegistration struct {
disp *ole.IDispatch
IsPendingRegistrationWithAU bool
RegistrationState int32
Service *IUpdateService
}
func toIUpdateServiceRegistration(disp *ole.IDispatch) (*IUpdateServiceRegistration, error) {
if disp == nil {
return nil, nil
}
var err error
reg := &IUpdateServiceRegistration{disp: disp}
if reg.IsPendingRegistrationWithAU, err = toBoolErr(oleutil.GetProperty(disp, "IsPendingRegistrationWithAU")); err != nil {
return nil, err
}
if reg.RegistrationState, err = toInt32Err(oleutil.GetProperty(disp, "RegistrationState")); err != nil {
return nil, err
}
serviceDisp, err := toIDispatchErr(oleutil.GetProperty(disp, "Service"))
if err != nil {
return nil, err
}
if serviceDisp != nil {
if reg.Service, err = toIUpdateService(serviceDisp); err != nil {
return nil, err
}
}
return reg, nil
}

View file

@ -15,12 +15,13 @@ package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IWebProxy contains the HTTP proxy settings.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iwebproxy
type IWebProxy struct {
disp *ole.Dispatch
disp *ole.IDispatch
Address string
AutoDetect bool
BypassList []string
@ -30,6 +31,40 @@ type IWebProxy struct {
}
func toIWebProxy(webProxyDisp *ole.IDispatch) (*IWebProxy, error) {
// TODO
return nil, nil
var err error
iWebProxy := &IWebProxy{
disp: webProxyDisp,
}
if iWebProxy.Address, err = toStringErr(oleutil.GetProperty(webProxyDisp, "Address")); err != nil {
return nil, err
}
if iWebProxy.AutoDetect, err = toBoolErr(oleutil.GetProperty(webProxyDisp, "AutoDetect")); err != nil {
return nil, err
}
bypassListDisp, err := toIDispatchErr(oleutil.GetProperty(webProxyDisp, "BypassList"))
if err != nil {
return nil, err
}
if bypassListDisp != nil {
if iWebProxy.BypassList, err = iStringCollectionToStringArrayErr(bypassListDisp, nil); err != nil {
return nil, err
}
}
if iWebProxy.BypassProxyOnLocal, err = toBoolErr(oleutil.GetProperty(webProxyDisp, "BypassProxyOnLocal")); err != nil {
return nil, err
}
if iWebProxy.ReadOnly, err = toBoolErr(oleutil.GetProperty(webProxyDisp, "ReadOnly")); err != nil {
return nil, err
}
if iWebProxy.UserName, err = toStringErr(oleutil.GetProperty(webProxyDisp, "UserName")); err != nil {
return nil, err
}
return iWebProxy, nil
}

View file

@ -0,0 +1,178 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"time"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IWindowsDriverUpdate contains the properties and methods available to an update that installs a Windows driver.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iwindowsdriverupdate
type IWindowsDriverUpdate struct {
*IUpdate
DeviceProblemNumber int32
DeviceStatus int32
DriverClass string
DriverHardwareID string
DriverManufacturer string
DriverModel string
DriverProvider string
DriverVerDate *time.Time
// IWindowsDriverUpdate2 properties
RebootRequired2 bool
IsPresent2 bool
// IWindowsDriverUpdate3 properties
BrowseOnly2 bool
// IWindowsDriverUpdate4 properties
WindowsDriverUpdateEntries []*IWindowsDriverUpdateEntry
// IWindowsDriverUpdate5 properties
AutoDownload2 int32
AutoSelection2 int32
}
// ToWindowsDriverUpdate attempts to cast an IUpdate to IWindowsDriverUpdate.
// Returns nil if the update is not a driver update.
func (u *IUpdate) ToWindowsDriverUpdate() (*IWindowsDriverUpdate, error) {
wdu := &IWindowsDriverUpdate{IUpdate: u}
var err error
// Try to get driver-specific properties
if wdu.DeviceProblemNumber, err = toInt32Err(oleutil.GetProperty(u.disp, "DeviceProblemNumber")); err != nil {
return nil, nil // Not a driver update
}
if wdu.DeviceStatus, err = toInt32Err(oleutil.GetProperty(u.disp, "DeviceStatus")); err != nil {
return nil, err
}
if wdu.DriverClass, err = toStringErr(oleutil.GetProperty(u.disp, "DriverClass")); err != nil {
return nil, err
}
if wdu.DriverHardwareID, err = toStringErr(oleutil.GetProperty(u.disp, "DriverHardwareID")); err != nil {
return nil, err
}
if wdu.DriverManufacturer, err = toStringErr(oleutil.GetProperty(u.disp, "DriverManufacturer")); err != nil {
return nil, err
}
if wdu.DriverModel, err = toStringErr(oleutil.GetProperty(u.disp, "DriverModel")); err != nil {
return nil, err
}
if wdu.DriverProvider, err = toStringErr(oleutil.GetProperty(u.disp, "DriverProvider")); err != nil {
return nil, err
}
if wdu.DriverVerDate, err = toTimeErr(oleutil.GetProperty(u.disp, "DriverVerDate")); err != nil {
return nil, err
}
// IWindowsDriverUpdate4 - WindowsDriverUpdateEntries
entriesDisp, err := toIDispatchErr(oleutil.GetProperty(u.disp, "WindowsDriverUpdateEntries"))
if err == nil && entriesDisp != nil {
wdu.WindowsDriverUpdateEntries, _ = toIWindowsDriverUpdateEntries(entriesDisp)
}
return wdu, nil
}
// IWindowsDriverUpdateEntry contains the properties that are available to a Windows driver update entry.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iwindowsdriverupdateentry
type IWindowsDriverUpdateEntry struct {
disp *ole.IDispatch
DeviceProblemNumber int32
DeviceStatus int32
DriverClass string
DriverHardwareID string
DriverManufacturer string
DriverModel string
DriverProvider string
DriverVerDate *time.Time
}
func toIWindowsDriverUpdateEntry(disp *ole.IDispatch) (*IWindowsDriverUpdateEntry, error) {
if disp == nil {
return nil, nil
}
var err error
entry := &IWindowsDriverUpdateEntry{disp: disp}
if entry.DeviceProblemNumber, err = toInt32Err(oleutil.GetProperty(disp, "DeviceProblemNumber")); err != nil {
return nil, err
}
if entry.DeviceStatus, err = toInt32Err(oleutil.GetProperty(disp, "DeviceStatus")); err != nil {
return nil, err
}
if entry.DriverClass, err = toStringErr(oleutil.GetProperty(disp, "DriverClass")); err != nil {
return nil, err
}
if entry.DriverHardwareID, err = toStringErr(oleutil.GetProperty(disp, "DriverHardwareID")); err != nil {
return nil, err
}
if entry.DriverManufacturer, err = toStringErr(oleutil.GetProperty(disp, "DriverManufacturer")); err != nil {
return nil, err
}
if entry.DriverModel, err = toStringErr(oleutil.GetProperty(disp, "DriverModel")); err != nil {
return nil, err
}
if entry.DriverProvider, err = toStringErr(oleutil.GetProperty(disp, "DriverProvider")); err != nil {
return nil, err
}
if entry.DriverVerDate, err = toTimeErr(oleutil.GetProperty(disp, "DriverVerDate")); err != nil {
return nil, err
}
return entry, nil
}
func toIWindowsDriverUpdateEntries(disp *ole.IDispatch) ([]*IWindowsDriverUpdateEntry, error) {
if disp == nil {
return nil, nil
}
count, err := toInt32Err(oleutil.GetProperty(disp, "Count"))
if err != nil {
return nil, err
}
entries := make([]*IWindowsDriverUpdateEntry, 0, count)
for i := int32(0); i < count; i++ {
entryDisp, err := toIDispatchErr(oleutil.GetProperty(disp, "Item", i))
if err != nil {
return nil, err
}
entry, err := toIWindowsDriverUpdateEntry(entryDisp)
if err != nil {
return nil, err
}
entries = append(entries, entry)
}
return entries, nil
}

View file

@ -0,0 +1,101 @@
/*
Copyright 2022 Zheng Dayu
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.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IWindowsUpdateAgentInfo retrieves information about the version of Windows Update Agent (WUA).
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iwindowsupdateagentinfo
type IWindowsUpdateAgentInfo struct {
disp *ole.IDispatch
}
// NewWindowsUpdateAgentInfo creates a new IWindowsUpdateAgentInfo instance.
func NewWindowsUpdateAgentInfo() (*IWindowsUpdateAgentInfo, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.AgentInfo")
if err != nil {
return nil, err
}
disp, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
return &IWindowsUpdateAgentInfo{disp: disp}, nil
}
// GetInfo retrieves version information about Windows Update Agent.
// varInfoIdentifier can be one of: "ApiMajorVersion", "ApiMinorVersion", "ProductVersionString"
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iwindowsupdateagentinfo-getinfo
func (info *IWindowsUpdateAgentInfo) GetInfo(varInfoIdentifier string) (interface{}, error) {
result, err := oleutil.CallMethod(info.disp, "GetInfo", varInfoIdentifier)
if err != nil {
return nil, err
}
return result.Value(), nil
}
// GetApiMajorVersion returns the major version of the WUA API.
func (info *IWindowsUpdateAgentInfo) GetApiMajorVersion() (int32, error) {
result, err := info.GetInfo("ApiMajorVersion")
if err != nil {
return 0, err
}
// Convert result to int32
switch v := result.(type) {
case int32:
return v, nil
case int:
return int32(v), nil
case int64:
return int32(v), nil
default:
return 0, nil
}
}
// GetApiMinorVersion returns the minor version of the WUA API.
func (info *IWindowsUpdateAgentInfo) GetApiMinorVersion() (int32, error) {
result, err := info.GetInfo("ApiMinorVersion")
if err != nil {
return 0, err
}
// Convert result to int32
switch v := result.(type) {
case int32:
return v, nil
case int:
return int32(v), nil
case int64:
return int32(v), nil
default:
return 0, nil
}
}
// GetProductVersionString returns the product version string of WUA.
func (info *IWindowsUpdateAgentInfo) GetProductVersionString() (string, error) {
result, err := info.GetInfo("ProductVersionString")
if err != nil {
return "", err
}
if str, ok := result.(string); ok {
return str, nil
}
return "", nil
}