projection: begin the exact-path public epoch

The public tree and its history contain only the listed paths. Earlier projection history remains preserved internally.

Source-Sha: 913fde029b935671833254797f0f20f1eb9fabba

Policy-Sha: 913fde029b935671833254797f0f20f1eb9fabba

Tree-Digest: 180ae530c1058a2a5c89837bdce2d323ae83e669e38590ca72e75b8d92b7262f
This commit is contained in:
Fimeg 2026-09-08 21:59:33 -04:00
commit 67e26be2d9
838 changed files with 157302 additions and 0 deletions

View file

@ -0,0 +1,154 @@
/*
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
// OperationResultCode defines the possible results of a download, install, uninstall, or verification operation on an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
const (
OperationResultCodeOrcNotStarted int32 = iota
OperationResultCodeOrcInProgress
OperationResultCodeOrcSucceeded
OperationResultCodeOrcSucceededWithErrors
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

@ -0,0 +1,130 @@
/*
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"
)
// ICategory represents the category to which an update belongs.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-icategory
type ICategory struct {
disp *ole.IDispatch
CategoryID string
Children []*ICategory
Description string
Image *IImageInformation
Name string
Order int32
Parent *ICategory
Type string
Updates []*IUpdate
}
func toICategories(categoriesDisp *ole.IDispatch) ([]*ICategory, error) {
count, err := toInt32Err(oleutil.GetProperty(categoriesDisp, "Count"))
if err != nil {
return nil, err
}
categories := make([]*ICategory, 0, count)
for i := 0; i < int(count); i++ {
categoryDisp, err := toIDispatchErr(oleutil.GetProperty(categoriesDisp, "Item", i))
if err != nil {
return nil, err
}
category, err := toICategory(categoryDisp)
if err != nil {
return nil, err
}
categories = append(categories, category)
}
return categories, nil
}
func toICategory(categoryDisp *ole.IDispatch) (*ICategory, error) {
var err error
iCategory := &ICategory{
disp: categoryDisp,
}
if iCategory.CategoryID, err = toStringErr(oleutil.GetProperty(categoryDisp, "CategoryID")); err != nil {
return nil, err
}
childrenDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Children"))
if err != nil {
return nil, err
}
if childrenDisp != nil {
if iCategory.Children, err = toICategories(childrenDisp); err != nil {
return nil, err
}
}
if iCategory.Description, err = toStringErr(oleutil.GetProperty(categoryDisp, "Description")); err != nil {
return nil, err
}
imageDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Image"))
if err != nil {
return nil, err
}
if imageDisp != nil {
if iCategory.Image, err = toIImageInformation(imageDisp); err != nil {
return nil, err
}
}
if iCategory.Name, err = toStringErr(oleutil.GetProperty(categoryDisp, "Name")); err != nil {
return nil, err
}
if iCategory.Order, err = toInt32Err(oleutil.GetProperty(categoryDisp, "Order")); 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
}
}
*/
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

@ -0,0 +1,66 @@
/*
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"
)
// IDownloadResult represents the result of a download operation.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-idownloadresult
type IDownloadResult struct {
disp *ole.IDispatch
HResult int32
ResultCode int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
}
func toIDownloadResult(downloadResultDisp *ole.IDispatch) (*IDownloadResult, error) {
var err error
iDownloadResult := &IDownloadResult{
disp: downloadResultDisp,
}
if iDownloadResult.HResult, err = toInt32Err(oleutil.GetProperty(downloadResultDisp, "HResult")); err != nil {
return nil, err
}
if iDownloadResult.ResultCode, err = toInt32Err(oleutil.GetProperty(downloadResultDisp, "ResultCode")); err != nil {
return nil, err
}
return iDownloadResult, nil
}
// GetUpdateResult returns an IUpdateDownloadResult interface that contains the download information for a specified update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-idownloadresult-getupdateresult
func (iDownloadResult *IDownloadResult) GetUpdateResult(updateIndex int32) (*IUpdateDownloadResult, error) {
var err error
iUpdateDownloadResult := &IUpdateDownloadResult{
disp: iDownloadResult.disp,
}
updatesDisp, err := toIDispatchErr(oleutil.CallMethod(iDownloadResult.disp, "GetUpdateResult", updateIndex))
if err != nil {
return nil, err
}
if iUpdateDownloadResult.HResult, err = toInt32Err(oleutil.GetProperty(updatesDisp, "HResult")); err != nil {
return nil, err
}
if iUpdateDownloadResult.ResultCode, err = toInt32Err(oleutil.GetProperty(updatesDisp, "ResultCode")); err != nil {
return nil, err
}
return iUpdateDownloadResult, nil
}

View file

@ -0,0 +1,54 @@
/*
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"
)
// IImageInformation contains information about a localized image that is associated with an update or a category.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iimageinformation
type IImageInformation struct {
disp *ole.IDispatch
AltText string
Height int64
Source string
Width int64
}
func toIImageInformation(imageInformationDisp *ole.IDispatch) (*IImageInformation, error) {
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

@ -0,0 +1,54 @@
/*
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"
)
// IInstallationBehavior represents the installation and uninstallation options of an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iinstallationbehavior
type IInstallationBehavior struct {
disp *ole.IDispatch
CanRequestUserInput bool
Impact int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-installationimpact
RebootBehavior int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-installationrebootbehavior
RequiresNetworkConnectivity bool
}
func toIInstallationBehavior(installationBehaviorDisp *ole.IDispatch) (*IInstallationBehavior, error) {
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,71 @@
/*
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"
)
// IInstallationResult represents the result of an installation or uninstallation.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iinstallationresult
type IInstallationResult struct {
disp *ole.IDispatch
HResult int32
RebootRequired bool
ResultCode int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
}
func toIInstallationResult(installationResultDisp *ole.IDispatch) (*IInstallationResult, error) {
var err error
iInstallationResult := &IInstallationResult{
disp: installationResultDisp,
}
if iInstallationResult.HResult, err = toInt32Err(oleutil.GetProperty(installationResultDisp, "HResult")); err != nil {
return nil, err
}
if iInstallationResult.RebootRequired, err = toBoolErr(oleutil.GetProperty(installationResultDisp, "RebootRequired")); err != nil {
return nil, err
}
if iInstallationResult.ResultCode, err = toInt32Err(oleutil.GetProperty(installationResultDisp, "ResultCode")); err != nil {
return nil, err
}
return iInstallationResult, nil
}
// GetUpdateResult returns an IInstallationResult interface that contains the installation information for a specified update.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iinstallationresult
func (iInstallationResult *IInstallationResult) GetUpdateResult(updateIndex int32) (*IInstallationResult, error) {
var err error
iUpdateInstallationResult := &IInstallationResult{
disp: iInstallationResult.disp,
}
updatesDisp, err := toIDispatchErr(oleutil.CallMethod(iInstallationResult.disp, "GetUpdateResult", updateIndex))
if err != nil {
return nil, err
}
if iUpdateInstallationResult.HResult, err = toInt32Err(oleutil.GetProperty(updatesDisp, "HResult")); err != nil {
return nil, err
}
if iUpdateInstallationResult.ResultCode, err = toInt32Err(oleutil.GetProperty(updatesDisp, "ResultCode")); err != nil {
return nil, err
}
return iUpdateInstallationResult, nil
}

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

@ -0,0 +1,72 @@
/*
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"
)
// ISearchResult represents the result of a search.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-isearchresult
type ISearchResult struct {
disp *ole.IDispatch
ResultCode int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
RootCategories []*ICategory
Updates []*IUpdate
Warnings []*IUpdateException
}
func toISearchResult(searchResultDisp *ole.IDispatch) (*ISearchResult, error) {
var err error
iSearchResult := &ISearchResult{
disp: searchResultDisp,
}
if iSearchResult.ResultCode, err = toInt32Err(oleutil.GetProperty(searchResultDisp, "ResultCode")); err != nil {
return nil, err
}
rootCategoriesDisp, err := toIDispatchErr(oleutil.GetProperty(searchResultDisp, "RootCategories"))
if err != nil {
return nil, err
}
if rootCategoriesDisp != nil {
if iSearchResult.RootCategories, err = toICategories(rootCategoriesDisp); err != nil {
return nil, err
}
}
updatesDisp, err := toIDispatchErr(oleutil.GetProperty(searchResultDisp, "Updates"))
if err != nil {
return nil, err
}
if updatesDisp != nil {
if iSearchResult.Updates, err = toIUpdates(updatesDisp); err != nil {
return nil, err
}
}
warningsDisp, err := toIDispatchErr(oleutil.GetProperty(searchResultDisp, "Warnings"))
if err != nil {
return nil, err
}
if warningsDisp != nil {
if iSearchResult.Warnings, err = toIUpdateExceptions(warningsDisp); err != nil {
return nil, err
}
}
return iSearchResult, nil
}

View file

@ -0,0 +1,144 @@
/*
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"
)
// 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
}
if disp == nil {
return nil, nil
}
count, err := toInt32Err(oleutil.GetProperty(disp, "Count"))
if err != nil {
return nil, err
}
stringCollection := make([]string, count)
for i := 0; i < int(count); i++ {
str, err := toStringErr(oleutil.GetProperty(disp, "Item", i))
if err != nil {
return nil, err
}
stringCollection[i] = str
}
return stringCollection, nil
}

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

@ -0,0 +1,415 @@
/*
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"
)
// IUpdate contains the properties and methods that are available to an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdate
type IUpdate struct {
disp *ole.IDispatch
AutoSelectOnWebSites bool
BundledUpdates []*IUpdateIdentity
CanRequireSource bool
Categories []*ICategory
Deadline *time.Time
DeltaCompressedContentAvailable bool
DeltaCompressedContentPreferred bool
DeploymentAction int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-deploymentaction
Description string
DownloadContents []*IUpdateDownloadContent
DownloadPriority int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-downloadpriority
EulaAccepted bool
EulaText string
HandlerID string
Identity *IUpdateIdentity
Image *IImageInformation
InstallationBehavior *IInstallationBehavior
IsBeta bool
IsDownloaded bool
IsHidden bool
IsInstalled bool
IsMandatory bool
IsUninstallable bool
KBArticleIDs []string
Languages []string
LastDeploymentChangeTime *time.Time
MaxDownloadSize int64
MinDownloadSize int64
MoreInfoUrls []string
MsrcSeverity string
RecommendedCpuSpeed int32
RecommendedHardDiskSpace int32
RecommendedMemory int32
ReleaseNotes string
SecurityBulletinIDs []string
SupersededUpdateIDs []string
SupportUrl string
Title string
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) {
count, err := toInt32Err(oleutil.GetProperty(updatesDisp, "Count"))
if err != nil {
return nil, err
}
updates := make([]*IUpdate, 0, count)
for i := 0; i < int(count); i++ {
updateDisp, err := toIDispatchErr(oleutil.GetProperty(updatesDisp, "Item", i))
if err != nil {
return nil, err
}
update, err := toIUpdate(updateDisp)
if err != nil {
return nil, err
}
updates = append(updates, update)
}
return updates, nil
}
// toIUpdates takes a IUpdateCollection and returns the a
// []*IUpdateIdentity of the contained IUpdates. This is *not* recursive, though possible should be
func toIUpdatesIdentities(updatesDisp *ole.IDispatch) ([]*IUpdateIdentity, error) {
if updatesDisp == nil {
return nil, nil
}
count, err := toInt32Err(oleutil.GetProperty(updatesDisp, "Count"))
if err != nil {
return nil, err
}
identities := make([]*IUpdateIdentity, count)
for i := 0; i < int(count); i++ {
updateDisp, err := toIDispatchErr(oleutil.GetProperty(updatesDisp, "Item", i))
if err != nil {
return nil, err
}
identityDisp, err := toIDispatchErr(oleutil.GetProperty(updateDisp, "Identity"))
if err != nil {
return nil, err
}
if identityDisp != nil {
if identities[i], err = toIUpdateIdentity(identityDisp); err != nil {
return nil, err
}
}
}
return identities, nil
}
func toIUpdate(updateDisp *ole.IDispatch) (*IUpdate, error) {
var err error
iUpdate := &IUpdate{
disp: updateDisp,
}
if iUpdate.AutoSelectOnWebSites, err = toBoolErr(oleutil.GetProperty(updateDisp, "AutoSelectOnWebSites")); err != nil {
return nil, err
}
bundledUpdatesDisp, err := toIDispatchErr(oleutil.GetProperty(updateDisp, "BundledUpdates"))
if err != nil {
return nil, err
}
if bundledUpdatesDisp != nil {
if iUpdate.BundledUpdates, err = toIUpdatesIdentities(bundledUpdatesDisp); err != nil {
return nil, err
}
}
if iUpdate.CanRequireSource, err = toBoolErr(oleutil.GetProperty(updateDisp, "CanRequireSource")); err != nil {
return nil, err
}
categoriesDisp, err := toIDispatchErr(oleutil.GetProperty(updateDisp, "Categories"))
if err != nil {
return nil, err
}
if categoriesDisp != nil {
if iUpdate.Categories, err = toICategories(categoriesDisp); err != nil {
return nil, err
}
}
if iUpdate.Deadline, err = toTimeErr(oleutil.GetProperty(updateDisp, "Deadline")); err != nil {
return nil, err
}
if iUpdate.DeltaCompressedContentAvailable, err = toBoolErr(oleutil.GetProperty(updateDisp, "DeltaCompressedContentAvailable")); err != nil {
return nil, err
}
if iUpdate.DeltaCompressedContentPreferred, err = toBoolErr(oleutil.GetProperty(updateDisp, "DeltaCompressedContentPreferred")); err != nil {
return nil, err
}
if iUpdate.DeploymentAction, err = toInt32Err(oleutil.GetProperty(updateDisp, "DeploymentAction")); err != nil {
return nil, err
}
if iUpdate.Description, err = toStringErr(oleutil.GetProperty(updateDisp, "Description")); err != nil {
return nil, err
}
downloadContentsDisp, err := toIDispatchErr(oleutil.GetProperty(updateDisp, "DownloadContents"))
if err != nil {
return nil, err
}
if downloadContentsDisp != nil {
if iUpdate.DownloadContents, err = toIUpdateDownloadContents(downloadContentsDisp); err != nil {
return nil, err
}
}
if iUpdate.DownloadPriority, err = toInt32Err(oleutil.GetProperty(updateDisp, "DownloadPriority")); err != nil {
return nil, err
}
if iUpdate.EulaAccepted, err = toBoolErr(oleutil.GetProperty(updateDisp, "EulaAccepted")); err != nil {
return nil, err
}
if iUpdate.EulaText, err = toStringErr(oleutil.GetProperty(updateDisp, "EulaText")); err != nil {
return nil, err
}
if iUpdate.HandlerID, err = toStringErr(oleutil.GetProperty(updateDisp, "HandlerID")); err != nil {
return nil, err
}
identityDisp, err := toIDispatchErr(oleutil.GetProperty(updateDisp, "Identity"))
if err != nil {
return nil, err
}
if identityDisp != nil {
if iUpdate.Identity, err = toIUpdateIdentity(identityDisp); err != nil {
return nil, err
}
}
imageDisp, err := toIDispatchErr(oleutil.GetProperty(updateDisp, "Image"))
if err != nil {
return nil, err
}
if imageDisp != nil {
if iUpdate.Image, err = toIImageInformation(imageDisp); err != nil {
return nil, err
}
}
installationBehaviorDisp, err := toIDispatchErr(oleutil.GetProperty(updateDisp, "InstallationBehavior"))
if err != nil {
return nil, err
}
if installationBehaviorDisp != nil {
if iUpdate.InstallationBehavior, err = toIInstallationBehavior(installationBehaviorDisp); err != nil {
return nil, err
}
}
if iUpdate.IsBeta, err = toBoolErr(oleutil.GetProperty(updateDisp, "IsBeta")); err != nil {
return nil, err
}
if iUpdate.IsDownloaded, err = toBoolErr(oleutil.GetProperty(updateDisp, "IsDownloaded")); err != nil {
return nil, err
}
if iUpdate.IsHidden, err = toBoolErr(oleutil.GetProperty(updateDisp, "IsHidden")); err != nil {
return nil, err
}
if iUpdate.IsInstalled, err = toBoolErr(oleutil.GetProperty(updateDisp, "IsInstalled")); err != nil {
return nil, err
}
if iUpdate.IsMandatory, err = toBoolErr(oleutil.GetProperty(updateDisp, "IsMandatory")); err != nil {
return nil, err
}
if iUpdate.IsUninstallable, err = toBoolErr(oleutil.GetProperty(updateDisp, "IsUninstallable")); err != nil {
return nil, err
}
if iUpdate.KBArticleIDs, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateDisp, "KBArticleIDs"))); err != nil {
return nil, err
}
if iUpdate.Languages, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateDisp, "Languages"))); err != nil {
return nil, err
}
if iUpdate.LastDeploymentChangeTime, err = toTimeErr(oleutil.GetProperty(updateDisp, "LastDeploymentChangeTime")); err != nil {
return nil, err
}
if iUpdate.MaxDownloadSize, err = toInt64Err(oleutil.GetProperty(updateDisp, "MaxDownloadSize")); err != nil {
return nil, err
}
if iUpdate.MinDownloadSize, err = toInt64Err(oleutil.GetProperty(updateDisp, "MinDownloadSize")); err != nil {
return nil, err
}
if iUpdate.MoreInfoUrls, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateDisp, "MoreInfoUrls"))); err != nil {
return nil, err
}
if iUpdate.MsrcSeverity, err = toStringErr(oleutil.GetProperty(updateDisp, "MsrcSeverity")); err != nil {
return nil, err
}
if iUpdate.RecommendedCpuSpeed, err = toInt32Err(oleutil.GetProperty(updateDisp, "RecommendedCpuSpeed")); err != nil {
return nil, err
}
if iUpdate.RecommendedHardDiskSpace, err = toInt32Err(oleutil.GetProperty(updateDisp, "RecommendedHardDiskSpace")); err != nil {
return nil, err
}
if iUpdate.RecommendedMemory, err = toInt32Err(oleutil.GetProperty(updateDisp, "RecommendedMemory")); err != nil {
return nil, err
}
if iUpdate.ReleaseNotes, err = toStringErr(oleutil.GetProperty(updateDisp, "ReleaseNotes")); err != nil {
return nil, err
}
if iUpdate.SecurityBulletinIDs, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateDisp, "SecurityBulletinIDs"))); err != nil {
return nil, err
}
if iUpdate.SupersededUpdateIDs, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateDisp, "SupersededUpdateIDs"))); err != nil {
return nil, err
}
if iUpdate.SupportUrl, err = toStringErr(oleutil.GetProperty(updateDisp, "SupportUrl")); err != nil {
return nil, err
}
if iUpdate.Title, err = toStringErr(oleutil.GetProperty(updateDisp, "Title")); err != nil {
return nil, err
}
uninstallationBehaviorDisp, err := toIDispatchErr(oleutil.GetProperty(updateDisp, "UninstallationBehavior"))
if err != nil {
return nil, err
}
if uninstallationBehaviorDisp != nil {
if iUpdate.UninstallationBehavior, err = toIInstallationBehavior(uninstallationBehaviorDisp); err != nil {
return nil, err
}
}
if iUpdate.UninstallationNotes, err = toStringErr(oleutil.GetProperty(updateDisp, "UninstallationNotes")); err != nil {
return nil, err
}
if iUpdate.UninstallationSteps, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateDisp, "UninstallationSteps"))); err != nil {
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
}
func toIUpdateCollection(updates []*IUpdate) (*ole.IDispatch, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.UpdateColl")
if err != nil {
return nil, err
}
coll, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
for _, update := range updates {
_, err := oleutil.CallMethod(coll, "Add", update.disp)
if err != nil {
return nil, err
}
}
return coll, nil
}
// AcceptEula accepts the Microsoft Software License Terms that are associated with Windows Update. Administrators and power users can call this method.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdate-accepteula
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

@ -0,0 +1,62 @@
/*
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"
)
// IUpdateDownloadContent represents the download content of an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatedownloadcontent
type IUpdateDownloadContent struct {
disp *ole.IDispatch
DownloadUrl string
}
func toIUpdateDownloadContents(updateDownloadContentsDisp *ole.IDispatch) ([]*IUpdateDownloadContent, error) {
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

@ -0,0 +1,136 @@
/*
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"
)
// IUpdateDownloader downloads updates from the server.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatedownloaders
type IUpdateDownloader struct {
disp *ole.IDispatch
ClientApplicationID string
IsForced bool
Priority int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-downloadpriority
Updates []*IUpdate
}
func toIUpdateDownloader(updateDownloaderDisp *ole.IDispatch) (*IUpdateDownloader, error) {
var err error
iUpdateDownloader := &IUpdateDownloader{
disp: updateDownloaderDisp,
}
if iUpdateDownloader.ClientApplicationID, err = toStringErr(oleutil.GetProperty(updateDownloaderDisp, "ClientApplicationID")); err != nil {
return nil, err
}
if iUpdateDownloader.IsForced, err = toBoolErr(oleutil.GetProperty(updateDownloaderDisp, "IsForced")); err != nil {
return nil, err
}
if iUpdateDownloader.Priority, err = toInt32Err(oleutil.GetProperty(updateDownloaderDisp, "Priority")); err != nil {
return nil, err
}
updatesDisp, err := toIDispatchErr(oleutil.GetProperty(updateDownloaderDisp, "Updates"))
if err != nil {
return nil, err
}
if updatesDisp != nil {
if iUpdateDownloader.Updates, err = toIUpdates(updatesDisp); err != nil {
return nil, err
}
}
return iUpdateDownloader, nil
}
// Download starts a synchronous download of the content files that are associated with the updates.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatedownloader-download
func (iUpdateDownloader *IUpdateDownloader) Download(updates []*IUpdate) (*IDownloadResult, error) {
updatesDisp, err := toIUpdateCollection(updates)
if err != nil {
return nil, err
}
if _, err = oleutil.PutProperty(iUpdateDownloader.disp, "Updates", updatesDisp); err != nil {
return nil, err
}
downloadResultDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateDownloader.disp, "Download"))
if err != nil {
return nil, err
}
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

@ -0,0 +1,44 @@
/*
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"
)
// IUpdateDownloadResult contains the properties that indicate the status of a download operation for an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatedownloadresult
type IUpdateDownloadResult struct {
disp *ole.IDispatch
HResult int32
ResultCode int32
}
func toIUpdateDownloadResult(iUpdateDownloadResultDisp *ole.IDispatch) (*IUpdateDownloadResult, error) {
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

@ -0,0 +1,72 @@
/*
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"
)
// IUpdateException represents info about the aspects of search results returned in the ISearchResult object that were incomplete. For more info, see Remarks.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdateexception
type IUpdateException struct {
disp *ole.IDispatch
Context int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-updateexceptioncontext
HResult int64
Message string
}
func toIUpdateExceptions(updateExceptionsDisp *ole.IDispatch) ([]*IUpdateException, error) {
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,135 @@
/*
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"
)
// IUpdateHistoryEntry represents the recorded history of an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatehistoryentry
type IUpdateHistoryEntry struct {
disp *ole.IDispatch
ClientApplicationID string
Date *time.Time
Description string
HResult int32
Operation int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-updateoperation
ResultCode int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
ServerSelection int32 // enum
ServiceID string
SupportUrl string
Title string
UninstallationNotes string
UninstallationSteps []string
UnmappedResultCode int32
UpdateIdentity *IUpdateIdentity
}
func toIUpdateHistoryEntries(updateHistoryEntriesDisp *ole.IDispatch) ([]*IUpdateHistoryEntry, error) {
count, err := toInt32Err(oleutil.GetProperty(updateHistoryEntriesDisp, "Count"))
if err != nil {
return nil, err
}
updateHistoryEntries := make([]*IUpdateHistoryEntry, 0, count)
for i := 0; i < int(count); i++ {
updateHistoryEntryDisp, err := toIDispatchErr(oleutil.GetProperty(updateHistoryEntriesDisp, "Item", i))
if err != nil {
return nil, err
}
updateHistoryEntry, err := toIUpdateHistoryEntry(updateHistoryEntryDisp)
if err != nil {
return nil, err
}
updateHistoryEntries = append(updateHistoryEntries, updateHistoryEntry)
}
return updateHistoryEntries, nil
}
func toIUpdateHistoryEntry(updateHistoryEntryDisp *ole.IDispatch) (*IUpdateHistoryEntry, error) {
var err error
iUpdateHistoryEntry := &IUpdateHistoryEntry{
disp: updateHistoryEntryDisp,
}
if iUpdateHistoryEntry.ClientApplicationID, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "ClientApplicationID")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.Date, err = toTimeErr(oleutil.GetProperty(updateHistoryEntryDisp, "Date")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.Description, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "Description")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.HResult, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "HResult")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.Operation, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "Operation")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.ResultCode, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "ResultCode")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.ServerSelection, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "ServerSelection")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.ServiceID, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "ServiceID")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.SupportUrl, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "SupportUrl")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.Title, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "Title")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.UninstallationNotes, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "UninstallationNotes")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.UninstallationSteps, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateHistoryEntryDisp, "UninstallationSteps"))); err != nil {
return nil, err
}
if iUpdateHistoryEntry.UnmappedResultCode, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "UnmappedResultCode")); err != nil {
return nil, err
}
updateIdentityDisp, err := toIDispatchErr(oleutil.GetProperty(updateHistoryEntryDisp, "UpdateIdentity"))
if err != nil {
return nil, err
}
if updateIdentityDisp != nil {
if iUpdateHistoryEntry.UpdateIdentity, err = toIUpdateIdentity(updateIdentityDisp); err != nil {
return nil, err
}
}
return iUpdateHistoryEntry, nil
}

View file

@ -0,0 +1,44 @@
/*
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"
)
// IUpdateIdentity represents the unique identifier of an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdateidentity
type IUpdateIdentity struct {
disp *ole.IDispatch
RevisionNumber int32
UpdateID string
}
func toIUpdateIdentity(updateIdentityDisp *ole.IDispatch) (*IUpdateIdentity, error) {
var err error
iUpdateIdentity := &IUpdateIdentity{
disp: updateIdentityDisp,
}
if iUpdateIdentity.RevisionNumber, err = toInt32Err(oleutil.GetProperty(updateIdentityDisp, "RevisionNumber")); err != nil {
return nil, err
}
if iUpdateIdentity.UpdateID, err = toStringErr(oleutil.GetProperty(updateIdentityDisp, "UpdateID")); err != nil {
return nil, err
}
return iUpdateIdentity, 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

@ -0,0 +1,221 @@
/*
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"
)
// IUpdateInstaller installs or uninstalls updates from or onto a computer.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdateinstaller
type IUpdateInstaller struct {
disp *ole.IDispatch
AllowSourcePrompts bool
ClientApplicationID string
IsBusy bool
IsForced bool
ForceQuiet bool
// ParentHwnd HWND
// ParentWindow IUnknown
RebootRequiredBeforeInstallation bool
Updates []*IUpdate
}
func toIUpdateInstaller(updateInstallerDisp *ole.IDispatch) (*IUpdateInstaller, error) {
var err error
iUpdateInstaller := &IUpdateInstaller{
disp: updateInstallerDisp,
}
if iUpdateInstaller.AllowSourcePrompts, err = toBoolErr(oleutil.GetProperty(updateInstallerDisp, "AllowSourcePrompts")); err != nil {
return nil, err
}
if iUpdateInstaller.ClientApplicationID, err = toStringErr(oleutil.GetProperty(updateInstallerDisp, "ClientApplicationID")); err != nil {
return nil, err
}
if iUpdateInstaller.IsBusy, err = toBoolErr(oleutil.GetProperty(updateInstallerDisp, "IsBusy")); err != nil {
return nil, err
}
if iUpdateInstaller.IsForced, err = toBoolErr(oleutil.GetProperty(updateInstallerDisp, "IsForced")); err != nil {
return nil, err
}
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
}
updatesDisp, err := toIDispatchErr(oleutil.GetProperty(updateInstallerDisp, "Updates"))
if err != nil {
return nil, err
}
if updatesDisp != nil {
if iUpdateInstaller.Updates, err = toIUpdates(updatesDisp); err != nil {
return nil, err
}
}
return iUpdateInstaller, nil
}
// Install starts a synchronous installation of the updates.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller-install
func (iUpdateInstaller *IUpdateInstaller) Install(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
}
installationResultDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateInstaller.disp, "Install"))
if err != nil {
return nil, err
}
return toIInstallationResult(installationResultDisp)
}
// Finalizes updates that were previously staged or installed.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller4-commit
func (iUpdateInstaller *IUpdateInstaller) Commit(dwFlags int32) error {
_, err := toIDispatchErr(oleutil.CallMethod(iUpdateInstaller.disp, "Commit", dwFlags))
if err != nil {
return err
}
return nil
}
// Sets a Boolean value that indicates whether Windows Installer is forced to install the updates without user interaction.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller2-put_forcequiet
func (iUpdateInstaller *IUpdateInstaller) PutForceQuiet(value bool) error {
_, err := toIDispatchErr(oleutil.PutProperty(iUpdateInstaller.disp, "ForceQuiet", value))
if err != nil {
return err
}
iUpdateInstaller.ForceQuiet = value
return nil
}
// Sets a Boolean value that indicates whether to forcibly install or uninstall an update.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdateinstaller-put_isforced
func (iUpdateInstaller *IUpdateInstaller) PutIsForced(value bool) error {
_, err := toIDispatchErr(oleutil.PutProperty(iUpdateInstaller.disp, "IsForced", value))
if err != nil {
return err
}
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

@ -0,0 +1,177 @@
/*
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"
)
// IUpdateSearcher searches for updates on a server.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatesearcher
type IUpdateSearcher struct {
disp *ole.IDispatch
CanAutomaticallyUpgradeService bool
ClientApplicationID string
IncludePotentiallySupersededUpdates bool
Online bool
ServerSelection int32
ServiceID string
}
func toIUpdateSearcher(updateSearcherDisp *ole.IDispatch) (*IUpdateSearcher, error) {
var err error
iUpdateSearcher := &IUpdateSearcher{
disp: updateSearcherDisp,
}
if iUpdateSearcher.CanAutomaticallyUpgradeService, err = toBoolErr(oleutil.GetProperty(updateSearcherDisp, "CanAutomaticallyUpgradeService")); err != nil {
return nil, err
}
if iUpdateSearcher.ClientApplicationID, err = toStringErr(oleutil.GetProperty(updateSearcherDisp, "ClientApplicationID")); err != nil {
return nil, err
}
if iUpdateSearcher.IncludePotentiallySupersededUpdates, err = toBoolErr(oleutil.GetProperty(updateSearcherDisp, "IncludePotentiallySupersededUpdates")); err != nil {
return nil, err
}
if iUpdateSearcher.Online, err = toBoolErr(oleutil.GetProperty(updateSearcherDisp, "Online")); err != nil {
return nil, err
}
if iUpdateSearcher.ServerSelection, err = toInt32Err(oleutil.GetProperty(updateSearcherDisp, "ServerSelection")); err != nil {
return nil, err
}
if iUpdateSearcher.ServiceID, err = toStringErr(oleutil.GetProperty(updateSearcherDisp, "ServiceID")); err != nil {
return nil, err
}
return iUpdateSearcher, nil
}
// Search performs a synchronous search for updates. The search uses the search options that are currently configured.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesearcher-search
func (iUpdateSearcher *IUpdateSearcher) Search(criteria string) (*ISearchResult, error) {
searchResultDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSearcher.disp, "Search", criteria))
if err != nil {
return nil, err
}
return toISearchResult(searchResultDisp)
}
// QueryHistory synchronously queries the computer for the history of the update events.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesearcher-queryhistory
func (iUpdateSearcher *IUpdateSearcher) QueryHistory(startIndex int32, count int32) ([]*IUpdateHistoryEntry, error) {
updateHistoryEntriesDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSearcher.disp, "QueryHistory", startIndex, count))
if err != nil {
return nil, err
}
return toIUpdateHistoryEntries(updateHistoryEntriesDisp)
}
// 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"))
}
// QueryHistoryAll synchronously queries the computer for the history of all update events.
func (iUpdateSearcher *IUpdateSearcher) QueryHistoryAll() ([]*IUpdateHistoryEntry, error) {
count, err := iUpdateSearcher.GetTotalHistoryCount()
if err != nil {
return nil, err
}
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

@ -0,0 +1,100 @@
/*
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"
)
// IUpdateSession represents a session in which the caller can perform operations that involve updates.
// For example, this interface represents sessions in which the caller performs a search, download, installation, or uninstallation operation.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatesession
type IUpdateSession struct {
disp *ole.IDispatch
ClientApplicationID string
ReadOnly bool
WebProxy *IWebProxy
}
func toIUpdateSession(updateSessionDisp *ole.IDispatch) (*IUpdateSession, error) {
var err error
iUpdateSession := &IUpdateSession{
disp: updateSessionDisp,
}
if iUpdateSession.ClientApplicationID, err = toStringErr(oleutil.GetProperty(updateSessionDisp, "ClientApplicationID")); err != nil {
return nil, err
}
if iUpdateSession.ReadOnly, err = toBoolErr(oleutil.GetProperty(updateSessionDisp, "ReadOnly")); err != nil {
return nil, err
}
webProxyDisp, err := toIDispatchErr(oleutil.GetProperty(updateSessionDisp, "WebProxy"))
if err != nil {
return nil, err
}
if webProxyDisp != nil {
if iUpdateSession.WebProxy, err = toIWebProxy(webProxyDisp); err != nil {
return nil, err
}
}
return iUpdateSession, nil
}
// NewUpdateSession creates a new IUpdateSession interface.
func NewUpdateSession() (*IUpdateSession, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.Session")
if err != nil {
return nil, err
}
disp, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
return toIUpdateSession(disp)
}
// CreateUpdateDownloader returns an IUpdateDownloader interface for this session.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesession-createupdatedownloader
func (iUpdateSession *IUpdateSession) CreateUpdateDownloader() (*IUpdateDownloader, error) {
updateDownloaderDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSession.disp, "CreateUpdateDownloader"))
if err != nil {
return nil, err
}
return toIUpdateDownloader(updateDownloaderDisp)
}
// CreateUpdateInstaller returns an IUpdateInstaller interface for this session.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesession-createupdateinstaller
func (iUpdateSession *IUpdateSession) CreateUpdateInstaller() (*IUpdateInstaller, error) {
updateInstallerDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSession.disp, "CreateUpdateInstaller"))
if err != nil {
return nil, err
}
return toIUpdateInstaller(updateInstallerDisp)
}
// CreateUpdateSearcher returns an IUpdateSearcher interface for this session.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesession-createupdatesearcher
func (iUpdateSession *IUpdateSession) CreateUpdateSearcher() (*IUpdateSearcher, error) {
updateSearcherDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSession.disp, "CreateUpdateSearcher"))
if err != nil {
return nil, err
}
return toIUpdateSearcher(updateSearcherDisp)
}

View file

@ -0,0 +1,70 @@
/*
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"
)
// IWebProxy contains the HTTP proxy settings.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iwebproxy
type IWebProxy struct {
disp *ole.IDispatch
Address string
AutoDetect bool
BypassList []string
BypassProxyOnLocal bool
ReadOnly bool
UserName string
}
func toIWebProxy(webProxyDisp *ole.IDispatch) (*IWebProxy, error) {
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
}

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 (
"time"
"github.com/go-ole/go-ole"
)
func toIDispatchErr(result *ole.VARIANT, err error) (*ole.IDispatch, error) {
if err != nil {
return nil, err
}
return variantToIDispatch(result), nil
}
func toInt64Err(result *ole.VARIANT, err error) (int64, error) {
if err != nil {
return 0, err
}
return variantToInt64(result), nil
}
func toInt32Err(result *ole.VARIANT, err error) (int32, error) {
if err != nil {
return 0, err
}
return variantToInt32(result), nil
}
func toFloat64Err(result *ole.VARIANT, err error) (float64, error) {
if err != nil {
return 0, err
}
return variantToFloat64(result), nil
}
func toFloat32Err(result *ole.VARIANT, err error) (float32, error) {
if err != nil {
return 0, err
}
return variantToFloat32(result), nil
}
func toStringErr(result *ole.VARIANT, err error) (string, error) {
if err != nil {
return "", err
}
return variantToString(result), nil
}
func toBoolErr(result *ole.VARIANT, err error) (bool, error) {
if err != nil {
return false, err
}
return variantToBool(result), nil
}
func toTimeErr(result *ole.VARIANT, err error) (*time.Time, error) {
if err != nil {
return nil, err
}
return variantToTime(result), nil
}
func variantToIDispatch(v *ole.VARIANT) *ole.IDispatch {
value := v.Value()
if value == nil {
return nil
}
return v.ToIDispatch()
}
func variantToInt64(v *ole.VARIANT) int64 {
value := v.Value()
if value == nil {
return 0
}
return value.(int64)
}
func variantToInt32(v *ole.VARIANT) int32 {
value := v.Value()
if value == nil {
return 0
}
return value.(int32)
}
func variantToFloat64(v *ole.VARIANT) float64 {
value := v.Value()
if value == nil {
return 0
}
return value.(float64)
}
func variantToFloat32(v *ole.VARIANT) float32 {
value := v.Value()
if value == nil {
return 0
}
return value.(float32)
}
func variantToString(v *ole.VARIANT) string {
value := v.Value()
if value == nil {
return ""
}
return value.(string)
}
func variantToBool(v *ole.VARIANT) bool {
value := v.Value()
if value == nil {
return false
}
return value.(bool)
}
func variantToTime(v *ole.VARIANT) *time.Time {
value := v.Value()
if value == nil {
return nil
}
valueTime := value.(time.Time)
return &valueTime
}