Fix windowsupdate package missing in fresh clones

This commit is contained in:
Fimeg
2025-10-29 12:15:30 -04:00
parent 0d591e2e21
commit c48ea033fc
21 changed files with 1675 additions and 1 deletions

1
.gitignore vendored
View File

@@ -271,7 +271,6 @@ test-results/
dev/
# Development packages and scripts
aggregator-agent/pkg/
aggregator-server/scripts/
# Build artifacts

View File

@@ -0,0 +1,25 @@
/*
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
)

View File

@@ -0,0 +1,126 @@
/*
Copyright 2022 Zheng Dayu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// ICategory represents the category to which an update belongs.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-icategory
type ICategory struct {
disp *ole.IDispatch
CategoryID string
Children []*ICategory
Description string
Image *IImageInformation
Name string
Order int32
Parent *ICategory
Type string
Updates []*IUpdate
}
func toICategories(categoriesDisp *ole.IDispatch) ([]*ICategory, error) {
count, err := toInt32Err(oleutil.GetProperty(categoriesDisp, "Count"))
if err != nil {
return nil, err
}
categories := make([]*ICategory, 0, count)
for i := 0; i < int(count); i++ {
categoryDisp, err := toIDispatchErr(oleutil.GetProperty(categoriesDisp, "Item", i))
if err != nil {
return nil, err
}
category, err := toICategory(categoryDisp)
if err != nil {
return nil, err
}
categories = append(categories, category)
}
return categories, nil
}
func toICategory(categoryDisp *ole.IDispatch) (*ICategory, error) {
var err error
iCategory := &ICategory{
disp: categoryDisp,
}
if iCategory.CategoryID, err = toStringErr(oleutil.GetProperty(categoryDisp, "CategoryID")); err != nil {
return nil, err
}
childrenDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Children"))
if err != nil {
return nil, err
}
if childrenDisp != nil {
if iCategory.Children, err = toICategories(childrenDisp); err != nil {
return nil, err
}
}
if iCategory.Description, err = toStringErr(oleutil.GetProperty(categoryDisp, "Description")); err != nil {
return nil, err
}
imageDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Image"))
if err != nil {
return nil, err
}
if imageDisp != nil {
if iCategory.Image, err = toIImageInformation(imageDisp); err != nil {
return nil, err
}
}
if iCategory.Name, err = toStringErr(oleutil.GetProperty(categoryDisp, "Name")); err != nil {
return nil, err
}
if iCategory.Order, err = toInt32Err(oleutil.GetProperty(categoryDisp, "Order")); err != nil {
return nil, err
}
// parentDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Parent"))
// if err != nil {
// return nil, err
// }
// if parentDisp != nil {
// if iCategory.Parent, err = toICategory(parentDisp); err != nil {
// return nil, err
// }
// }
if iCategory.Type, err = toStringErr(oleutil.GetProperty(categoryDisp, "Type")); err != nil {
return nil, err
}
// updatesDisp, err := toIDispatchErr(oleutil.GetProperty(categoryDisp, "Updates"))
// if err != nil {
// return nil, err
// }
// if updatesDisp != nil {
// if iCategory.Updates, err = toIUpdates(updatesDisp); err != nil {
// return nil, err
// }
// }
return iCategory, nil
}

View File

@@ -0,0 +1,66 @@
/*
Copyright 2022 Zheng Dayu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IDownloadResult represents the result of a download operation.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-idownloadresult
type IDownloadResult struct {
disp *ole.IDispatch
HResult int32
ResultCode int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
}
func toIDownloadResult(downloadResultDisp *ole.IDispatch) (*IDownloadResult, error) {
var err error
iDownloadResult := &IDownloadResult{
disp: downloadResultDisp,
}
if iDownloadResult.HResult, err = toInt32Err(oleutil.GetProperty(downloadResultDisp, "HResult")); err != nil {
return nil, err
}
if iDownloadResult.ResultCode, err = toInt32Err(oleutil.GetProperty(downloadResultDisp, "ResultCode")); err != nil {
return nil, err
}
return iDownloadResult, nil
}
// GetUpdateResult returns an IUpdateDownloadResult interface that contains the download information for a specified update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-idownloadresult-getupdateresult
func (iDownloadResult *IDownloadResult) GetUpdateResult(updateIndex int32) (*IUpdateDownloadResult, error) {
var err error
iUpdateDownloadResult := &IUpdateDownloadResult{
disp: iDownloadResult.disp,
}
updatesDisp, err := toIDispatchErr(oleutil.CallMethod(iDownloadResult.disp, "GetUpdateResult", updateIndex))
if err != nil {
return nil, err
}
if iUpdateDownloadResult.HResult, err = toInt32Err(oleutil.GetProperty(updatesDisp, "HResult")); err != nil {
return nil, err
}
if iUpdateDownloadResult.ResultCode, err = toInt32Err(oleutil.GetProperty(updatesDisp, "ResultCode")); err != nil {
return nil, err
}
return iUpdateDownloadResult, nil
}

View File

@@ -0,0 +1,33 @@
/*
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"
)
// 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) {
// TODO
return nil, nil
}

View File

@@ -0,0 +1,33 @@
/*
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"
)
// 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) {
// TODO
return nil, nil
}

View File

@@ -0,0 +1,71 @@
/*
Copyright 2022 Zheng Dayu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IInstallationResult represents the result of an installation or uninstallation.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iinstallationresult
type IInstallationResult struct {
disp *ole.IDispatch
HResult int32
RebootRequired bool
ResultCode int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
}
func toIInstallationResult(installationResultDisp *ole.IDispatch) (*IInstallationResult, error) {
var err error
iInstallationResult := &IInstallationResult{
disp: installationResultDisp,
}
if iInstallationResult.HResult, err = toInt32Err(oleutil.GetProperty(installationResultDisp, "HResult")); err != nil {
return nil, err
}
if iInstallationResult.RebootRequired, err = toBoolErr(oleutil.GetProperty(installationResultDisp, "RebootRequired")); err != nil {
return nil, err
}
if iInstallationResult.ResultCode, err = toInt32Err(oleutil.GetProperty(installationResultDisp, "ResultCode")); err != nil {
return nil, err
}
return iInstallationResult, nil
}
// GetUpdateResult returns an IInstallationResult interface that contains the installation information for a specified update.
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iinstallationresult
func (iInstallationResult *IInstallationResult) GetUpdateResult(updateIndex int32) (*IInstallationResult, error) {
var err error
iUpdateInstallationResult := &IInstallationResult{
disp: iInstallationResult.disp,
}
updatesDisp, err := toIDispatchErr(oleutil.CallMethod(iInstallationResult.disp, "GetUpdateResult", updateIndex))
if err != nil {
return nil, err
}
if iUpdateInstallationResult.HResult, err = toInt32Err(oleutil.GetProperty(updatesDisp, "HResult")); err != nil {
return nil, err
}
if iUpdateInstallationResult.ResultCode, err = toInt32Err(oleutil.GetProperty(updatesDisp, "ResultCode")); err != nil {
return nil, err
}
return iUpdateInstallationResult, nil
}

View File

@@ -0,0 +1,72 @@
/*
Copyright 2022 Zheng Dayu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// ISearchResult represents the result of a search.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-isearchresult
type ISearchResult struct {
disp *ole.IDispatch
ResultCode int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
RootCategories []*ICategory
Updates []*IUpdate
Warnings []*IUpdateException
}
func toISearchResult(searchResultDisp *ole.IDispatch) (*ISearchResult, error) {
var err error
iSearchResult := &ISearchResult{
disp: searchResultDisp,
}
if iSearchResult.ResultCode, err = toInt32Err(oleutil.GetProperty(searchResultDisp, "ResultCode")); err != nil {
return nil, err
}
rootCategoriesDisp, err := toIDispatchErr(oleutil.GetProperty(searchResultDisp, "RootCategories"))
if err != nil {
return nil, err
}
if rootCategoriesDisp != nil {
if iSearchResult.RootCategories, err = toICategories(rootCategoriesDisp); err != nil {
return nil, err
}
}
updatesDisp, err := toIDispatchErr(oleutil.GetProperty(searchResultDisp, "Updates"))
if err != nil {
return nil, err
}
if updatesDisp != nil {
if iSearchResult.Updates, err = toIUpdates(updatesDisp); err != nil {
return nil, err
}
}
warningsDisp, err := toIDispatchErr(oleutil.GetProperty(searchResultDisp, "Warnings"))
if err != nil {
return nil, err
}
if warningsDisp != nil {
if iSearchResult.Warnings, err = toIUpdateExceptions(warningsDisp); err != nil {
return nil, err
}
}
return iSearchResult, nil
}

View File

@@ -0,0 +1,34 @@
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-istringcollection
func iStringCollectionToStringArrayErr(disp *ole.IDispatch, err error) ([]string, error) {
if err != nil {
return nil, err
}
if disp == nil {
return nil, nil
}
count, err := toInt32Err(oleutil.GetProperty(disp, "Count"))
if err != nil {
return nil, err
}
stringCollection := make([]string, count)
for i := 0; i < int(count); i++ {
str, err := toStringErr(oleutil.GetProperty(disp, "Item", i))
if err != nil {
return nil, err
}
stringCollection[i] = str
}
return stringCollection, nil
}

View File

@@ -0,0 +1,363 @@
/*
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
}
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
}
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
}

View File

@@ -0,0 +1,30 @@
/*
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"
)
// 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) {
// TODO
return nil, nil
}

View File

@@ -0,0 +1,78 @@
/*
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)
}

View File

@@ -0,0 +1,31 @@
/*
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"
)
// 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) {
// TODO
return nil, nil
}

View File

@@ -0,0 +1,32 @@
/*
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"
)
// 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) {
// TODO
return nil, nil
}

View File

@@ -0,0 +1,135 @@
/*
Copyright 2022 Zheng Dayu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package windowsupdate
import (
"time"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateHistoryEntry represents the recorded history of an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatehistoryentry
type IUpdateHistoryEntry struct {
disp *ole.IDispatch
ClientApplicationID string
Date *time.Time
Description string
HResult int32
Operation int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-updateoperation
ResultCode int32 // enum https://docs.microsoft.com/en-us/windows/win32/api/wuapi/ne-wuapi-operationresultcode
ServerSelection int32 // enum
ServiceID string
SupportUrl string
Title string
UninstallationNotes string
UninstallationSteps []string
UnmappedResultCode int32
UpdateIdentity *IUpdateIdentity
}
func toIUpdateHistoryEntries(updateHistoryEntriesDisp *ole.IDispatch) ([]*IUpdateHistoryEntry, error) {
count, err := toInt32Err(oleutil.GetProperty(updateHistoryEntriesDisp, "Count"))
if err != nil {
return nil, err
}
updateHistoryEntries := make([]*IUpdateHistoryEntry, 0, count)
for i := 0; i < int(count); i++ {
updateHistoryEntryDisp, err := toIDispatchErr(oleutil.GetProperty(updateHistoryEntriesDisp, "Item", i))
if err != nil {
return nil, err
}
updateHistoryEntry, err := toIUpdateHistoryEntry(updateHistoryEntryDisp)
if err != nil {
return nil, err
}
updateHistoryEntries = append(updateHistoryEntries, updateHistoryEntry)
}
return updateHistoryEntries, nil
}
func toIUpdateHistoryEntry(updateHistoryEntryDisp *ole.IDispatch) (*IUpdateHistoryEntry, error) {
var err error
iUpdateHistoryEntry := &IUpdateHistoryEntry{
disp: updateHistoryEntryDisp,
}
if iUpdateHistoryEntry.ClientApplicationID, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "ClientApplicationID")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.Date, err = toTimeErr(oleutil.GetProperty(updateHistoryEntryDisp, "Date")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.Description, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "Description")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.HResult, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "HResult")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.Operation, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "Operation")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.ResultCode, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "ResultCode")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.ServerSelection, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "ServerSelection")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.ServiceID, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "ServiceID")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.SupportUrl, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "SupportUrl")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.Title, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "Title")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.UninstallationNotes, err = toStringErr(oleutil.GetProperty(updateHistoryEntryDisp, "UninstallationNotes")); err != nil {
return nil, err
}
if iUpdateHistoryEntry.UninstallationSteps, err = iStringCollectionToStringArrayErr(toIDispatchErr(oleutil.GetProperty(updateHistoryEntryDisp, "UninstallationSteps"))); err != nil {
return nil, err
}
if iUpdateHistoryEntry.UnmappedResultCode, err = toInt32Err(oleutil.GetProperty(updateHistoryEntryDisp, "UnmappedResultCode")); err != nil {
return nil, err
}
updateIdentityDisp, err := toIDispatchErr(oleutil.GetProperty(updateHistoryEntryDisp, "UpdateIdentity"))
if err != nil {
return nil, err
}
if updateIdentityDisp != nil {
if iUpdateHistoryEntry.UpdateIdentity, err = toIUpdateIdentity(updateIdentityDisp); err != nil {
return nil, err
}
}
return iUpdateHistoryEntry, nil
}

View File

@@ -0,0 +1,44 @@
/*
Copyright 2022 Zheng Dayu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateIdentity represents the unique identifier of an update.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdateidentity
type IUpdateIdentity struct {
disp *ole.IDispatch
RevisionNumber int32
UpdateID string
}
func toIUpdateIdentity(updateIdentityDisp *ole.IDispatch) (*IUpdateIdentity, error) {
var err error
iUpdateIdentity := &IUpdateIdentity{
disp: updateIdentityDisp,
}
if iUpdateIdentity.RevisionNumber, err = toInt32Err(oleutil.GetProperty(updateIdentityDisp, "RevisionNumber")); err != nil {
return nil, err
}
if iUpdateIdentity.UpdateID, err = toStringErr(oleutil.GetProperty(updateIdentityDisp, "UpdateID")); err != nil {
return nil, err
}
return iUpdateIdentity, nil
}

View File

@@ -0,0 +1,127 @@
/*
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
}

View File

@@ -0,0 +1,99 @@
/*
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) {
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)
}

View File

@@ -0,0 +1,100 @@
/*
Copyright 2022 Zheng Dayu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package windowsupdate
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// IUpdateSession represents a session in which the caller can perform operations that involve updates.
// For example, this interface represents sessions in which the caller performs a search, download, installation, or uninstallation operation.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nn-wuapi-iupdatesession
type IUpdateSession struct {
disp *ole.IDispatch
ClientApplicationID string
ReadOnly bool
WebProxy *IWebProxy
}
func toIUpdateSession(updateSessionDisp *ole.IDispatch) (*IUpdateSession, error) {
var err error
iUpdateSession := &IUpdateSession{
disp: updateSessionDisp,
}
if iUpdateSession.ClientApplicationID, err = toStringErr(oleutil.GetProperty(updateSessionDisp, "ClientApplicationID")); err != nil {
return nil, err
}
if iUpdateSession.ReadOnly, err = toBoolErr(oleutil.GetProperty(updateSessionDisp, "ReadOnly")); err != nil {
return nil, err
}
webProxyDisp, err := toIDispatchErr(oleutil.GetProperty(updateSessionDisp, "WebProxy"))
if err != nil {
return nil, err
}
if webProxyDisp != nil {
if iUpdateSession.WebProxy, err = toIWebProxy(webProxyDisp); err != nil {
return nil, err
}
}
return iUpdateSession, nil
}
// NewUpdateSession creates a new IUpdateSession interface.
func NewUpdateSession() (*IUpdateSession, error) {
unknown, err := oleutil.CreateObject("Microsoft.Update.Session")
if err != nil {
return nil, err
}
disp, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return nil, err
}
return toIUpdateSession(disp)
}
// CreateUpdateDownloader returns an IUpdateDownloader interface for this session.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesession-createupdatedownloader
func (iUpdateSession *IUpdateSession) CreateUpdateDownloader() (*IUpdateDownloader, error) {
updateDownloaderDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSession.disp, "CreateUpdateDownloader"))
if err != nil {
return nil, err
}
return toIUpdateDownloader(updateDownloaderDisp)
}
// CreateUpdateInstaller returns an IUpdateInstaller interface for this session.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesession-createupdateinstaller
func (iUpdateSession *IUpdateSession) CreateUpdateInstaller() (*IUpdateInstaller, error) {
updateInstallerDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSession.disp, "CreateUpdateInstaller"))
if err != nil {
return nil, err
}
return toIUpdateInstaller(updateInstallerDisp)
}
// CreateUpdateSearcher returns an IUpdateSearcher interface for this session.
// https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesession-createupdatesearcher
func (iUpdateSession *IUpdateSession) CreateUpdateSearcher() (*IUpdateSearcher, error) {
updateSearcherDisp, err := toIDispatchErr(oleutil.CallMethod(iUpdateSession.disp, "CreateUpdateSearcher"))
if err != nil {
return nil, err
}
return toIUpdateSearcher(updateSearcherDisp)
}

View File

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

View File

@@ -0,0 +1,141 @@
/*
Copyright 2022 Zheng Dayu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package windowsupdate
import (
"time"
"github.com/go-ole/go-ole"
)
func toIDispatchErr(result *ole.VARIANT, err error) (*ole.IDispatch, error) {
if err != nil {
return nil, err
}
return variantToIDispatch(result), nil
}
func toInt64Err(result *ole.VARIANT, err error) (int64, error) {
if err != nil {
return 0, err
}
return variantToInt64(result), nil
}
func toInt32Err(result *ole.VARIANT, err error) (int32, error) {
if err != nil {
return 0, err
}
return variantToInt32(result), nil
}
func toFloat64Err(result *ole.VARIANT, err error) (float64, error) {
if err != nil {
return 0, err
}
return variantToFloat64(result), nil
}
func toFloat32Err(result *ole.VARIANT, err error) (float32, error) {
if err != nil {
return 0, err
}
return variantToFloat32(result), nil
}
func toStringErr(result *ole.VARIANT, err error) (string, error) {
if err != nil {
return "", err
}
return variantToString(result), nil
}
func toBoolErr(result *ole.VARIANT, err error) (bool, error) {
if err != nil {
return false, err
}
return variantToBool(result), nil
}
func toTimeErr(result *ole.VARIANT, err error) (*time.Time, error) {
if err != nil {
return nil, err
}
return variantToTime(result), nil
}
func variantToIDispatch(v *ole.VARIANT) *ole.IDispatch {
value := v.Value()
if value == nil {
return nil
}
return v.ToIDispatch()
}
func variantToInt64(v *ole.VARIANT) int64 {
value := v.Value()
if value == nil {
return 0
}
return value.(int64)
}
func variantToInt32(v *ole.VARIANT) int32 {
value := v.Value()
if value == nil {
return 0
}
return value.(int32)
}
func variantToFloat64(v *ole.VARIANT) float64 {
value := v.Value()
if value == nil {
return 0
}
return value.(float64)
}
func variantToFloat32(v *ole.VARIANT) float32 {
value := v.Value()
if value == nil {
return 0
}
return value.(float32)
}
func variantToString(v *ole.VARIANT) string {
value := v.Value()
if value == nil {
return ""
}
return value.(string)
}
func variantToBool(v *ole.VARIANT) bool {
value := v.Value()
if value == nil {
return false
}
return value.(bool)
}
func variantToTime(v *ole.VARIANT) *time.Time {
value := v.Value()
if value == nil {
return nil
}
valueTime := value.(time.Time)
return &valueTime
}