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:
commit
67e26be2d9
838 changed files with 157302 additions and 0 deletions
154
agent/pkg/windowsupdate/enum.go
Normal file
154
agent/pkg/windowsupdate/enum.go
Normal 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
|
||||
)
|
||||
143
agent/pkg/windowsupdate/iautomaticupdates.go
Normal file
143
agent/pkg/windowsupdate/iautomaticupdates.go
Normal 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
|
||||
}
|
||||
124
agent/pkg/windowsupdate/iautomaticupdatessettings.go
Normal file
124
agent/pkg/windowsupdate/iautomaticupdatessettings.go
Normal 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
|
||||
}
|
||||
130
agent/pkg/windowsupdate/icategory.go
Normal file
130
agent/pkg/windowsupdate/icategory.go
Normal 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
|
||||
}
|
||||
77
agent/pkg/windowsupdate/idownloadjob.go
Normal file
77
agent/pkg/windowsupdate/idownloadjob.go
Normal 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)
|
||||
}
|
||||
86
agent/pkg/windowsupdate/idownloadprogress.go
Normal file
86
agent/pkg/windowsupdate/idownloadprogress.go
Normal 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)
|
||||
}
|
||||
66
agent/pkg/windowsupdate/idownloadresult.go
Normal file
66
agent/pkg/windowsupdate/idownloadresult.go
Normal 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
|
||||
}
|
||||
54
agent/pkg/windowsupdate/iimageinformation.go
Normal file
54
agent/pkg/windowsupdate/iimageinformation.go
Normal 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
|
||||
}
|
||||
54
agent/pkg/windowsupdate/iinstallationbehavior.go
Normal file
54
agent/pkg/windowsupdate/iinstallationbehavior.go
Normal 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
|
||||
}
|
||||
77
agent/pkg/windowsupdate/iinstallationjob.go
Normal file
77
agent/pkg/windowsupdate/iinstallationjob.go
Normal 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)
|
||||
}
|
||||
61
agent/pkg/windowsupdate/iinstallationprogress.go
Normal file
61
agent/pkg/windowsupdate/iinstallationprogress.go
Normal 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)
|
||||
}
|
||||
71
agent/pkg/windowsupdate/iinstallationresult.go
Normal file
71
agent/pkg/windowsupdate/iinstallationresult.go
Normal 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
|
||||
}
|
||||
56
agent/pkg/windowsupdate/isearchjob.go
Normal file
56
agent/pkg/windowsupdate/isearchjob.go
Normal 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
|
||||
}
|
||||
72
agent/pkg/windowsupdate/isearchresult.go
Normal file
72
agent/pkg/windowsupdate/isearchresult.go
Normal 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
|
||||
}
|
||||
144
agent/pkg/windowsupdate/istringcollection.go
Normal file
144
agent/pkg/windowsupdate/istringcollection.go
Normal 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
|
||||
}
|
||||
59
agent/pkg/windowsupdate/isysteminformation.go
Normal file
59
agent/pkg/windowsupdate/isysteminformation.go
Normal 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
|
||||
}
|
||||
415
agent/pkg/windowsupdate/iupdate.go
Normal file
415
agent/pkg/windowsupdate/iupdate.go
Normal 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
|
||||
}
|
||||
134
agent/pkg/windowsupdate/iupdatecollection.go
Normal file
134
agent/pkg/windowsupdate/iupdatecollection.go
Normal 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
|
||||
}
|
||||
62
agent/pkg/windowsupdate/iupdatedownloadcontent.go
Normal file
62
agent/pkg/windowsupdate/iupdatedownloadcontent.go
Normal 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
|
||||
}
|
||||
136
agent/pkg/windowsupdate/iupdatedownloader.go
Normal file
136
agent/pkg/windowsupdate/iupdatedownloader.go
Normal 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
|
||||
}
|
||||
44
agent/pkg/windowsupdate/iupdatedownloadresult.go
Normal file
44
agent/pkg/windowsupdate/iupdatedownloadresult.go
Normal 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
|
||||
}
|
||||
72
agent/pkg/windowsupdate/iupdateexception.go
Normal file
72
agent/pkg/windowsupdate/iupdateexception.go
Normal 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
|
||||
}
|
||||
135
agent/pkg/windowsupdate/iupdatehistoryentry.go
Normal file
135
agent/pkg/windowsupdate/iupdatehistoryentry.go
Normal 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
|
||||
}
|
||||
44
agent/pkg/windowsupdate/iupdateidentity.go
Normal file
44
agent/pkg/windowsupdate/iupdateidentity.go
Normal 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
|
||||
}
|
||||
51
agent/pkg/windowsupdate/iupdateinstallationresult.go
Normal file
51
agent/pkg/windowsupdate/iupdateinstallationresult.go
Normal 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
|
||||
}
|
||||
221
agent/pkg/windowsupdate/iupdateinstaller.go
Normal file
221
agent/pkg/windowsupdate/iupdateinstaller.go
Normal 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
|
||||
}
|
||||
177
agent/pkg/windowsupdate/iupdatesearcher.go
Normal file
177
agent/pkg/windowsupdate/iupdatesearcher.go
Normal 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
|
||||
}
|
||||
133
agent/pkg/windowsupdate/iupdateservice.go
Normal file
133
agent/pkg/windowsupdate/iupdateservice.go
Normal 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
|
||||
}
|
||||
141
agent/pkg/windowsupdate/iupdateservicemanager.go
Normal file
141
agent/pkg/windowsupdate/iupdateservicemanager.go
Normal 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)
|
||||
}
|
||||
57
agent/pkg/windowsupdate/iupdateserviceregistration.go
Normal file
57
agent/pkg/windowsupdate/iupdateserviceregistration.go
Normal 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
|
||||
}
|
||||
100
agent/pkg/windowsupdate/iupdatesession.go
Normal file
100
agent/pkg/windowsupdate/iupdatesession.go
Normal 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)
|
||||
}
|
||||
70
agent/pkg/windowsupdate/iwebproxy.go
Normal file
70
agent/pkg/windowsupdate/iwebproxy.go
Normal 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
|
||||
}
|
||||
178
agent/pkg/windowsupdate/iwindowsdriverupdate.go
Normal file
178
agent/pkg/windowsupdate/iwindowsdriverupdate.go
Normal 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
|
||||
}
|
||||
101
agent/pkg/windowsupdate/iwindowsupdateagentinfo.go
Normal file
101
agent/pkg/windowsupdate/iwindowsupdateagentinfo.go
Normal 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
|
||||
}
|
||||
141
agent/pkg/windowsupdate/oleconv.go
Normal file
141
agent/pkg/windowsupdate/oleconv.go
Normal 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
|
||||
}
|
||||
Loading…
Reference in a new issue