Fix windowsupdate package missing in fresh clones
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -271,7 +271,6 @@ test-results/
|
|||||||
dev/
|
dev/
|
||||||
|
|
||||||
# Development packages and scripts
|
# Development packages and scripts
|
||||||
aggregator-agent/pkg/
|
|
||||||
aggregator-server/scripts/
|
aggregator-server/scripts/
|
||||||
|
|
||||||
# Build artifacts
|
# Build artifacts
|
||||||
|
|||||||
25
aggregator-agent/pkg/windowsupdate/enum.go
Normal file
25
aggregator-agent/pkg/windowsupdate/enum.go
Normal 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
|
||||||
|
)
|
||||||
126
aggregator-agent/pkg/windowsupdate/icategory.go
Normal file
126
aggregator-agent/pkg/windowsupdate/icategory.go
Normal 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
|
||||||
|
}
|
||||||
66
aggregator-agent/pkg/windowsupdate/idownloadresult.go
Normal file
66
aggregator-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
|
||||||
|
}
|
||||||
33
aggregator-agent/pkg/windowsupdate/iimageinformation.go
Normal file
33
aggregator-agent/pkg/windowsupdate/iimageinformation.go
Normal 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
|
||||||
|
}
|
||||||
33
aggregator-agent/pkg/windowsupdate/iinstallationbehavior.go
Normal file
33
aggregator-agent/pkg/windowsupdate/iinstallationbehavior.go
Normal 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
|
||||||
|
}
|
||||||
71
aggregator-agent/pkg/windowsupdate/iinstallationresult.go
Normal file
71
aggregator-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
|
||||||
|
}
|
||||||
72
aggregator-agent/pkg/windowsupdate/isearchresult.go
Normal file
72
aggregator-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
|
||||||
|
}
|
||||||
34
aggregator-agent/pkg/windowsupdate/istringcollection.go
Normal file
34
aggregator-agent/pkg/windowsupdate/istringcollection.go
Normal 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
|
||||||
|
}
|
||||||
363
aggregator-agent/pkg/windowsupdate/iupdate.go
Normal file
363
aggregator-agent/pkg/windowsupdate/iupdate.go
Normal 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
|
||||||
|
}
|
||||||
30
aggregator-agent/pkg/windowsupdate/iupdatedownloadcontent.go
Normal file
30
aggregator-agent/pkg/windowsupdate/iupdatedownloadcontent.go
Normal 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
|
||||||
|
}
|
||||||
78
aggregator-agent/pkg/windowsupdate/iupdatedownloader.go
Normal file
78
aggregator-agent/pkg/windowsupdate/iupdatedownloader.go
Normal 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)
|
||||||
|
}
|
||||||
31
aggregator-agent/pkg/windowsupdate/iupdatedownloadresult.go
Normal file
31
aggregator-agent/pkg/windowsupdate/iupdatedownloadresult.go
Normal 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
|
||||||
|
}
|
||||||
32
aggregator-agent/pkg/windowsupdate/iupdateexception.go
Normal file
32
aggregator-agent/pkg/windowsupdate/iupdateexception.go
Normal 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
|
||||||
|
}
|
||||||
135
aggregator-agent/pkg/windowsupdate/iupdatehistoryentry.go
Normal file
135
aggregator-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
aggregator-agent/pkg/windowsupdate/iupdateidentity.go
Normal file
44
aggregator-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
|
||||||
|
}
|
||||||
127
aggregator-agent/pkg/windowsupdate/iupdateinstaller.go
Normal file
127
aggregator-agent/pkg/windowsupdate/iupdateinstaller.go
Normal 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
|
||||||
|
}
|
||||||
99
aggregator-agent/pkg/windowsupdate/iupdatesearcher.go
Normal file
99
aggregator-agent/pkg/windowsupdate/iupdatesearcher.go
Normal 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)
|
||||||
|
}
|
||||||
100
aggregator-agent/pkg/windowsupdate/iupdatesession.go
Normal file
100
aggregator-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)
|
||||||
|
}
|
||||||
35
aggregator-agent/pkg/windowsupdate/iwebproxy.go
Normal file
35
aggregator-agent/pkg/windowsupdate/iwebproxy.go
Normal 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
|
||||||
|
}
|
||||||
141
aggregator-agent/pkg/windowsupdate/oleconv.go
Normal file
141
aggregator-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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user