diff --git a/Taskfile.yml b/Taskfile.yml index ec53990..ffeea8d 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -9,11 +9,6 @@ tasks: - git add . - git commit -m "Updated mappings" - gofmt: - dir: pkg/webview2 - cmds: - - go fmt - test: cmds: - go test ./... @@ -22,7 +17,6 @@ tasks: dir: scripts cmds: - go run update_version_mapping.go - - task: gofmt - go fmt update_version_mapping.go - task: test - task: commit @@ -31,7 +25,6 @@ tasks: dir: scripts cmds: - go run update_version_mapping.go -forced - - task: gofmt - go fmt update_version_mapping.go - task: test - task: commit diff --git a/pkg/webview2/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go b/pkg/webview2/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go index 23e84b4..f6932de 100644 --- a/pkg/webview2/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go +++ b/pkg/webview2/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go @@ -5,8 +5,8 @@ package webview2 type COREWEBVIEW2_PHYSICAL_KEY_STATUS struct { RepeatCount uint32 ScanCode uint32 - IsExtendedKey bool - IsMenuKeyDown bool - WasKeyDown bool - IsKeyReleased bool + IsExtendedKey int32 + IsMenuKeyDown int32 + WasKeyDown int32 + IsKeyReleased int32 } diff --git a/pkg/webview2/ICoreWebView2.go b/pkg/webview2/ICoreWebView2.go index 9b0af89..b0d4b55 100644 --- a/pkg/webview2/ICoreWebView2.go +++ b/pkg/webview2/ICoreWebView2.go @@ -79,6 +79,19 @@ func (i *ICoreWebView2) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetSettings() (*ICoreWebView2Settings, error) { var settings *ICoreWebView2Settings @@ -99,7 +112,7 @@ func (i *ICoreWebView2) GetSource() (string, error) { hr, _, _ := i.Vtbl.GetSource.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_uri)), + uintptr(unsafe.Pointer(&_uri)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -165,7 +178,7 @@ func (i *ICoreWebView2) RemoveNavigationStarting(token EventRegistrationToken) e hr, _, _ := i.Vtbl.RemoveNavigationStarting.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -192,7 +205,7 @@ func (i *ICoreWebView2) RemoveContentLoading(token EventRegistrationToken) error hr, _, _ := i.Vtbl.RemoveContentLoading.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -219,7 +232,7 @@ func (i *ICoreWebView2) RemoveSourceChanged(token EventRegistrationToken) error hr, _, _ := i.Vtbl.RemoveSourceChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -246,7 +259,7 @@ func (i *ICoreWebView2) RemoveHistoryChanged(token EventRegistrationToken) error hr, _, _ := i.Vtbl.RemoveHistoryChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -273,7 +286,7 @@ func (i *ICoreWebView2) RemoveNavigationCompleted(token EventRegistrationToken) hr, _, _ := i.Vtbl.RemoveNavigationCompleted.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -300,7 +313,7 @@ func (i *ICoreWebView2) RemoveFrameNavigationStarting(token EventRegistrationTok hr, _, _ := i.Vtbl.RemoveFrameNavigationStarting.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -327,7 +340,7 @@ func (i *ICoreWebView2) RemoveFrameNavigationCompleted(token EventRegistrationTo hr, _, _ := i.Vtbl.RemoveFrameNavigationCompleted.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -354,7 +367,7 @@ func (i *ICoreWebView2) RemoveScriptDialogOpening(token EventRegistrationToken) hr, _, _ := i.Vtbl.RemoveScriptDialogOpening.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -381,7 +394,7 @@ func (i *ICoreWebView2) RemovePermissionRequested(token EventRegistrationToken) hr, _, _ := i.Vtbl.RemovePermissionRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -408,7 +421,7 @@ func (i *ICoreWebView2) RemoveProcessFailed(token EventRegistrationToken) error hr, _, _ := i.Vtbl.RemoveProcessFailed.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -552,7 +565,7 @@ func (i *ICoreWebView2) RemoveWebMessageReceived(token EventRegistrationToken) e hr, _, _ := i.Vtbl.RemoveWebMessageReceived.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -703,7 +716,7 @@ func (i *ICoreWebView2) RemoveNewWindowRequested(token EventRegistrationToken) e hr, _, _ := i.Vtbl.RemoveNewWindowRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -730,7 +743,7 @@ func (i *ICoreWebView2) RemoveDocumentTitleChanged(token EventRegistrationToken) hr, _, _ := i.Vtbl.RemoveDocumentTitleChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -744,7 +757,7 @@ func (i *ICoreWebView2) GetDocumentTitle() (string, error) { hr, _, _ := i.Vtbl.GetDocumentTitle.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_title)), + uintptr(unsafe.Pointer(&_title)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -822,7 +835,7 @@ func (i *ICoreWebView2) RemoveContainsFullScreenElementChanged(token EventRegist hr, _, _ := i.Vtbl.RemoveContainsFullScreenElementChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -865,7 +878,7 @@ func (i *ICoreWebView2) RemoveWebResourceRequested(token EventRegistrationToken) hr, _, _ := i.Vtbl.RemoveWebResourceRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -930,7 +943,7 @@ func (i *ICoreWebView2) RemoveWindowCloseRequested(token EventRegistrationToken) hr, _, _ := i.Vtbl.RemoveWindowCloseRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2AcceleratorKeyPressedEventArgs.go b/pkg/webview2/ICoreWebView2AcceleratorKeyPressedEventArgs.go index f4f632e..1757e6b 100644 --- a/pkg/webview2/ICoreWebView2AcceleratorKeyPressedEventArgs.go +++ b/pkg/webview2/ICoreWebView2AcceleratorKeyPressedEventArgs.go @@ -27,6 +27,19 @@ func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventKind() (COREWEBVIEW2_KEY_EVENT_KIND, error) { var keyEventKind COREWEBVIEW2_KEY_EVENT_KIND @@ -41,9 +54,9 @@ func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventKind() (COREWEB return keyEventKind, nil } -func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetVirtualKey() (uint, error) { +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetVirtualKey() (uint32, error) { - var virtualKey uint + var virtualKey uint32 hr, _, _ := i.Vtbl.GetVirtualKey.Call( uintptr(unsafe.Pointer(i)), @@ -55,9 +68,9 @@ func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetVirtualKey() (uint, err return virtualKey, nil } -func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventLParam() (int, error) { +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventLParam() (int32, error) { - var lParam int + var lParam int32 hr, _, _ := i.Vtbl.GetKeyEventLParam.Call( uintptr(unsafe.Pointer(i)), @@ -103,7 +116,7 @@ func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) PutHandled(handled bool) e hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&handled)), + boolToUintptr(handled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2AcceleratorKeyPressedEventArgs2.go b/pkg/webview2/ICoreWebView2AcceleratorKeyPressedEventArgs2.go index c73c39b..104767c 100644 --- a/pkg/webview2/ICoreWebView2AcceleratorKeyPressedEventArgs2.go +++ b/pkg/webview2/ICoreWebView2AcceleratorKeyPressedEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2AcceleratorKeyPressedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2AcceleratorKeyPressedEventArgsVtbl GetIsBrowserAcceleratorKeyEnabled ComProc PutIsBrowserAcceleratorKeyEnabled ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2AcceleratorKeyPressedEventArgs2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2AcceleratorKeyPressedEventArgs2() *ICoreWebView2AcceleratorKeyPressedEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetICoreWebView2AcceleratorKeyPressedEventArgs2() *ICoreWebView2AcceleratorKeyPressedEventArgs2 { var result *ICoreWebView2AcceleratorKeyPressedEventArgs2 iidICoreWebView2AcceleratorKeyPressedEventArgs2 := NewGUID("{03b2c8c8-7799-4e34-bd66-ed26aa85f2bf}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2AcceleratorKeyPressedEventArgs2)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2AcceleratorKeyPressedEventArgs2) PutIsBrowserAcceleratorKe hr, _, _ := i.Vtbl.PutIsBrowserAcceleratorKeyEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler.go b/pkg/webview2/ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler.go index 1a3d86c..6334cc6 100644 --- a/pkg/webview2/ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler.go +++ b/pkg/webview2/ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler.go @@ -33,13 +33,13 @@ func ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerIUnknownRel return this.impl.Release() } -func ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerInvoke(this *ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler, errorCode uintptr, result string) uintptr { +func ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerInvoke(this *ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler, errorCode uintptr, result *uint16) uintptr { return this.impl.AddScriptToExecuteOnDocumentCreatedCompleted(errorCode, result) } type ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerImpl interface { IUnknownImpl - AddScriptToExecuteOnDocumentCreatedCompleted(errorCode uintptr, result string) uintptr + AddScriptToExecuteOnDocumentCreatedCompleted(errorCode uintptr, result *uint16) uintptr } var ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerFn = ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerVtbl{ diff --git a/pkg/webview2/ICoreWebView2BasicAuthenticationRequestedEventArgs.go b/pkg/webview2/ICoreWebView2BasicAuthenticationRequestedEventArgs.go index e820b24..71ca2a9 100644 --- a/pkg/webview2/ICoreWebView2BasicAuthenticationRequestedEventArgs.go +++ b/pkg/webview2/ICoreWebView2BasicAuthenticationRequestedEventArgs.go @@ -27,13 +27,26 @@ func (i *ICoreWebView2BasicAuthenticationRequestedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2BasicAuthenticationRequestedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2BasicAuthenticationRequestedEventArgs) GetUri() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -50,7 +63,7 @@ func (i *ICoreWebView2BasicAuthenticationRequestedEventArgs) GetChallenge() (str hr, _, _ := i.Vtbl.GetChallenge.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_challenge)), + uintptr(unsafe.Pointer(&_challenge)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -95,7 +108,7 @@ func (i *ICoreWebView2BasicAuthenticationRequestedEventArgs) PutCancel(cancel bo hr, _, _ := i.Vtbl.PutCancel.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&cancel)), + boolToUintptr(cancel), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2BasicAuthenticationResponse.go b/pkg/webview2/ICoreWebView2BasicAuthenticationResponse.go index 2a5f980..7089647 100644 --- a/pkg/webview2/ICoreWebView2BasicAuthenticationResponse.go +++ b/pkg/webview2/ICoreWebView2BasicAuthenticationResponse.go @@ -25,13 +25,26 @@ func (i *ICoreWebView2BasicAuthenticationResponse) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2BasicAuthenticationResponse) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2BasicAuthenticationResponse) GetUserName() (string, error) { // Create *uint16 to hold result var _userName *uint16 hr, _, _ := i.Vtbl.GetUserName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_userName)), + uintptr(unsafe.Pointer(&_userName)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -66,7 +79,7 @@ func (i *ICoreWebView2BasicAuthenticationResponse) GetPassword() (string, error) hr, _, _ := i.Vtbl.GetPassword.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_password)), + uintptr(unsafe.Pointer(&_password)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2BrowserExtension.go b/pkg/webview2/ICoreWebView2BrowserExtension.go index 29cf1cb..20810ca 100644 --- a/pkg/webview2/ICoreWebView2BrowserExtension.go +++ b/pkg/webview2/ICoreWebView2BrowserExtension.go @@ -26,13 +26,26 @@ func (i *ICoreWebView2BrowserExtension) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2BrowserExtension) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2BrowserExtension) GetId() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetId.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -49,7 +62,7 @@ func (i *ICoreWebView2BrowserExtension) GetName() (string, error) { hr, _, _ := i.Vtbl.GetName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -92,7 +105,7 @@ func (i *ICoreWebView2BrowserExtension) Enable(isEnabled bool, handler *ICoreWeb hr, _, _ := i.Vtbl.Enable.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&isEnabled)), + boolToUintptr(isEnabled), uintptr(unsafe.Pointer(handler)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2BrowserExtensionList.go b/pkg/webview2/ICoreWebView2BrowserExtensionList.go index fb82c94..e6758d4 100644 --- a/pkg/webview2/ICoreWebView2BrowserExtensionList.go +++ b/pkg/webview2/ICoreWebView2BrowserExtensionList.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2BrowserExtensionList) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2BrowserExtensionList) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2BrowserExtensionList) GetCount() (uint32, error) { var value uint32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2BrowserExtensionList) GetValueAtIndex(index uint32) (*ICor hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2BrowserProcessExitedEventArgs.go b/pkg/webview2/ICoreWebView2BrowserProcessExitedEventArgs.go index 239d9df..be6a29d 100644 --- a/pkg/webview2/ICoreWebView2BrowserProcessExitedEventArgs.go +++ b/pkg/webview2/ICoreWebView2BrowserProcessExitedEventArgs.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2BrowserProcessExitedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2BrowserProcessExitedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2BrowserProcessExitedEventArgs) GetBrowserProcessExitKind() (COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND, error) { var value COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND diff --git a/pkg/webview2/ICoreWebView2CallDevToolsProtocolMethodCompletedHandler.go b/pkg/webview2/ICoreWebView2CallDevToolsProtocolMethodCompletedHandler.go index 95e1714..3de046e 100644 --- a/pkg/webview2/ICoreWebView2CallDevToolsProtocolMethodCompletedHandler.go +++ b/pkg/webview2/ICoreWebView2CallDevToolsProtocolMethodCompletedHandler.go @@ -33,13 +33,13 @@ func ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerIUnknownRelease(this return this.impl.Release() } -func ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerInvoke(this *ICoreWebView2CallDevToolsProtocolMethodCompletedHandler, errorCode uintptr, result string) uintptr { +func ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerInvoke(this *ICoreWebView2CallDevToolsProtocolMethodCompletedHandler, errorCode uintptr, result *uint16) uintptr { return this.impl.CallDevToolsProtocolMethodCompleted(errorCode, result) } type ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerImpl interface { IUnknownImpl - CallDevToolsProtocolMethodCompleted(errorCode uintptr, result string) uintptr + CallDevToolsProtocolMethodCompleted(errorCode uintptr, result *uint16) uintptr } var ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerFn = ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerVtbl{ diff --git a/pkg/webview2/ICoreWebView2Certificate.go b/pkg/webview2/ICoreWebView2Certificate.go index 6ca1d4e..215add8 100644 --- a/pkg/webview2/ICoreWebView2Certificate.go +++ b/pkg/webview2/ICoreWebView2Certificate.go @@ -29,13 +29,26 @@ func (i *ICoreWebView2Certificate) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Certificate) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Certificate) GetSubject() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetSubject.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -52,7 +65,7 @@ func (i *ICoreWebView2Certificate) GetIssuer() (string, error) { hr, _, _ := i.Vtbl.GetIssuer.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -97,7 +110,7 @@ func (i *ICoreWebView2Certificate) GetDerEncodedSerialNumber() (string, error) { hr, _, _ := i.Vtbl.GetDerEncodedSerialNumber.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -114,7 +127,7 @@ func (i *ICoreWebView2Certificate) GetDisplayName() (string, error) { hr, _, _ := i.Vtbl.GetDisplayName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -131,7 +144,7 @@ func (i *ICoreWebView2Certificate) ToPemEncoding() (string, error) { hr, _, _ := i.Vtbl.ToPemEncoding.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_pemEncodedData)), + uintptr(unsafe.Pointer(&_pemEncodedData)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ClientCertificate.go b/pkg/webview2/ICoreWebView2ClientCertificate.go index 6d2dc6b..ea37f84 100644 --- a/pkg/webview2/ICoreWebView2ClientCertificate.go +++ b/pkg/webview2/ICoreWebView2ClientCertificate.go @@ -30,13 +30,26 @@ func (i *ICoreWebView2ClientCertificate) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ClientCertificate) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ClientCertificate) GetSubject() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetSubject.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -53,7 +66,7 @@ func (i *ICoreWebView2ClientCertificate) GetIssuer() (string, error) { hr, _, _ := i.Vtbl.GetIssuer.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -98,7 +111,7 @@ func (i *ICoreWebView2ClientCertificate) GetDerEncodedSerialNumber() (string, er hr, _, _ := i.Vtbl.GetDerEncodedSerialNumber.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -115,7 +128,7 @@ func (i *ICoreWebView2ClientCertificate) GetDisplayName() (string, error) { hr, _, _ := i.Vtbl.GetDisplayName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -132,7 +145,7 @@ func (i *ICoreWebView2ClientCertificate) ToPemEncoding() (string, error) { hr, _, _ := i.Vtbl.ToPemEncoding.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_pemEncodedData)), + uintptr(unsafe.Pointer(&_pemEncodedData)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ClientCertificateCollection.go b/pkg/webview2/ICoreWebView2ClientCertificateCollection.go index d413394..53b506e 100644 --- a/pkg/webview2/ICoreWebView2ClientCertificateCollection.go +++ b/pkg/webview2/ICoreWebView2ClientCertificateCollection.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2ClientCertificateCollection) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ClientCertificateCollection) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ClientCertificateCollection) GetCount() (uint32, error) { var value uint32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2ClientCertificateCollection) GetValueAtIndex(index uint32) hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2ClientCertificateRequestedEventArgs.go b/pkg/webview2/ICoreWebView2ClientCertificateRequestedEventArgs.go index d0a2fde..c77b4fb 100644 --- a/pkg/webview2/ICoreWebView2ClientCertificateRequestedEventArgs.go +++ b/pkg/webview2/ICoreWebView2ClientCertificateRequestedEventArgs.go @@ -33,13 +33,26 @@ func (i *ICoreWebView2ClientCertificateRequestedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ClientCertificateRequestedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ClientCertificateRequestedEventArgs) GetHost() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetHost.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -50,13 +63,13 @@ func (i *ICoreWebView2ClientCertificateRequestedEventArgs) GetHost() (string, er return value, nil } -func (i *ICoreWebView2ClientCertificateRequestedEventArgs) GetPort() (int, error) { +func (i *ICoreWebView2ClientCertificateRequestedEventArgs) GetPort() (int32, error) { - var value int + var value int32 hr, _, _ := i.Vtbl.GetPort.Call( uintptr(unsafe.Pointer(i)), - uintptr(value), + uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { return 0, syscall.Errno(hr) @@ -154,7 +167,7 @@ func (i *ICoreWebView2ClientCertificateRequestedEventArgs) PutCancel(value bool) hr, _, _ := i.Vtbl.PutCancel.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -182,7 +195,7 @@ func (i *ICoreWebView2ClientCertificateRequestedEventArgs) PutHandled(value bool hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2CompositionController.go b/pkg/webview2/ICoreWebView2CompositionController.go index ff07e6b..53728f2 100644 --- a/pkg/webview2/ICoreWebView2CompositionController.go +++ b/pkg/webview2/ICoreWebView2CompositionController.go @@ -29,6 +29,19 @@ func (i *ICoreWebView2CompositionController) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2CompositionController) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2CompositionController) GetRootVisualTarget() (*IUnknown, error) { var target *IUnknown @@ -61,8 +74,8 @@ func (i *ICoreWebView2CompositionController) SendMouseInput(eventKind COREWEBVIE uintptr(unsafe.Pointer(i)), uintptr(eventKind), uintptr(virtualKeys), - uintptr(unsafe.Pointer(&mouseData)), - uintptr(unsafe.Pointer(&point)), + uintptr(mouseData), + uintptr(*(*uint64)(unsafe.Pointer(&point))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -130,7 +143,7 @@ func (i *ICoreWebView2CompositionController) RemoveCursorChanged(token EventRegi hr, _, _ := i.Vtbl.RemoveCursorChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2CompositionController2.go b/pkg/webview2/ICoreWebView2CompositionController2.go index dadefc5..10dd6bc 100644 --- a/pkg/webview2/ICoreWebView2CompositionController2.go +++ b/pkg/webview2/ICoreWebView2CompositionController2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2CompositionController2Vtbl struct { - IUnknownVtbl + ICoreWebView2CompositionControllerVtbl GetAutomationProvider ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2CompositionController2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2CompositionController2() *ICoreWebView2CompositionController2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2CompositionController2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2CompositionController) GetICoreWebView2CompositionController2() *ICoreWebView2CompositionController2 { var result *ICoreWebView2CompositionController2 iidICoreWebView2CompositionController2 := NewGUID("{0b6a3d24-49cb-4806-ba20-b5e0734a7b26}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2CompositionController2)), diff --git a/pkg/webview2/ICoreWebView2CompositionController3.go b/pkg/webview2/ICoreWebView2CompositionController3.go index 713e89d..91d5f45 100644 --- a/pkg/webview2/ICoreWebView2CompositionController3.go +++ b/pkg/webview2/ICoreWebView2CompositionController3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2CompositionController3Vtbl struct { - IUnknownVtbl + ICoreWebView2CompositionController2Vtbl DragEnter ComProc DragLeave ComProc DragOver ComProc @@ -25,10 +25,30 @@ func (i *ICoreWebView2CompositionController3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2CompositionController3() *ICoreWebView2CompositionController3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2CompositionController3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2CompositionController) GetICoreWebView2CompositionController3() *ICoreWebView2CompositionController3 { var result *ICoreWebView2CompositionController3 iidICoreWebView2CompositionController3 := NewGUID("{9570570e-4d76-4361-9ee1-f04d0dbdfb1e}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2CompositionController3)), @@ -44,8 +64,8 @@ func (i *ICoreWebView2CompositionController3) DragEnter(dataObject *IDataObject, hr, _, _ := i.Vtbl.DragEnter.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(dataObject)), - uintptr(unsafe.Pointer(&keyState)), - uintptr(unsafe.Pointer(&point)), + uintptr(keyState), + uintptr(*(*uint64)(unsafe.Pointer(&point))), uintptr(unsafe.Pointer(&effect)), ) if windows.Handle(hr) != windows.S_OK { @@ -71,8 +91,8 @@ func (i *ICoreWebView2CompositionController3) DragOver(keyState uint32, point PO hr, _, _ := i.Vtbl.DragOver.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&keyState)), - uintptr(unsafe.Pointer(&point)), + uintptr(keyState), + uintptr(*(*uint64)(unsafe.Pointer(&point))), uintptr(unsafe.Pointer(&effect)), ) if windows.Handle(hr) != windows.S_OK { @@ -88,8 +108,8 @@ func (i *ICoreWebView2CompositionController3) Drop(dataObject *IDataObject, keyS hr, _, _ := i.Vtbl.Drop.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(dataObject)), - uintptr(unsafe.Pointer(&keyState)), - uintptr(unsafe.Pointer(&point)), + uintptr(keyState), + uintptr(*(*uint64)(unsafe.Pointer(&point))), uintptr(unsafe.Pointer(&effect)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2CompositionController4.go b/pkg/webview2/ICoreWebView2CompositionController4.go index 6853145..5b9e693 100644 --- a/pkg/webview2/ICoreWebView2CompositionController4.go +++ b/pkg/webview2/ICoreWebView2CompositionController4.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2CompositionController4Vtbl struct { - IUnknownVtbl + ICoreWebView2CompositionController3Vtbl GetNonClientRegionAtPoint ComProc QueryNonClientRegion ComProc AddNonClientRegionChanged ComProc @@ -25,10 +25,30 @@ func (i *ICoreWebView2CompositionController4) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2CompositionController4() *ICoreWebView2CompositionController4 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2CompositionController4) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2CompositionController) GetICoreWebView2CompositionController4() *ICoreWebView2CompositionController4 { var result *ICoreWebView2CompositionController4 iidICoreWebView2CompositionController4 := NewGUID("{7C367B9B-3D2B-450F-9E58-D61A20F486AA}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2CompositionController4)), @@ -43,7 +63,7 @@ func (i *ICoreWebView2CompositionController4) GetNonClientRegionAtPoint(point PO hr, _, _ := i.Vtbl.GetNonClientRegionAtPoint.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&point)), + uintptr(*(*uint64)(unsafe.Pointer(&point))), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { @@ -86,7 +106,7 @@ func (i *ICoreWebView2CompositionController4) RemoveNonClientRegionChanged(token hr, _, _ := i.Vtbl.RemoveNonClientRegionChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ContentLoadingEventArgs.go b/pkg/webview2/ICoreWebView2ContentLoadingEventArgs.go index 44f0326..37b7c5c 100644 --- a/pkg/webview2/ICoreWebView2ContentLoadingEventArgs.go +++ b/pkg/webview2/ICoreWebView2ContentLoadingEventArgs.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2ContentLoadingEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ContentLoadingEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ContentLoadingEventArgs) GetIsErrorPage() (bool, error) { // Create int32 to hold bool result var _value int32 diff --git a/pkg/webview2/ICoreWebView2ContextMenuItem.go b/pkg/webview2/ICoreWebView2ContextMenuItem.go index 525c6b6..a829317 100644 --- a/pkg/webview2/ICoreWebView2ContextMenuItem.go +++ b/pkg/webview2/ICoreWebView2ContextMenuItem.go @@ -34,13 +34,26 @@ func (i *ICoreWebView2ContextMenuItem) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ContextMenuItem) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ContextMenuItem) GetName() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -57,7 +70,7 @@ func (i *ICoreWebView2ContextMenuItem) GetLabel() (string, error) { hr, _, _ := i.Vtbl.GetLabel.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -88,7 +101,7 @@ func (i *ICoreWebView2ContextMenuItem) GetShortcutKeyDescription() (string, erro hr, _, _ := i.Vtbl.GetShortcutKeyDescription.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -131,7 +144,7 @@ func (i *ICoreWebView2ContextMenuItem) PutIsEnabled(value bool) error { hr, _, _ := i.Vtbl.PutIsEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -159,7 +172,7 @@ func (i *ICoreWebView2ContextMenuItem) PutIsChecked(value bool) error { hr, _, _ := i.Vtbl.PutIsChecked.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -216,7 +229,7 @@ func (i *ICoreWebView2ContextMenuItem) RemoveCustomItemSelected(token EventRegis hr, _, _ := i.Vtbl.RemoveCustomItemSelected.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ContextMenuItemCollection.go b/pkg/webview2/ICoreWebView2ContextMenuItemCollection.go index 2759ce7..2061dd6 100644 --- a/pkg/webview2/ICoreWebView2ContextMenuItemCollection.go +++ b/pkg/webview2/ICoreWebView2ContextMenuItemCollection.go @@ -25,6 +25,19 @@ func (i *ICoreWebView2ContextMenuItemCollection) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ContextMenuItemCollection) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ContextMenuItemCollection) GetCount() (uint32, error) { var value uint32 @@ -45,7 +58,7 @@ func (i *ICoreWebView2ContextMenuItemCollection) GetValueAtIndex(index uint32) ( hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { @@ -58,7 +71,7 @@ func (i *ICoreWebView2ContextMenuItemCollection) RemoveValueAtIndex(index uint32 hr, _, _ := i.Vtbl.RemoveValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -70,7 +83,7 @@ func (i *ICoreWebView2ContextMenuItemCollection) InsertValueAtIndex(index uint32 hr, _, _ := i.Vtbl.InsertValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2ContextMenuRequestedEventArgs.go b/pkg/webview2/ICoreWebView2ContextMenuRequestedEventArgs.go index 46f6c3f..d8399f5 100644 --- a/pkg/webview2/ICoreWebView2ContextMenuRequestedEventArgs.go +++ b/pkg/webview2/ICoreWebView2ContextMenuRequestedEventArgs.go @@ -29,6 +29,19 @@ func (i *ICoreWebView2ContextMenuRequestedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ContextMenuRequestedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ContextMenuRequestedEventArgs) GetMenuItems() (*ICoreWebView2ContextMenuItemCollection, error) { var value *ICoreWebView2ContextMenuItemCollection @@ -75,7 +88,7 @@ func (i *ICoreWebView2ContextMenuRequestedEventArgs) PutSelectedCommandId(value hr, _, _ := i.Vtbl.PutSelectedCommandId.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + uintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -101,7 +114,7 @@ func (i *ICoreWebView2ContextMenuRequestedEventArgs) PutHandled(value bool) erro hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ContextMenuTarget.go b/pkg/webview2/ICoreWebView2ContextMenuTarget.go index 58eaf0f..d381d7a 100644 --- a/pkg/webview2/ICoreWebView2ContextMenuTarget.go +++ b/pkg/webview2/ICoreWebView2ContextMenuTarget.go @@ -34,6 +34,19 @@ func (i *ICoreWebView2ContextMenuTarget) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ContextMenuTarget) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ContextMenuTarget) GetKind() (COREWEBVIEW2_CONTEXT_MENU_TARGET_KIND, error) { var value COREWEBVIEW2_CONTEXT_MENU_TARGET_KIND @@ -86,7 +99,7 @@ func (i *ICoreWebView2ContextMenuTarget) GetPageUri() (string, error) { hr, _, _ := i.Vtbl.GetPageUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -103,7 +116,7 @@ func (i *ICoreWebView2ContextMenuTarget) GetFrameUri() (string, error) { hr, _, _ := i.Vtbl.GetFrameUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -136,7 +149,7 @@ func (i *ICoreWebView2ContextMenuTarget) GetLinkUri() (string, error) { hr, _, _ := i.Vtbl.GetLinkUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -169,7 +182,7 @@ func (i *ICoreWebView2ContextMenuTarget) GetLinkText() (string, error) { hr, _, _ := i.Vtbl.GetLinkText.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -202,7 +215,7 @@ func (i *ICoreWebView2ContextMenuTarget) GetSourceUri() (string, error) { hr, _, _ := i.Vtbl.GetSourceUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -235,7 +248,7 @@ func (i *ICoreWebView2ContextMenuTarget) GetSelectionText() (string, error) { hr, _, _ := i.Vtbl.GetSelectionText.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Controller.go b/pkg/webview2/ICoreWebView2Controller.go index 18347d6..46273df 100644 --- a/pkg/webview2/ICoreWebView2Controller.go +++ b/pkg/webview2/ICoreWebView2Controller.go @@ -4,6 +4,7 @@ package webview2 import ( "golang.org/x/sys/windows" + "math" "syscall" "unsafe" ) @@ -44,6 +45,19 @@ func (i *ICoreWebView2Controller) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Controller) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Controller) GetIsVisible() (bool, error) { // Create int32 to hold bool result var _isVisible int32 @@ -64,7 +78,7 @@ func (i *ICoreWebView2Controller) PutIsVisible(isVisible bool) error { hr, _, _ := i.Vtbl.PutIsVisible.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&isVisible)), + boolToUintptr(isVisible), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -116,7 +130,7 @@ func (i *ICoreWebView2Controller) PutZoomFactor(zoomFactor float64) error { hr, _, _ := i.Vtbl.PutZoomFactor.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&zoomFactor)), + uintptr(math.Float64bits(zoomFactor)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -143,7 +157,7 @@ func (i *ICoreWebView2Controller) RemoveZoomFactorChanged(token EventRegistratio hr, _, _ := i.Vtbl.RemoveZoomFactorChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -156,7 +170,7 @@ func (i *ICoreWebView2Controller) SetBoundsAndZoomFactor(bounds RECT, zoomFactor hr, _, _ := i.Vtbl.SetBoundsAndZoomFactor.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&bounds)), - uintptr(unsafe.Pointer(&zoomFactor)), + uintptr(math.Float64bits(zoomFactor)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -195,7 +209,7 @@ func (i *ICoreWebView2Controller) RemoveMoveFocusRequested(token EventRegistrati hr, _, _ := i.Vtbl.RemoveMoveFocusRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -222,7 +236,7 @@ func (i *ICoreWebView2Controller) RemoveGotFocus(token EventRegistrationToken) e hr, _, _ := i.Vtbl.RemoveGotFocus.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -249,7 +263,7 @@ func (i *ICoreWebView2Controller) RemoveLostFocus(token EventRegistrationToken) hr, _, _ := i.Vtbl.RemoveLostFocus.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -276,7 +290,7 @@ func (i *ICoreWebView2Controller) RemoveAcceleratorKeyPressed(token EventRegistr hr, _, _ := i.Vtbl.RemoveAcceleratorKeyPressed.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -302,7 +316,7 @@ func (i *ICoreWebView2Controller) PutParentWindow(parentWindow HWND) error { hr, _, _ := i.Vtbl.PutParentWindow.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&parentWindow)), + uintptr(parentWindow), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Controller2.go b/pkg/webview2/ICoreWebView2Controller2.go index e4891c4..a168d35 100644 --- a/pkg/webview2/ICoreWebView2Controller2.go +++ b/pkg/webview2/ICoreWebView2Controller2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Controller2Vtbl struct { - IUnknownVtbl + ICoreWebView2ControllerVtbl GetDefaultBackgroundColor ComProc PutDefaultBackgroundColor ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Controller2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Controller2() *ICoreWebView2Controller2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Controller2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Controller) GetICoreWebView2Controller2() *ICoreWebView2Controller2 { var result *ICoreWebView2Controller2 iidICoreWebView2Controller2 := NewGUID("{c979903e-d4ca-4228-92eb-47ee3fa96eab}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Controller2)), @@ -53,7 +73,7 @@ func (i *ICoreWebView2Controller2) PutDefaultBackgroundColor(value COREWEBVIEW2_ hr, _, _ := i.Vtbl.PutDefaultBackgroundColor.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + uintptr(*(*uint32)(unsafe.Pointer(&value))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Controller3.go b/pkg/webview2/ICoreWebView2Controller3.go index 8dd5b03..1dd947f 100644 --- a/pkg/webview2/ICoreWebView2Controller3.go +++ b/pkg/webview2/ICoreWebView2Controller3.go @@ -4,12 +4,13 @@ package webview2 import ( "golang.org/x/sys/windows" + "math" "syscall" "unsafe" ) type ICoreWebView2Controller3Vtbl struct { - IUnknownVtbl + ICoreWebView2Controller2Vtbl GetRasterizationScale ComProc PutRasterizationScale ComProc GetShouldDetectMonitorScaleChanges ComProc @@ -29,10 +30,30 @@ func (i *ICoreWebView2Controller3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Controller3() *ICoreWebView2Controller3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Controller3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Controller) GetICoreWebView2Controller3() *ICoreWebView2Controller3 { var result *ICoreWebView2Controller3 iidICoreWebView2Controller3 := NewGUID("{f9614724-5d2b-41dc-aef7-73d62b51543b}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Controller3)), @@ -59,7 +80,7 @@ func (i *ICoreWebView2Controller3) PutRasterizationScale(scale float64) error { hr, _, _ := i.Vtbl.PutRasterizationScale.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&scale)), + uintptr(math.Float64bits(scale)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -84,16 +105,10 @@ func (i *ICoreWebView2Controller3) GetShouldDetectMonitorScaleChanges() (bool, e } func (i *ICoreWebView2Controller3) PutShouldDetectMonitorScaleChanges(value bool) error { - var intValue uintptr - if value { - intValue = 1 - } else { - intValue = 0 - } hr, _, _ := i.Vtbl.PutShouldDetectMonitorScaleChanges.Call( uintptr(unsafe.Pointer(i)), - intValue, + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -120,7 +135,7 @@ func (i *ICoreWebView2Controller3) RemoveRasterizationScaleChanged(token EventRe hr, _, _ := i.Vtbl.RemoveRasterizationScaleChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Controller4.go b/pkg/webview2/ICoreWebView2Controller4.go index eccc0ea..27f7f17 100644 --- a/pkg/webview2/ICoreWebView2Controller4.go +++ b/pkg/webview2/ICoreWebView2Controller4.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Controller4Vtbl struct { - IUnknownVtbl + ICoreWebView2Controller3Vtbl GetAllowExternalDrop ComProc PutAllowExternalDrop ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Controller4) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Controller4() *ICoreWebView2Controller4 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Controller4) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Controller) GetICoreWebView2Controller4() *ICoreWebView2Controller4 { var result *ICoreWebView2Controller4 iidICoreWebView2Controller4 := NewGUID("{97d418d5-a426-4e49-a151-e1a10f327d9e}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Controller4)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2Controller4) PutAllowExternalDrop(value bool) error { hr, _, _ := i.Vtbl.PutAllowExternalDrop.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ControllerOptions.go b/pkg/webview2/ICoreWebView2ControllerOptions.go index fb6cc2f..4beec17 100644 --- a/pkg/webview2/ICoreWebView2ControllerOptions.go +++ b/pkg/webview2/ICoreWebView2ControllerOptions.go @@ -25,13 +25,26 @@ func (i *ICoreWebView2ControllerOptions) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ControllerOptions) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ControllerOptions) GetProfileName() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetProfileName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -80,7 +93,7 @@ func (i *ICoreWebView2ControllerOptions) PutIsInPrivateModeEnabled(value bool) e hr, _, _ := i.Vtbl.PutIsInPrivateModeEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ControllerOptions2.go b/pkg/webview2/ICoreWebView2ControllerOptions2.go index 41aef9b..f999966 100644 --- a/pkg/webview2/ICoreWebView2ControllerOptions2.go +++ b/pkg/webview2/ICoreWebView2ControllerOptions2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2ControllerOptions2Vtbl struct { - IUnknownVtbl + ICoreWebView2ControllerOptionsVtbl GetScriptLocale ComProc PutScriptLocale ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2ControllerOptions2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2ControllerOptions2() *ICoreWebView2ControllerOptions2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ControllerOptions2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2ControllerOptions) GetICoreWebView2ControllerOptions2() *ICoreWebView2ControllerOptions2 { var result *ICoreWebView2ControllerOptions2 iidICoreWebView2ControllerOptions2 := NewGUID("{06c991d8-9e7e-11ed-a8fc-0242ac120002}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2ControllerOptions2)), @@ -41,7 +61,7 @@ func (i *ICoreWebView2ControllerOptions2) GetScriptLocale() (string, error) { hr, _, _ := i.Vtbl.GetScriptLocale.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Cookie.go b/pkg/webview2/ICoreWebView2Cookie.go index 8dd2dae..4d4a91a 100644 --- a/pkg/webview2/ICoreWebView2Cookie.go +++ b/pkg/webview2/ICoreWebView2Cookie.go @@ -4,6 +4,7 @@ package webview2 import ( "golang.org/x/sys/windows" + "math" "syscall" "unsafe" ) @@ -35,13 +36,26 @@ func (i *ICoreWebView2Cookie) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Cookie) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Cookie) GetName() (string, error) { // Create *uint16 to hold result var _name *uint16 hr, _, _ := i.Vtbl.GetName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_name)), + uintptr(unsafe.Pointer(&_name)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -58,7 +72,7 @@ func (i *ICoreWebView2Cookie) GetValue() (string, error) { hr, _, _ := i.Vtbl.GetValue.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -93,7 +107,7 @@ func (i *ICoreWebView2Cookie) GetDomain() (string, error) { hr, _, _ := i.Vtbl.GetDomain.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_domain)), + uintptr(unsafe.Pointer(&_domain)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -110,7 +124,7 @@ func (i *ICoreWebView2Cookie) GetPath() (string, error) { hr, _, _ := i.Vtbl.GetPath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_path)), + uintptr(unsafe.Pointer(&_path)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -139,7 +153,7 @@ func (i *ICoreWebView2Cookie) PutExpires(expires float64) error { hr, _, _ := i.Vtbl.PutExpires.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&expires)), + uintptr(math.Float64bits(expires)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -167,7 +181,7 @@ func (i *ICoreWebView2Cookie) PutIsHttpOnly(isHttpOnly bool) error { hr, _, _ := i.Vtbl.PutIsHttpOnly.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&isHttpOnly)), + boolToUintptr(isHttpOnly), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -221,7 +235,7 @@ func (i *ICoreWebView2Cookie) PutIsSecure(isSecure bool) error { hr, _, _ := i.Vtbl.PutIsSecure.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&isSecure)), + boolToUintptr(isSecure), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2CookieList.go b/pkg/webview2/ICoreWebView2CookieList.go index 69a7318..6f1e830 100644 --- a/pkg/webview2/ICoreWebView2CookieList.go +++ b/pkg/webview2/ICoreWebView2CookieList.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2CookieList) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2CookieList) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2CookieList) GetCount() (uint32, error) { var value uint32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2CookieList) GetValueAtIndex(index uint32) (*ICoreWebView2C hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2CookieManager.go b/pkg/webview2/ICoreWebView2CookieManager.go index b7fd879..10195a0 100644 --- a/pkg/webview2/ICoreWebView2CookieManager.go +++ b/pkg/webview2/ICoreWebView2CookieManager.go @@ -29,6 +29,19 @@ func (i *ICoreWebView2CookieManager) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2CookieManager) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2CookieManager) CreateCookie(name string, value string, domain string, path string) (*ICoreWebView2Cookie, error) { // Convert string 'name' to *uint16 diff --git a/pkg/webview2/ICoreWebView2CustomSchemeRegistration.go b/pkg/webview2/ICoreWebView2CustomSchemeRegistration.go index 034024a..711a0ba 100644 --- a/pkg/webview2/ICoreWebView2CustomSchemeRegistration.go +++ b/pkg/webview2/ICoreWebView2CustomSchemeRegistration.go @@ -28,13 +28,26 @@ func (i *ICoreWebView2CustomSchemeRegistration) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2CustomSchemeRegistration) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2CustomSchemeRegistration) GetSchemeName() (string, error) { // Create *uint16 to hold result var _schemeName *uint16 hr, _, _ := i.Vtbl.GetSchemeName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_schemeName)), + uintptr(unsafe.Pointer(&_schemeName)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -65,7 +78,7 @@ func (i *ICoreWebView2CustomSchemeRegistration) PutTreatAsSecure(value bool) err hr, _, _ := i.Vtbl.PutTreatAsSecure.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -81,7 +94,7 @@ func (i *ICoreWebView2CustomSchemeRegistration) GetAllowedOrigins() (uint32, *st hr, _, _ := i.Vtbl.GetAllowedOrigins.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&allowedOriginsCount)), - uintptr(unsafe.Pointer(allowedOrigins)), + uintptr(unsafe.Pointer(&allowedOrigins)), ) if windows.Handle(hr) != windows.S_OK { return 0, nil, syscall.Errno(hr) @@ -99,7 +112,7 @@ func (i *ICoreWebView2CustomSchemeRegistration) SetAllowedOrigins(allowedOrigins hr, _, _ := i.Vtbl.SetAllowedOrigins.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&allowedOriginsCount)), + uintptr(allowedOriginsCount), uintptr(unsafe.Pointer(_allowedOrigins)), ) if windows.Handle(hr) != windows.S_OK { @@ -128,7 +141,7 @@ func (i *ICoreWebView2CustomSchemeRegistration) PutHasAuthorityComponent(hasAuth hr, _, _ := i.Vtbl.PutHasAuthorityComponent.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&hasAuthorityComponent)), + boolToUintptr(hasAuthorityComponent), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2DOMContentLoadedEventArgs.go b/pkg/webview2/ICoreWebView2DOMContentLoadedEventArgs.go index d2b3b34..2a96e56 100644 --- a/pkg/webview2/ICoreWebView2DOMContentLoadedEventArgs.go +++ b/pkg/webview2/ICoreWebView2DOMContentLoadedEventArgs.go @@ -22,6 +22,19 @@ func (i *ICoreWebView2DOMContentLoadedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2DOMContentLoadedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2DOMContentLoadedEventArgs) GetNavigationId() (uint64, error) { var value uint64 diff --git a/pkg/webview2/ICoreWebView2Deferral.go b/pkg/webview2/ICoreWebView2Deferral.go index efe5775..0898ad3 100644 --- a/pkg/webview2/ICoreWebView2Deferral.go +++ b/pkg/webview2/ICoreWebView2Deferral.go @@ -22,6 +22,19 @@ func (i *ICoreWebView2Deferral) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Deferral) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Deferral) Complete() error { hr, _, _ := i.Vtbl.Complete.Call( diff --git a/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceivedEventArgs.go b/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceivedEventArgs.go index 7225340..4e7d7e7 100644 --- a/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceivedEventArgs.go +++ b/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceivedEventArgs.go @@ -22,13 +22,26 @@ func (i *ICoreWebView2DevToolsProtocolEventReceivedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2DevToolsProtocolEventReceivedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2DevToolsProtocolEventReceivedEventArgs) GetParameterObjectAsJson() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetParameterObjectAsJson.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceivedEventArgs2.go b/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceivedEventArgs2.go index 2a85d90..c9e324c 100644 --- a/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceivedEventArgs2.go +++ b/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceivedEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2DevToolsProtocolEventReceivedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2DevToolsProtocolEventReceivedEventArgsVtbl GetSessionId ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2DevToolsProtocolEventReceivedEventArgs2) AddRef() uintptr return refCounter } -func (i *ICoreWebView2) GetICoreWebView2DevToolsProtocolEventReceivedEventArgs2() *ICoreWebView2DevToolsProtocolEventReceivedEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2DevToolsProtocolEventReceivedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2DevToolsProtocolEventReceivedEventArgs) GetICoreWebView2DevToolsProtocolEventReceivedEventArgs2() *ICoreWebView2DevToolsProtocolEventReceivedEventArgs2 { var result *ICoreWebView2DevToolsProtocolEventReceivedEventArgs2 iidICoreWebView2DevToolsProtocolEventReceivedEventArgs2 := NewGUID("{2dc4959d-1494-4393-95ba-bea4cb9ebd1b}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2DevToolsProtocolEventReceivedEventArgs2)), @@ -40,7 +60,7 @@ func (i *ICoreWebView2DevToolsProtocolEventReceivedEventArgs2) GetSessionId() (s hr, _, _ := i.Vtbl.GetSessionId.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceiver.go b/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceiver.go index 0750648..e0376bb 100644 --- a/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceiver.go +++ b/pkg/webview2/ICoreWebView2DevToolsProtocolEventReceiver.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2DevToolsProtocolEventReceiver) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2DevToolsProtocolEventReceiver) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2DevToolsProtocolEventReceiver) AddDevToolsProtocolEventReceived(eventHandler *ICoreWebView2DevToolsProtocolEventReceivedEventHandler) (EventRegistrationToken, error) { var token EventRegistrationToken @@ -42,7 +55,7 @@ func (i *ICoreWebView2DevToolsProtocolEventReceiver) RemoveDevToolsProtocolEvent hr, _, _ := i.Vtbl.RemoveDevToolsProtocolEventReceived.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2DownloadOperation.go b/pkg/webview2/ICoreWebView2DownloadOperation.go index c26339b..1d53359 100644 --- a/pkg/webview2/ICoreWebView2DownloadOperation.go +++ b/pkg/webview2/ICoreWebView2DownloadOperation.go @@ -40,6 +40,19 @@ func (i *ICoreWebView2DownloadOperation) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2DownloadOperation) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2DownloadOperation) AddBytesReceivedChanged(eventHandler *ICoreWebView2BytesReceivedChangedEventHandler) (EventRegistrationToken, error) { var token EventRegistrationToken @@ -59,7 +72,7 @@ func (i *ICoreWebView2DownloadOperation) RemoveBytesReceivedChanged(token EventR hr, _, _ := i.Vtbl.RemoveBytesReceivedChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -86,7 +99,7 @@ func (i *ICoreWebView2DownloadOperation) RemoveEstimatedEndTimeChanged(token Eve hr, _, _ := i.Vtbl.RemoveEstimatedEndTimeChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -113,7 +126,7 @@ func (i *ICoreWebView2DownloadOperation) RemoveStateChanged(token EventRegistrat hr, _, _ := i.Vtbl.RemoveStateChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -127,7 +140,7 @@ func (i *ICoreWebView2DownloadOperation) GetUri() (string, error) { hr, _, _ := i.Vtbl.GetUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_uri)), + uintptr(unsafe.Pointer(&_uri)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -144,7 +157,7 @@ func (i *ICoreWebView2DownloadOperation) GetContentDisposition() (string, error) hr, _, _ := i.Vtbl.GetContentDisposition.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_contentDisposition)), + uintptr(unsafe.Pointer(&_contentDisposition)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -161,7 +174,7 @@ func (i *ICoreWebView2DownloadOperation) GetMimeType() (string, error) { hr, _, _ := i.Vtbl.GetMimeType.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_mimeType)), + uintptr(unsafe.Pointer(&_mimeType)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -206,7 +219,7 @@ func (i *ICoreWebView2DownloadOperation) GetEstimatedEndTime() (string, error) { hr, _, _ := i.Vtbl.GetEstimatedEndTime.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_estimatedEndTime)), + uintptr(unsafe.Pointer(&_estimatedEndTime)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -223,7 +236,7 @@ func (i *ICoreWebView2DownloadOperation) GetResultFilePath() (string, error) { hr, _, _ := i.Vtbl.GetResultFilePath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_resultFilePath)), + uintptr(unsafe.Pointer(&_resultFilePath)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2DownloadStartingEventArgs.go b/pkg/webview2/ICoreWebView2DownloadStartingEventArgs.go index ac63d86..ce6d706 100644 --- a/pkg/webview2/ICoreWebView2DownloadStartingEventArgs.go +++ b/pkg/webview2/ICoreWebView2DownloadStartingEventArgs.go @@ -29,6 +29,19 @@ func (i *ICoreWebView2DownloadStartingEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2DownloadStartingEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2DownloadStartingEventArgs) GetDownloadOperation() (*ICoreWebView2DownloadOperation, error) { var downloadOperation *ICoreWebView2DownloadOperation @@ -63,7 +76,7 @@ func (i *ICoreWebView2DownloadStartingEventArgs) PutCancel(cancel bool) error { hr, _, _ := i.Vtbl.PutCancel.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&cancel)), + boolToUintptr(cancel), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -77,7 +90,7 @@ func (i *ICoreWebView2DownloadStartingEventArgs) GetResultFilePath() (string, er hr, _, _ := i.Vtbl.GetResultFilePath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_resultFilePath)), + uintptr(unsafe.Pointer(&_resultFilePath)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -126,7 +139,7 @@ func (i *ICoreWebView2DownloadStartingEventArgs) PutHandled(handled bool) error hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&handled)), + boolToUintptr(handled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Environment.go b/pkg/webview2/ICoreWebView2Environment.go index 91aae99..0ccf0c1 100644 --- a/pkg/webview2/ICoreWebView2Environment.go +++ b/pkg/webview2/ICoreWebView2Environment.go @@ -26,11 +26,24 @@ func (i *ICoreWebView2Environment) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Environment) CreateCoreWebView2Controller(parentWindow HWND, handler *ICoreWebView2CreateCoreWebView2ControllerCompletedHandler) error { hr, _, _ := i.Vtbl.CreateCoreWebView2Controller.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&parentWindow)), + uintptr(parentWindow), uintptr(unsafe.Pointer(handler)), ) if windows.Handle(hr) != windows.S_OK { @@ -39,7 +52,7 @@ func (i *ICoreWebView2Environment) CreateCoreWebView2Controller(parentWindow HWN return nil } -func (i *ICoreWebView2Environment) CreateWebResourceResponse(content *IStream, statusCode int, reasonPhrase string, headers string) (*ICoreWebView2WebResourceResponse, error) { +func (i *ICoreWebView2Environment) CreateWebResourceResponse(content *IStream, statusCode int32, reasonPhrase string, headers string) (*ICoreWebView2WebResourceResponse, error) { // Convert string 'reasonPhrase' to *uint16 _reasonPhrase, err := UTF16PtrFromString(reasonPhrase) @@ -73,7 +86,7 @@ func (i *ICoreWebView2Environment) GetBrowserVersionString() (string, error) { hr, _, _ := i.Vtbl.GetBrowserVersionString.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_versionInfo)), + uintptr(unsafe.Pointer(&_versionInfo)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -103,7 +116,7 @@ func (i *ICoreWebView2Environment) RemoveNewBrowserVersionAvailable(token EventR hr, _, _ := i.Vtbl.RemoveNewBrowserVersionAvailable.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Environment10.go b/pkg/webview2/ICoreWebView2Environment10.go index a763a97..0b0c8a8 100644 --- a/pkg/webview2/ICoreWebView2Environment10.go +++ b/pkg/webview2/ICoreWebView2Environment10.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment10Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment9Vtbl CreateCoreWebView2ControllerOptions ComProc CreateCoreWebView2ControllerWithOptions ComProc CreateCoreWebView2CompositionControllerWithOptions ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2Environment10) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment10() *ICoreWebView2Environment10 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment10) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment10() *ICoreWebView2Environment10 { var result *ICoreWebView2Environment10 iidICoreWebView2Environment10 := NewGUID("{ee0eb9df-6f12-46ce-b53f-3f47b9c928e0}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment10)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2Environment10) CreateCoreWebView2ControllerWithOptions(Par hr, _, _ := i.Vtbl.CreateCoreWebView2ControllerWithOptions.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&ParentWindow)), + uintptr(ParentWindow), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(handler)), ) @@ -68,7 +88,7 @@ func (i *ICoreWebView2Environment10) CreateCoreWebView2CompositionControllerWith hr, _, _ := i.Vtbl.CreateCoreWebView2CompositionControllerWithOptions.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&ParentWindow)), + uintptr(ParentWindow), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(handler)), ) diff --git a/pkg/webview2/ICoreWebView2Environment11.go b/pkg/webview2/ICoreWebView2Environment11.go index 01c1750..f9b4534 100644 --- a/pkg/webview2/ICoreWebView2Environment11.go +++ b/pkg/webview2/ICoreWebView2Environment11.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment11Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment10Vtbl GetFailureReportFolderPath ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Environment11) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment11() *ICoreWebView2Environment11 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment11) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment11() *ICoreWebView2Environment11 { var result *ICoreWebView2Environment11 iidICoreWebView2Environment11 := NewGUID("{f0913dc6-a0ec-42ef-9805-91dff3a2966a}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment11)), @@ -40,7 +60,7 @@ func (i *ICoreWebView2Environment11) GetFailureReportFolderPath() (string, error hr, _, _ := i.Vtbl.GetFailureReportFolderPath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Environment12.go b/pkg/webview2/ICoreWebView2Environment12.go index f90c8d1..105eb07 100644 --- a/pkg/webview2/ICoreWebView2Environment12.go +++ b/pkg/webview2/ICoreWebView2Environment12.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment12Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment11Vtbl CreateSharedBuffer ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Environment12) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment12() *ICoreWebView2Environment12 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment12) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment12() *ICoreWebView2Environment12 { var result *ICoreWebView2Environment12 iidICoreWebView2Environment12 := NewGUID("{f503db9b-739f-48dd-b151-fdfcf253f54e}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment12)), @@ -40,7 +60,7 @@ func (i *ICoreWebView2Environment12) CreateSharedBuffer(Size uint64) (*ICoreWebV hr, _, _ := i.Vtbl.CreateSharedBuffer.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&Size)), + uintptr(Size), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2Environment13.go b/pkg/webview2/ICoreWebView2Environment13.go index 827acfc..f3c1b9e 100644 --- a/pkg/webview2/ICoreWebView2Environment13.go +++ b/pkg/webview2/ICoreWebView2Environment13.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment13Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment12Vtbl GetProcessExtendedInfos ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Environment13) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment13() *ICoreWebView2Environment13 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment13) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment13() *ICoreWebView2Environment13 { var result *ICoreWebView2Environment13 iidICoreWebView2Environment13 := NewGUID("{af641f58-72b2-11ee-b962-0242ac120002}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment13)), diff --git a/pkg/webview2/ICoreWebView2Environment14.go b/pkg/webview2/ICoreWebView2Environment14.go index ec7605d..e03d5c2 100644 --- a/pkg/webview2/ICoreWebView2Environment14.go +++ b/pkg/webview2/ICoreWebView2Environment14.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment14Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment13Vtbl CreateWebFileSystemFileHandle ComProc CreateWebFileSystemDirectoryHandle ComProc CreateObjectCollection ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2Environment14) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment14() *ICoreWebView2Environment14 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment14) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment14() *ICoreWebView2Environment14 { var result *ICoreWebView2Environment14 iidICoreWebView2Environment14 := NewGUID("{a5e9fad9-c875-59da-9bd7-473aa5ca1cef}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment14)), @@ -84,8 +104,8 @@ func (i *ICoreWebView2Environment14) CreateObjectCollection(length uint32, items hr, _, _ := i.Vtbl.CreateObjectCollection.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&length)), - uintptr(unsafe.Pointer(&items)), + uintptr(length), + uintptr(unsafe.Pointer(items)), uintptr(unsafe.Pointer(&objectCollection)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2Environment2.go b/pkg/webview2/ICoreWebView2Environment2.go index 914cce3..d24981e 100644 --- a/pkg/webview2/ICoreWebView2Environment2.go +++ b/pkg/webview2/ICoreWebView2Environment2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment2Vtbl struct { - IUnknownVtbl + ICoreWebView2EnvironmentVtbl CreateWebResourceRequest ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Environment2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment2() *ICoreWebView2Environment2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment2() *ICoreWebView2Environment2 { var result *ICoreWebView2Environment2 iidICoreWebView2Environment2 := NewGUID("{41f3632b-5ef4-404f-ad82-2d606c5a9a21}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment2)), diff --git a/pkg/webview2/ICoreWebView2Environment3.go b/pkg/webview2/ICoreWebView2Environment3.go index 58fbec8..302e845 100644 --- a/pkg/webview2/ICoreWebView2Environment3.go +++ b/pkg/webview2/ICoreWebView2Environment3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment3Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment2Vtbl CreateCoreWebView2CompositionController ComProc CreateCoreWebView2PointerInfo ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Environment3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment3() *ICoreWebView2Environment3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment3() *ICoreWebView2Environment3 { var result *ICoreWebView2Environment3 iidICoreWebView2Environment3 := NewGUID("{80a22ae3-be7c-4ce2-afe1-5a50056cdeeb}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment3)), @@ -39,7 +59,7 @@ func (i *ICoreWebView2Environment3) CreateCoreWebView2CompositionController(Pare hr, _, _ := i.Vtbl.CreateCoreWebView2CompositionController.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&ParentWindow)), + uintptr(ParentWindow), uintptr(unsafe.Pointer(handler)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2Environment4.go b/pkg/webview2/ICoreWebView2Environment4.go index 3be765f..fd6b264 100644 --- a/pkg/webview2/ICoreWebView2Environment4.go +++ b/pkg/webview2/ICoreWebView2Environment4.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment4Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment3Vtbl GetAutomationProviderForWindow ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Environment4) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment4() *ICoreWebView2Environment4 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment4) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment4() *ICoreWebView2Environment4 { var result *ICoreWebView2Environment4 iidICoreWebView2Environment4 := NewGUID("{20944379-6dcf-41d6-a0a0-abc0fc50de0d}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment4)), @@ -40,7 +60,7 @@ func (i *ICoreWebView2Environment4) GetAutomationProviderForWindow(hwnd HWND) (* hr, _, _ := i.Vtbl.GetAutomationProviderForWindow.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&hwnd)), + uintptr(hwnd), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2Environment5.go b/pkg/webview2/ICoreWebView2Environment5.go index cd7060f..2a11380 100644 --- a/pkg/webview2/ICoreWebView2Environment5.go +++ b/pkg/webview2/ICoreWebView2Environment5.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment5Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment4Vtbl AddBrowserProcessExited ComProc RemoveBrowserProcessExited ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Environment5) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment5() *ICoreWebView2Environment5 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment5) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment5() *ICoreWebView2Environment5 { var result *ICoreWebView2Environment5 iidICoreWebView2Environment5 := NewGUID("{319e423d-e0d7-4b8d-9254-ae9475de9b17}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment5)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2Environment5) RemoveBrowserProcessExited(token EventRegist hr, _, _ := i.Vtbl.RemoveBrowserProcessExited.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Environment6.go b/pkg/webview2/ICoreWebView2Environment6.go index 5265f7d..598b20c 100644 --- a/pkg/webview2/ICoreWebView2Environment6.go +++ b/pkg/webview2/ICoreWebView2Environment6.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment6Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment5Vtbl CreatePrintSettings ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Environment6) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment6() *ICoreWebView2Environment6 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment6) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment6() *ICoreWebView2Environment6 { var result *ICoreWebView2Environment6 iidICoreWebView2Environment6 := NewGUID("{e59ee362-acbd-4857-9a8e-d3644d9459a9}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment6)), diff --git a/pkg/webview2/ICoreWebView2Environment7.go b/pkg/webview2/ICoreWebView2Environment7.go index e4a652f..c55d009 100644 --- a/pkg/webview2/ICoreWebView2Environment7.go +++ b/pkg/webview2/ICoreWebView2Environment7.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment7Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment6Vtbl GetUserDataFolder ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Environment7) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment7() *ICoreWebView2Environment7 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment7) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment7() *ICoreWebView2Environment7 { var result *ICoreWebView2Environment7 iidICoreWebView2Environment7 := NewGUID("{43c22296-3bbd-43a4-9c00-5c0df6dd29a2}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment7)), @@ -40,7 +60,7 @@ func (i *ICoreWebView2Environment7) GetUserDataFolder() (string, error) { hr, _, _ := i.Vtbl.GetUserDataFolder.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Environment8.go b/pkg/webview2/ICoreWebView2Environment8.go index 9894aef..3437342 100644 --- a/pkg/webview2/ICoreWebView2Environment8.go +++ b/pkg/webview2/ICoreWebView2Environment8.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment8Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment7Vtbl AddProcessInfosChanged ComProc RemoveProcessInfosChanged ComProc GetProcessInfos ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2Environment8) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment8() *ICoreWebView2Environment8 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment8) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment8() *ICoreWebView2Environment8 { var result *ICoreWebView2Environment8 iidICoreWebView2Environment8 := NewGUID("{d6eb91dd-c3d2-45e5-bd29-6dc2bc4de9cf}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment8)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2Environment8) RemoveProcessInfosChanged(token EventRegistr hr, _, _ := i.Vtbl.RemoveProcessInfosChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Environment9.go b/pkg/webview2/ICoreWebView2Environment9.go index e324c44..b79bc67 100644 --- a/pkg/webview2/ICoreWebView2Environment9.go +++ b/pkg/webview2/ICoreWebView2Environment9.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Environment9Vtbl struct { - IUnknownVtbl + ICoreWebView2Environment8Vtbl CreateContextMenuItem ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Environment9) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Environment9() *ICoreWebView2Environment9 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Environment9) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Environment) GetICoreWebView2Environment9() *ICoreWebView2Environment9 { var result *ICoreWebView2Environment9 iidICoreWebView2Environment9 := NewGUID("{f06f41bf-4b5a-49d8-b9f6-fa16cd29f274}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Environment9)), diff --git a/pkg/webview2/ICoreWebView2EnvironmentOptions.go b/pkg/webview2/ICoreWebView2EnvironmentOptions.go index 061f78e..f6f7c9e 100644 --- a/pkg/webview2/ICoreWebView2EnvironmentOptions.go +++ b/pkg/webview2/ICoreWebView2EnvironmentOptions.go @@ -29,13 +29,26 @@ func (i *ICoreWebView2EnvironmentOptions) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2EnvironmentOptions) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2EnvironmentOptions) GetAdditionalBrowserArguments() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetAdditionalBrowserArguments.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -70,7 +83,7 @@ func (i *ICoreWebView2EnvironmentOptions) GetLanguage() (string, error) { hr, _, _ := i.Vtbl.GetLanguage.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -105,7 +118,7 @@ func (i *ICoreWebView2EnvironmentOptions) GetTargetCompatibleBrowserVersion() (s hr, _, _ := i.Vtbl.GetTargetCompatibleBrowserVersion.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -154,7 +167,7 @@ func (i *ICoreWebView2EnvironmentOptions) PutAllowSingleSignOnUsingOSPrimaryAcco hr, _, _ := i.Vtbl.PutAllowSingleSignOnUsingOSPrimaryAccount.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&allow)), + boolToUintptr(allow), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2EnvironmentOptions2.go b/pkg/webview2/ICoreWebView2EnvironmentOptions2.go index 4acef94..44e9527 100644 --- a/pkg/webview2/ICoreWebView2EnvironmentOptions2.go +++ b/pkg/webview2/ICoreWebView2EnvironmentOptions2.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2EnvironmentOptions2) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2EnvironmentOptions2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2EnvironmentOptions2) GetExclusiveUserDataFolderAccess() (bool, error) { // Create int32 to hold bool result var _value int32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2EnvironmentOptions2) PutExclusiveUserDataFolderAccess(valu hr, _, _ := i.Vtbl.PutExclusiveUserDataFolderAccess.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2EnvironmentOptions3.go b/pkg/webview2/ICoreWebView2EnvironmentOptions3.go index 9e1aad3..90022d3 100644 --- a/pkg/webview2/ICoreWebView2EnvironmentOptions3.go +++ b/pkg/webview2/ICoreWebView2EnvironmentOptions3.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2EnvironmentOptions3) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2EnvironmentOptions3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2EnvironmentOptions3) GetIsCustomCrashReportingEnabled() (bool, error) { // Create int32 to hold bool result var _value int32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2EnvironmentOptions3) PutIsCustomCrashReportingEnabled(valu hr, _, _ := i.Vtbl.PutIsCustomCrashReportingEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2EnvironmentOptions4.go b/pkg/webview2/ICoreWebView2EnvironmentOptions4.go index b675342..6bd5f62 100644 --- a/pkg/webview2/ICoreWebView2EnvironmentOptions4.go +++ b/pkg/webview2/ICoreWebView2EnvironmentOptions4.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2EnvironmentOptions4) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2EnvironmentOptions4) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2EnvironmentOptions4) GetCustomSchemeRegistrations() (uint32, ICoreWebView2CustomSchemeRegistration, error) { var count uint32 @@ -43,8 +56,8 @@ func (i *ICoreWebView2EnvironmentOptions4) SetCustomSchemeRegistrations(count ui hr, _, _ := i.Vtbl.SetCustomSchemeRegistrations.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&count)), - uintptr(unsafe.Pointer(&schemeRegistrations)), + uintptr(count), + uintptr(unsafe.Pointer(schemeRegistrations)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2EnvironmentOptions5.go b/pkg/webview2/ICoreWebView2EnvironmentOptions5.go index b213fc6..b3050a0 100644 --- a/pkg/webview2/ICoreWebView2EnvironmentOptions5.go +++ b/pkg/webview2/ICoreWebView2EnvironmentOptions5.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2EnvironmentOptions5) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2EnvironmentOptions5) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2EnvironmentOptions5) GetEnableTrackingPrevention() (bool, error) { // Create int32 to hold bool result var _value int32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2EnvironmentOptions5) PutEnableTrackingPrevention(value boo hr, _, _ := i.Vtbl.PutEnableTrackingPrevention.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2EnvironmentOptions6.go b/pkg/webview2/ICoreWebView2EnvironmentOptions6.go index 602fc37..a550786 100644 --- a/pkg/webview2/ICoreWebView2EnvironmentOptions6.go +++ b/pkg/webview2/ICoreWebView2EnvironmentOptions6.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2EnvironmentOptions6) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2EnvironmentOptions6) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2EnvironmentOptions6) GetAreBrowserExtensionsEnabled() (bool, error) { // Create int32 to hold bool result var _value int32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2EnvironmentOptions6) PutAreBrowserExtensionsEnabled(value hr, _, _ := i.Vtbl.PutAreBrowserExtensionsEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2EnvironmentOptions7.go b/pkg/webview2/ICoreWebView2EnvironmentOptions7.go index c6ebda0..ce7d960 100644 --- a/pkg/webview2/ICoreWebView2EnvironmentOptions7.go +++ b/pkg/webview2/ICoreWebView2EnvironmentOptions7.go @@ -25,6 +25,19 @@ func (i *ICoreWebView2EnvironmentOptions7) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2EnvironmentOptions7) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2EnvironmentOptions7) GetChannelSearchKind() (COREWEBVIEW2_CHANNEL_SEARCH_KIND, error) { var value COREWEBVIEW2_CHANNEL_SEARCH_KIND diff --git a/pkg/webview2/ICoreWebView2EnvironmentOptions8.go b/pkg/webview2/ICoreWebView2EnvironmentOptions8.go index 5d666ca..f716d77 100644 --- a/pkg/webview2/ICoreWebView2EnvironmentOptions8.go +++ b/pkg/webview2/ICoreWebView2EnvironmentOptions8.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2EnvironmentOptions8) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2EnvironmentOptions8) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2EnvironmentOptions8) GetScrollBarStyle() (COREWEBVIEW2_SCROLLBAR_STYLE, error) { var value COREWEBVIEW2_SCROLLBAR_STYLE diff --git a/pkg/webview2/ICoreWebView2ExecuteScriptCompletedHandler.go b/pkg/webview2/ICoreWebView2ExecuteScriptCompletedHandler.go index 160b520..e2f4f98 100644 --- a/pkg/webview2/ICoreWebView2ExecuteScriptCompletedHandler.go +++ b/pkg/webview2/ICoreWebView2ExecuteScriptCompletedHandler.go @@ -33,13 +33,13 @@ func ICoreWebView2ExecuteScriptCompletedHandlerIUnknownRelease(this *ICoreWebVie return this.impl.Release() } -func ICoreWebView2ExecuteScriptCompletedHandlerInvoke(this *ICoreWebView2ExecuteScriptCompletedHandler, errorCode uintptr, result string) uintptr { +func ICoreWebView2ExecuteScriptCompletedHandlerInvoke(this *ICoreWebView2ExecuteScriptCompletedHandler, errorCode uintptr, result *uint16) uintptr { return this.impl.ExecuteScriptCompleted(errorCode, result) } type ICoreWebView2ExecuteScriptCompletedHandlerImpl interface { IUnknownImpl - ExecuteScriptCompleted(errorCode uintptr, result string) uintptr + ExecuteScriptCompleted(errorCode uintptr, result *uint16) uintptr } var ICoreWebView2ExecuteScriptCompletedHandlerFn = ICoreWebView2ExecuteScriptCompletedHandlerVtbl{ diff --git a/pkg/webview2/ICoreWebView2ExecuteScriptResult.go b/pkg/webview2/ICoreWebView2ExecuteScriptResult.go index 73c5693..159e3c4 100644 --- a/pkg/webview2/ICoreWebView2ExecuteScriptResult.go +++ b/pkg/webview2/ICoreWebView2ExecuteScriptResult.go @@ -25,6 +25,19 @@ func (i *ICoreWebView2ExecuteScriptResult) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ExecuteScriptResult) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ExecuteScriptResult) GetSucceeded() (bool, error) { // Create int32 to hold bool result var _value int32 @@ -47,7 +60,7 @@ func (i *ICoreWebView2ExecuteScriptResult) GetResultAsJson() (string, error) { hr, _, _ := i.Vtbl.GetResultAsJson.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_jsonResult)), + uintptr(unsafe.Pointer(&_jsonResult)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -66,7 +79,7 @@ func (i *ICoreWebView2ExecuteScriptResult) TryGetResultAsString() (string, bool, hr, _, _ := i.Vtbl.TryGetResultAsString.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_stringResult)), + uintptr(unsafe.Pointer(&_stringResult)), uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2File.go b/pkg/webview2/ICoreWebView2File.go index 90089d9..a94d8fb 100644 --- a/pkg/webview2/ICoreWebView2File.go +++ b/pkg/webview2/ICoreWebView2File.go @@ -22,13 +22,26 @@ func (i *ICoreWebView2File) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2File) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2File) GetPath() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetPath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2FileSystemHandle.go b/pkg/webview2/ICoreWebView2FileSystemHandle.go index 1ae6cf3..ead48c0 100644 --- a/pkg/webview2/ICoreWebView2FileSystemHandle.go +++ b/pkg/webview2/ICoreWebView2FileSystemHandle.go @@ -24,6 +24,19 @@ func (i *ICoreWebView2FileSystemHandle) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2FileSystemHandle) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2FileSystemHandle) GetKind() (COREWEBVIEW2_FILE_SYSTEM_HANDLE_KIND, error) { var value COREWEBVIEW2_FILE_SYSTEM_HANDLE_KIND @@ -44,7 +57,7 @@ func (i *ICoreWebView2FileSystemHandle) GetPath() (string, error) { hr, _, _ := i.Vtbl.GetPath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Frame.go b/pkg/webview2/ICoreWebView2Frame.go index 3c08c98..ee02d77 100644 --- a/pkg/webview2/ICoreWebView2Frame.go +++ b/pkg/webview2/ICoreWebView2Frame.go @@ -29,13 +29,26 @@ func (i *ICoreWebView2Frame) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Frame) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Frame) GetName() (string, error) { // Create *uint16 to hold result var _name *uint16 hr, _, _ := i.Vtbl.GetName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_name)), + uintptr(unsafe.Pointer(&_name)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -65,7 +78,7 @@ func (i *ICoreWebView2Frame) RemoveNameChanged(token EventRegistrationToken) err hr, _, _ := i.Vtbl.RemoveNameChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -90,7 +103,7 @@ func (i *ICoreWebView2Frame) AddHostObjectToScriptWithOrigins(name string, objec uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(_name)), uintptr(unsafe.Pointer(object)), - uintptr(unsafe.Pointer(&originsCount)), + uintptr(originsCount), uintptr(unsafe.Pointer(_origins)), ) if windows.Handle(hr) != windows.S_OK { @@ -136,7 +149,7 @@ func (i *ICoreWebView2Frame) RemoveDestroyed(token EventRegistrationToken) error hr, _, _ := i.Vtbl.RemoveDestroyed.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Frame2.go b/pkg/webview2/ICoreWebView2Frame2.go index 3a38dff..1390f87 100644 --- a/pkg/webview2/ICoreWebView2Frame2.go +++ b/pkg/webview2/ICoreWebView2Frame2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Frame2Vtbl struct { - IUnknownVtbl + ICoreWebView2FrameVtbl AddNavigationStarting ComProc RemoveNavigationStarting ComProc AddContentLoading ComProc @@ -34,10 +34,30 @@ func (i *ICoreWebView2Frame2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Frame2() *ICoreWebView2Frame2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Frame2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Frame) GetICoreWebView2Frame2() *ICoreWebView2Frame2 { var result *ICoreWebView2Frame2 iidICoreWebView2Frame2 := NewGUID("{7a6a5834-d185-4dbf-b63f-4a9bc43107d4}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Frame2)), @@ -65,7 +85,7 @@ func (i *ICoreWebView2Frame2) RemoveNavigationStarting(token EventRegistrationTo hr, _, _ := i.Vtbl.RemoveNavigationStarting.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -92,7 +112,7 @@ func (i *ICoreWebView2Frame2) RemoveContentLoading(token EventRegistrationToken) hr, _, _ := i.Vtbl.RemoveContentLoading.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -119,7 +139,7 @@ func (i *ICoreWebView2Frame2) RemoveNavigationCompleted(token EventRegistrationT hr, _, _ := i.Vtbl.RemoveNavigationCompleted.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -146,7 +166,7 @@ func (i *ICoreWebView2Frame2) RemoveDOMContentLoaded(token EventRegistrationToke hr, _, _ := i.Vtbl.RemoveDOMContentLoaded.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -228,7 +248,7 @@ func (i *ICoreWebView2Frame2) RemoveWebMessageReceived(token EventRegistrationTo hr, _, _ := i.Vtbl.RemoveWebMessageReceived.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Frame3.go b/pkg/webview2/ICoreWebView2Frame3.go index e386c68..74c6301 100644 --- a/pkg/webview2/ICoreWebView2Frame3.go +++ b/pkg/webview2/ICoreWebView2Frame3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Frame3Vtbl struct { - IUnknownVtbl + ICoreWebView2Frame2Vtbl AddPermissionRequested ComProc RemovePermissionRequested ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Frame3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Frame3() *ICoreWebView2Frame3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Frame3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Frame) GetICoreWebView2Frame3() *ICoreWebView2Frame3 { var result *ICoreWebView2Frame3 iidICoreWebView2Frame3 := NewGUID("{b50d82cc-cc28-481d-9614-cb048895e6a0}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Frame3)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2Frame3) RemovePermissionRequested(token EventRegistrationT hr, _, _ := i.Vtbl.RemovePermissionRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Frame4.go b/pkg/webview2/ICoreWebView2Frame4.go index fb86908..8c2f152 100644 --- a/pkg/webview2/ICoreWebView2Frame4.go +++ b/pkg/webview2/ICoreWebView2Frame4.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Frame4Vtbl struct { - IUnknownVtbl + ICoreWebView2Frame3Vtbl PostSharedBufferToScript ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Frame4) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Frame4() *ICoreWebView2Frame4 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Frame4) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Frame) GetICoreWebView2Frame4() *ICoreWebView2Frame4 { var result *ICoreWebView2Frame4 iidICoreWebView2Frame4 := NewGUID("{188782dc-92aa-4732-ab3c-fcc59f6f68b9}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Frame4)), diff --git a/pkg/webview2/ICoreWebView2Frame5.go b/pkg/webview2/ICoreWebView2Frame5.go index ea37d81..5b49614 100644 --- a/pkg/webview2/ICoreWebView2Frame5.go +++ b/pkg/webview2/ICoreWebView2Frame5.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Frame5Vtbl struct { - IUnknownVtbl + ICoreWebView2Frame4Vtbl GetFrameId ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Frame5) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Frame5() *ICoreWebView2Frame5 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Frame5) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Frame) GetICoreWebView2Frame5() *ICoreWebView2Frame5 { var result *ICoreWebView2Frame5 iidICoreWebView2Frame5 := NewGUID("{99d199c4-7305-11ee-b962-0242ac120002}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Frame5)), diff --git a/pkg/webview2/ICoreWebView2Frame6.go b/pkg/webview2/ICoreWebView2Frame6.go index bf50a86..a8d27fe 100644 --- a/pkg/webview2/ICoreWebView2Frame6.go +++ b/pkg/webview2/ICoreWebView2Frame6.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Frame6Vtbl struct { - IUnknownVtbl + ICoreWebView2Frame5Vtbl AddScreenCaptureStarting ComProc RemoveScreenCaptureStarting ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Frame6) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Frame6() *ICoreWebView2Frame6 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Frame6) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Frame) GetICoreWebView2Frame6() *ICoreWebView2Frame6 { var result *ICoreWebView2Frame6 iidICoreWebView2Frame6 := NewGUID("{0de611fd-31e9-5ddc-9d71-95eda26eff32}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Frame6)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2Frame6) RemoveScreenCaptureStarting(token EventRegistratio hr, _, _ := i.Vtbl.RemoveScreenCaptureStarting.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2FrameCreatedEventArgs.go b/pkg/webview2/ICoreWebView2FrameCreatedEventArgs.go index e8a1f16..66b52a4 100644 --- a/pkg/webview2/ICoreWebView2FrameCreatedEventArgs.go +++ b/pkg/webview2/ICoreWebView2FrameCreatedEventArgs.go @@ -22,6 +22,19 @@ func (i *ICoreWebView2FrameCreatedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2FrameCreatedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2FrameCreatedEventArgs) GetFrame() (*ICoreWebView2Frame, error) { var value *ICoreWebView2Frame diff --git a/pkg/webview2/ICoreWebView2FrameInfo.go b/pkg/webview2/ICoreWebView2FrameInfo.go index 8f8defd..05fe28a 100644 --- a/pkg/webview2/ICoreWebView2FrameInfo.go +++ b/pkg/webview2/ICoreWebView2FrameInfo.go @@ -23,13 +23,26 @@ func (i *ICoreWebView2FrameInfo) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2FrameInfo) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2FrameInfo) GetName() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -46,7 +59,7 @@ func (i *ICoreWebView2FrameInfo) GetSource() (string, error) { hr, _, _ := i.Vtbl.GetSource.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2FrameInfo2.go b/pkg/webview2/ICoreWebView2FrameInfo2.go index 3991d11..fc8ac5e 100644 --- a/pkg/webview2/ICoreWebView2FrameInfo2.go +++ b/pkg/webview2/ICoreWebView2FrameInfo2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2FrameInfo2Vtbl struct { - IUnknownVtbl + ICoreWebView2FrameInfoVtbl GetParentFrameInfo ComProc GetFrameId ComProc GetFrameKind ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2FrameInfo2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2FrameInfo2() *ICoreWebView2FrameInfo2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2FrameInfo2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2FrameInfo) GetICoreWebView2FrameInfo2() *ICoreWebView2FrameInfo2 { var result *ICoreWebView2FrameInfo2 iidICoreWebView2FrameInfo2 := NewGUID("{56f85cfa-72c4-11ee-b962-0242ac120002}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2FrameInfo2)), diff --git a/pkg/webview2/ICoreWebView2FrameInfoCollection.go b/pkg/webview2/ICoreWebView2FrameInfoCollection.go index c23462e..32a386f 100644 --- a/pkg/webview2/ICoreWebView2FrameInfoCollection.go +++ b/pkg/webview2/ICoreWebView2FrameInfoCollection.go @@ -22,6 +22,19 @@ func (i *ICoreWebView2FrameInfoCollection) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2FrameInfoCollection) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2FrameInfoCollection) GetIterator() (*ICoreWebView2FrameInfoCollectionIterator, error) { var value *ICoreWebView2FrameInfoCollectionIterator diff --git a/pkg/webview2/ICoreWebView2FrameInfoCollectionIterator.go b/pkg/webview2/ICoreWebView2FrameInfoCollectionIterator.go index 9651543..5d8c8d3 100644 --- a/pkg/webview2/ICoreWebView2FrameInfoCollectionIterator.go +++ b/pkg/webview2/ICoreWebView2FrameInfoCollectionIterator.go @@ -24,6 +24,19 @@ func (i *ICoreWebView2FrameInfoCollectionIterator) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2FrameInfoCollectionIterator) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2FrameInfoCollectionIterator) GetHasCurrent() (bool, error) { // Create int32 to hold bool result var _value int32 diff --git a/pkg/webview2/ICoreWebView2HttpHeadersCollectionIterator.go b/pkg/webview2/ICoreWebView2HttpHeadersCollectionIterator.go index c27457a..ed76d4e 100644 --- a/pkg/webview2/ICoreWebView2HttpHeadersCollectionIterator.go +++ b/pkg/webview2/ICoreWebView2HttpHeadersCollectionIterator.go @@ -24,6 +24,19 @@ func (i *ICoreWebView2HttpHeadersCollectionIterator) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2HttpHeadersCollectionIterator) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2HttpHeadersCollectionIterator) GetCurrentHeader() (string, string, error) { // Create *uint16 to hold result var _name *uint16 @@ -32,8 +45,8 @@ func (i *ICoreWebView2HttpHeadersCollectionIterator) GetCurrentHeader() (string, hr, _, _ := i.Vtbl.GetCurrentHeader.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_name)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_name)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2HttpRequestHeaders.go b/pkg/webview2/ICoreWebView2HttpRequestHeaders.go index 12e7bac..7ad5be0 100644 --- a/pkg/webview2/ICoreWebView2HttpRequestHeaders.go +++ b/pkg/webview2/ICoreWebView2HttpRequestHeaders.go @@ -27,19 +27,32 @@ func (i *ICoreWebView2HttpRequestHeaders) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2HttpRequestHeaders) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2HttpRequestHeaders) GetHeader(name string) (string, error) { // Convert string 'name' to *uint16 _name, err := UTF16PtrFromString(name) if err != nil { - return "", nil + return "", err } // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetHeader.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(_name)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -75,7 +88,7 @@ func (i *ICoreWebView2HttpRequestHeaders) Contains(name string) (bool, error) { // Convert string 'name' to *uint16 _name, err := UTF16PtrFromString(name) if err != nil { - return false, nil + return false, err } // Create int32 to hold bool result var _value int32 diff --git a/pkg/webview2/ICoreWebView2HttpResponseHeaders.go b/pkg/webview2/ICoreWebView2HttpResponseHeaders.go index 819a480..86e907d 100644 --- a/pkg/webview2/ICoreWebView2HttpResponseHeaders.go +++ b/pkg/webview2/ICoreWebView2HttpResponseHeaders.go @@ -26,6 +26,19 @@ func (i *ICoreWebView2HttpResponseHeaders) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2HttpResponseHeaders) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2HttpResponseHeaders) AppendHeader(name string, value string) error { // Convert string 'name' to *uint16 @@ -47,7 +60,7 @@ func (i *ICoreWebView2HttpResponseHeaders) AppendHeader(name string, value strin if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) } - return err + return nil } func (i *ICoreWebView2HttpResponseHeaders) Contains(name string) (bool, error) { @@ -55,7 +68,7 @@ func (i *ICoreWebView2HttpResponseHeaders) Contains(name string) (bool, error) { // Convert string 'name' to *uint16 _name, err := UTF16PtrFromString(name) if err != nil { - return false, nil + return false, err } // Create int32 to hold bool result var _value int32 @@ -77,14 +90,14 @@ func (i *ICoreWebView2HttpResponseHeaders) GetHeader(name string) (string, error // Convert string 'name' to *uint16 _name, err := UTF16PtrFromString(name) if err != nil { - return "", nil + return "", err } // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetHeader.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(_name)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2LaunchingExternalUriSchemeEventArgs.go b/pkg/webview2/ICoreWebView2LaunchingExternalUriSchemeEventArgs.go index e710652..b201c63 100644 --- a/pkg/webview2/ICoreWebView2LaunchingExternalUriSchemeEventArgs.go +++ b/pkg/webview2/ICoreWebView2LaunchingExternalUriSchemeEventArgs.go @@ -27,13 +27,26 @@ func (i *ICoreWebView2LaunchingExternalUriSchemeEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2LaunchingExternalUriSchemeEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2LaunchingExternalUriSchemeEventArgs) GetUri() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -50,7 +63,7 @@ func (i *ICoreWebView2LaunchingExternalUriSchemeEventArgs) GetInitiatingOrigin() hr, _, _ := i.Vtbl.GetInitiatingOrigin.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -97,7 +110,7 @@ func (i *ICoreWebView2LaunchingExternalUriSchemeEventArgs) PutCancel(value bool) hr, _, _ := i.Vtbl.PutCancel.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2MoveFocusRequestedEventArgs.go b/pkg/webview2/ICoreWebView2MoveFocusRequestedEventArgs.go index 0f4a5c0..1910d12 100644 --- a/pkg/webview2/ICoreWebView2MoveFocusRequestedEventArgs.go +++ b/pkg/webview2/ICoreWebView2MoveFocusRequestedEventArgs.go @@ -24,6 +24,19 @@ func (i *ICoreWebView2MoveFocusRequestedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2MoveFocusRequestedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2MoveFocusRequestedEventArgs) GetReason() (COREWEBVIEW2_MOVE_FOCUS_REASON, error) { var reason COREWEBVIEW2_MOVE_FOCUS_REASON @@ -58,7 +71,7 @@ func (i *ICoreWebView2MoveFocusRequestedEventArgs) PutHandled(value bool) error hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2NavigationCompletedEventArgs.go b/pkg/webview2/ICoreWebView2NavigationCompletedEventArgs.go index 7c42f37..5720d69 100644 --- a/pkg/webview2/ICoreWebView2NavigationCompletedEventArgs.go +++ b/pkg/webview2/ICoreWebView2NavigationCompletedEventArgs.go @@ -24,6 +24,19 @@ func (i *ICoreWebView2NavigationCompletedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NavigationCompletedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2NavigationCompletedEventArgs) GetIsSuccess() (bool, error) { // Create int32 to hold bool result var _isSuccess int32 diff --git a/pkg/webview2/ICoreWebView2NavigationCompletedEventArgs2.go b/pkg/webview2/ICoreWebView2NavigationCompletedEventArgs2.go index e0db30a..308a36e 100644 --- a/pkg/webview2/ICoreWebView2NavigationCompletedEventArgs2.go +++ b/pkg/webview2/ICoreWebView2NavigationCompletedEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2NavigationCompletedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2NavigationCompletedEventArgsVtbl GetHttpStatusCode ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2NavigationCompletedEventArgs2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2NavigationCompletedEventArgs2() *ICoreWebView2NavigationCompletedEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NavigationCompletedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2NavigationCompletedEventArgs) GetICoreWebView2NavigationCompletedEventArgs2() *ICoreWebView2NavigationCompletedEventArgs2 { var result *ICoreWebView2NavigationCompletedEventArgs2 iidICoreWebView2NavigationCompletedEventArgs2 := NewGUID("{fdf8b738-ee1e-4db2-a329-8d7d7b74d792}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2NavigationCompletedEventArgs2)), @@ -34,13 +54,13 @@ func (i *ICoreWebView2) GetICoreWebView2NavigationCompletedEventArgs2() *ICoreWe return result } -func (i *ICoreWebView2NavigationCompletedEventArgs2) GetHttpStatusCode() (int, error) { +func (i *ICoreWebView2NavigationCompletedEventArgs2) GetHttpStatusCode() (int32, error) { - var value int + var value int32 hr, _, _ := i.Vtbl.GetHttpStatusCode.Call( uintptr(unsafe.Pointer(i)), - uintptr(value), + uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { return 0, syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2NavigationStartingEventArgs.go b/pkg/webview2/ICoreWebView2NavigationStartingEventArgs.go index 34e6b25..c0e276a 100644 --- a/pkg/webview2/ICoreWebView2NavigationStartingEventArgs.go +++ b/pkg/webview2/ICoreWebView2NavigationStartingEventArgs.go @@ -28,13 +28,26 @@ func (i *ICoreWebView2NavigationStartingEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NavigationStartingEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2NavigationStartingEventArgs) GetUri() (string, error) { // Create *uint16 to hold result var _uri *uint16 hr, _, _ := i.Vtbl.GetUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_uri)), + uintptr(unsafe.Pointer(&_uri)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -111,7 +124,7 @@ func (i *ICoreWebView2NavigationStartingEventArgs) PutCancel(cancel bool) error hr, _, _ := i.Vtbl.PutCancel.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&cancel)), + boolToUintptr(cancel), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2NavigationStartingEventArgs2.go b/pkg/webview2/ICoreWebView2NavigationStartingEventArgs2.go index 16d2e3e..01bb863 100644 --- a/pkg/webview2/ICoreWebView2NavigationStartingEventArgs2.go +++ b/pkg/webview2/ICoreWebView2NavigationStartingEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2NavigationStartingEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2NavigationStartingEventArgsVtbl GetAdditionalAllowedFrameAncestors ComProc PutAdditionalAllowedFrameAncestors ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2NavigationStartingEventArgs2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2NavigationStartingEventArgs2() *ICoreWebView2NavigationStartingEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NavigationStartingEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2NavigationStartingEventArgs) GetICoreWebView2NavigationStartingEventArgs2() *ICoreWebView2NavigationStartingEventArgs2 { var result *ICoreWebView2NavigationStartingEventArgs2 iidICoreWebView2NavigationStartingEventArgs2 := NewGUID("{9086be93-91aa-472d-a7e0-579f2ba006ad}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2NavigationStartingEventArgs2)), @@ -41,7 +61,7 @@ func (i *ICoreWebView2NavigationStartingEventArgs2) GetAdditionalAllowedFrameAnc hr, _, _ := i.Vtbl.GetAdditionalAllowedFrameAncestors.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2NavigationStartingEventArgs3.go b/pkg/webview2/ICoreWebView2NavigationStartingEventArgs3.go index c04120e..048fd82 100644 --- a/pkg/webview2/ICoreWebView2NavigationStartingEventArgs3.go +++ b/pkg/webview2/ICoreWebView2NavigationStartingEventArgs3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2NavigationStartingEventArgs3Vtbl struct { - IUnknownVtbl + ICoreWebView2NavigationStartingEventArgs2Vtbl GetNavigationKind ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2NavigationStartingEventArgs3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2NavigationStartingEventArgs3() *ICoreWebView2NavigationStartingEventArgs3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NavigationStartingEventArgs3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2NavigationStartingEventArgs) GetICoreWebView2NavigationStartingEventArgs3() *ICoreWebView2NavigationStartingEventArgs3 { var result *ICoreWebView2NavigationStartingEventArgs3 iidICoreWebView2NavigationStartingEventArgs3 := NewGUID("{ddffe494-4942-4bd2-ab73-35b8ff40e19f}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2NavigationStartingEventArgs3)), diff --git a/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs.go b/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs.go index c47edc7..973bb0b 100644 --- a/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs.go +++ b/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs.go @@ -29,13 +29,26 @@ func (i *ICoreWebView2NewWindowRequestedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NewWindowRequestedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2NewWindowRequestedEventArgs) GetUri() (string, error) { // Create *uint16 to hold result var _uri *uint16 hr, _, _ := i.Vtbl.GetUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_uri)), + uintptr(unsafe.Pointer(&_uri)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -76,7 +89,7 @@ func (i *ICoreWebView2NewWindowRequestedEventArgs) PutHandled(handled bool) erro hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&handled)), + boolToUintptr(handled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs2.go b/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs2.go index 727437c..1744b58 100644 --- a/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs2.go +++ b/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2NewWindowRequestedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2NewWindowRequestedEventArgsVtbl GetName ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2NewWindowRequestedEventArgs2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2NewWindowRequestedEventArgs2() *ICoreWebView2NewWindowRequestedEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NewWindowRequestedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2NewWindowRequestedEventArgs) GetICoreWebView2NewWindowRequestedEventArgs2() *ICoreWebView2NewWindowRequestedEventArgs2 { var result *ICoreWebView2NewWindowRequestedEventArgs2 iidICoreWebView2NewWindowRequestedEventArgs2 := NewGUID("{bbc7baed-74c6-4c92-b63a-7f5aeae03de3}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2NewWindowRequestedEventArgs2)), @@ -40,7 +60,7 @@ func (i *ICoreWebView2NewWindowRequestedEventArgs2) GetName() (string, error) { hr, _, _ := i.Vtbl.GetName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs3.go b/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs3.go index 99cc223..df828a5 100644 --- a/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs3.go +++ b/pkg/webview2/ICoreWebView2NewWindowRequestedEventArgs3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2NewWindowRequestedEventArgs3Vtbl struct { - IUnknownVtbl + ICoreWebView2NewWindowRequestedEventArgs2Vtbl GetOriginalSourceFrameInfo ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2NewWindowRequestedEventArgs3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2NewWindowRequestedEventArgs3() *ICoreWebView2NewWindowRequestedEventArgs3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NewWindowRequestedEventArgs3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2NewWindowRequestedEventArgs) GetICoreWebView2NewWindowRequestedEventArgs3() *ICoreWebView2NewWindowRequestedEventArgs3 { var result *ICoreWebView2NewWindowRequestedEventArgs3 iidICoreWebView2NewWindowRequestedEventArgs3 := NewGUID("{842bed3c-6ad6-4dd9-b938-28c96667ad66}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2NewWindowRequestedEventArgs3)), diff --git a/pkg/webview2/ICoreWebView2NonClientRegionChangedEventArgs.go b/pkg/webview2/ICoreWebView2NonClientRegionChangedEventArgs.go index 9fa76a5..1eb37da 100644 --- a/pkg/webview2/ICoreWebView2NonClientRegionChangedEventArgs.go +++ b/pkg/webview2/ICoreWebView2NonClientRegionChangedEventArgs.go @@ -22,6 +22,19 @@ func (i *ICoreWebView2NonClientRegionChangedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NonClientRegionChangedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2NonClientRegionChangedEventArgs) GetRegionKind() (COREWEBVIEW2_NON_CLIENT_REGION_KIND, error) { var value COREWEBVIEW2_NON_CLIENT_REGION_KIND diff --git a/pkg/webview2/ICoreWebView2Notification.go b/pkg/webview2/ICoreWebView2Notification.go index 29e2996..8c669f2 100644 --- a/pkg/webview2/ICoreWebView2Notification.go +++ b/pkg/webview2/ICoreWebView2Notification.go @@ -39,6 +39,19 @@ func (i *ICoreWebView2Notification) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Notification) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Notification) AddCloseRequested(eventHandler *ICoreWebView2NotificationCloseRequestedEventHandler) (EventRegistrationToken, error) { var token EventRegistrationToken @@ -58,7 +71,7 @@ func (i *ICoreWebView2Notification) RemoveCloseRequested(token EventRegistration hr, _, _ := i.Vtbl.RemoveCloseRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -105,7 +118,7 @@ func (i *ICoreWebView2Notification) GetBody() (string, error) { hr, _, _ := i.Vtbl.GetBody.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -136,7 +149,7 @@ func (i *ICoreWebView2Notification) GetLanguage() (string, error) { hr, _, _ := i.Vtbl.GetLanguage.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -153,7 +166,7 @@ func (i *ICoreWebView2Notification) GetTag() (string, error) { hr, _, _ := i.Vtbl.GetTag.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -170,7 +183,7 @@ func (i *ICoreWebView2Notification) GetIconUri() (string, error) { hr, _, _ := i.Vtbl.GetIconUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -187,7 +200,7 @@ func (i *ICoreWebView2Notification) GetTitle() (string, error) { hr, _, _ := i.Vtbl.GetTitle.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -204,7 +217,7 @@ func (i *ICoreWebView2Notification) GetBadgeUri() (string, error) { hr, _, _ := i.Vtbl.GetBadgeUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -221,7 +234,7 @@ func (i *ICoreWebView2Notification) GetBodyImageUri() (string, error) { hr, _, _ := i.Vtbl.GetBodyImageUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2NotificationReceivedEventArgs.go b/pkg/webview2/ICoreWebView2NotificationReceivedEventArgs.go index 304802c..dc3c4e0 100644 --- a/pkg/webview2/ICoreWebView2NotificationReceivedEventArgs.go +++ b/pkg/webview2/ICoreWebView2NotificationReceivedEventArgs.go @@ -26,13 +26,26 @@ func (i *ICoreWebView2NotificationReceivedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2NotificationReceivedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2NotificationReceivedEventArgs) GetSenderOrigin() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetSenderOrigin.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -61,7 +74,7 @@ func (i *ICoreWebView2NotificationReceivedEventArgs) PutHandled(value bool) erro hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ObjectCollection.go b/pkg/webview2/ICoreWebView2ObjectCollection.go index 0c87011..80e8765 100644 --- a/pkg/webview2/ICoreWebView2ObjectCollection.go +++ b/pkg/webview2/ICoreWebView2ObjectCollection.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2ObjectCollectionVtbl struct { - IUnknownVtbl + ICoreWebView2ObjectCollectionViewVtbl RemoveValueAtIndex ComProc InsertValueAtIndex ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2ObjectCollection) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2ObjectCollection() *ICoreWebView2ObjectCollection { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ObjectCollection) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2ObjectCollectionView) GetICoreWebView2ObjectCollection() *ICoreWebView2ObjectCollection { var result *ICoreWebView2ObjectCollection iidICoreWebView2ObjectCollection := NewGUID("{5cfec11c-25bd-4e8d-9e1a-7acdaeeec047}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2ObjectCollection)), @@ -39,7 +59,7 @@ func (i *ICoreWebView2ObjectCollection) RemoveValueAtIndex(index uint32) error { hr, _, _ := i.Vtbl.RemoveValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -51,7 +71,7 @@ func (i *ICoreWebView2ObjectCollection) InsertValueAtIndex(index uint32, value * hr, _, _ := i.Vtbl.InsertValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2ObjectCollectionView.go b/pkg/webview2/ICoreWebView2ObjectCollectionView.go index cdad6e7..73456c9 100644 --- a/pkg/webview2/ICoreWebView2ObjectCollectionView.go +++ b/pkg/webview2/ICoreWebView2ObjectCollectionView.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2ObjectCollectionView) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ObjectCollectionView) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ObjectCollectionView) GetCount() (uint32, error) { var value uint32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2ObjectCollectionView) GetValueAtIndex(index uint32) (*IUnk hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs.go b/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs.go index 832a4c6..688190e 100644 --- a/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs.go +++ b/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs.go @@ -27,13 +27,26 @@ func (i *ICoreWebView2PermissionRequestedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2PermissionRequestedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2PermissionRequestedEventArgs) GetUri() (string, error) { // Create *uint16 to hold result var _uri *uint16 hr, _, _ := i.Vtbl.GetUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_uri)), + uintptr(unsafe.Pointer(&_uri)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs2.go b/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs2.go index 0093325..c2e8537 100644 --- a/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs2.go +++ b/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2PermissionRequestedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2PermissionRequestedEventArgsVtbl GetHandled ComProc PutHandled ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2PermissionRequestedEventArgs2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2PermissionRequestedEventArgs2() *ICoreWebView2PermissionRequestedEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2PermissionRequestedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2PermissionRequestedEventArgs) GetICoreWebView2PermissionRequestedEventArgs2() *ICoreWebView2PermissionRequestedEventArgs2 { var result *ICoreWebView2PermissionRequestedEventArgs2 iidICoreWebView2PermissionRequestedEventArgs2 := NewGUID("{74d7127f-9de6-4200-8734-42d6fb4ff741}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2PermissionRequestedEventArgs2)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2PermissionRequestedEventArgs2) PutHandled(value bool) erro hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs3.go b/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs3.go index 99fc5d3..a3dc780 100644 --- a/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs3.go +++ b/pkg/webview2/ICoreWebView2PermissionRequestedEventArgs3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2PermissionRequestedEventArgs3Vtbl struct { - IUnknownVtbl + ICoreWebView2PermissionRequestedEventArgs2Vtbl GetSavesInProfile ComProc PutSavesInProfile ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2PermissionRequestedEventArgs3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2PermissionRequestedEventArgs3() *ICoreWebView2PermissionRequestedEventArgs3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2PermissionRequestedEventArgs3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2PermissionRequestedEventArgs) GetICoreWebView2PermissionRequestedEventArgs3() *ICoreWebView2PermissionRequestedEventArgs3 { var result *ICoreWebView2PermissionRequestedEventArgs3 iidICoreWebView2PermissionRequestedEventArgs3 := NewGUID("{e61670bc-3dce-4177-86d2-c629ae3cb6ac}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2PermissionRequestedEventArgs3)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2PermissionRequestedEventArgs3) PutSavesInProfile(value boo hr, _, _ := i.Vtbl.PutSavesInProfile.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2PermissionSetting.go b/pkg/webview2/ICoreWebView2PermissionSetting.go index 7bcbdd7..ae594e5 100644 --- a/pkg/webview2/ICoreWebView2PermissionSetting.go +++ b/pkg/webview2/ICoreWebView2PermissionSetting.go @@ -24,6 +24,19 @@ func (i *ICoreWebView2PermissionSetting) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2PermissionSetting) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2PermissionSetting) GetPermissionKind() (COREWEBVIEW2_PERMISSION_KIND, error) { var value COREWEBVIEW2_PERMISSION_KIND @@ -44,7 +57,7 @@ func (i *ICoreWebView2PermissionSetting) GetPermissionOrigin() (string, error) { hr, _, _ := i.Vtbl.GetPermissionOrigin.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2PermissionSettingCollectionView.go b/pkg/webview2/ICoreWebView2PermissionSettingCollectionView.go index bd9a4b7..f8579d8 100644 --- a/pkg/webview2/ICoreWebView2PermissionSettingCollectionView.go +++ b/pkg/webview2/ICoreWebView2PermissionSettingCollectionView.go @@ -23,13 +23,26 @@ func (i *ICoreWebView2PermissionSettingCollectionView) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2PermissionSettingCollectionView) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2PermissionSettingCollectionView) GetValueAtIndex(index uint32) (*ICoreWebView2PermissionSetting, error) { var permissionSetting *ICoreWebView2PermissionSetting hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&permissionSetting)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2PointerInfo.go b/pkg/webview2/ICoreWebView2PointerInfo.go index 240ce64..ad82b30 100644 --- a/pkg/webview2/ICoreWebView2PointerInfo.go +++ b/pkg/webview2/ICoreWebView2PointerInfo.go @@ -77,6 +77,19 @@ func (i *ICoreWebView2PointerInfo) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2PointerInfo) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2PointerInfo) GetPointerKind() (uint32, error) { var pointerKind uint32 @@ -95,7 +108,7 @@ func (i *ICoreWebView2PointerInfo) PutPointerKind(pointerKind uint32) error { hr, _, _ := i.Vtbl.PutPointerKind.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&pointerKind)), + uintptr(pointerKind), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -121,7 +134,7 @@ func (i *ICoreWebView2PointerInfo) PutPointerId(pointerId uint32) error { hr, _, _ := i.Vtbl.PutPointerId.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&pointerId)), + uintptr(pointerId), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -147,7 +160,7 @@ func (i *ICoreWebView2PointerInfo) PutFrameId(frameId uint32) error { hr, _, _ := i.Vtbl.PutFrameId.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&frameId)), + uintptr(frameId), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -173,7 +186,7 @@ func (i *ICoreWebView2PointerInfo) PutPointerFlags(pointerFlags uint32) error { hr, _, _ := i.Vtbl.PutPointerFlags.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&pointerFlags)), + uintptr(pointerFlags), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -251,7 +264,7 @@ func (i *ICoreWebView2PointerInfo) PutPixelLocation(pixelLocation POINT) error { hr, _, _ := i.Vtbl.PutPixelLocation.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&pixelLocation)), + uintptr(*(*uint64)(unsafe.Pointer(&pixelLocation))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -277,7 +290,7 @@ func (i *ICoreWebView2PointerInfo) PutHimetricLocation(himetricLocation POINT) e hr, _, _ := i.Vtbl.PutHimetricLocation.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&himetricLocation)), + uintptr(*(*uint64)(unsafe.Pointer(&himetricLocation))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -303,7 +316,7 @@ func (i *ICoreWebView2PointerInfo) PutPixelLocationRaw(pixelLocationRaw POINT) e hr, _, _ := i.Vtbl.PutPixelLocationRaw.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&pixelLocationRaw)), + uintptr(*(*uint64)(unsafe.Pointer(&pixelLocationRaw))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -329,7 +342,7 @@ func (i *ICoreWebView2PointerInfo) PutHimetricLocationRaw(himetricLocationRaw PO hr, _, _ := i.Vtbl.PutHimetricLocationRaw.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&himetricLocationRaw)), + uintptr(*(*uint64)(unsafe.Pointer(&himetricLocationRaw))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -355,7 +368,7 @@ func (i *ICoreWebView2PointerInfo) PutTime(time uint32) error { hr, _, _ := i.Vtbl.PutTime.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&time)), + uintptr(time), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -381,7 +394,7 @@ func (i *ICoreWebView2PointerInfo) PutHistoryCount(historyCount uint32) error { hr, _, _ := i.Vtbl.PutHistoryCount.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&historyCount)), + uintptr(historyCount), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -407,7 +420,7 @@ func (i *ICoreWebView2PointerInfo) PutInputData(inputData int32) error { hr, _, _ := i.Vtbl.PutInputData.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&inputData)), + uintptr(inputData), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -433,7 +446,7 @@ func (i *ICoreWebView2PointerInfo) PutKeyStates(keyStates uint32) error { hr, _, _ := i.Vtbl.PutKeyStates.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&keyStates)), + uintptr(keyStates), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -459,7 +472,7 @@ func (i *ICoreWebView2PointerInfo) PutPerformanceCount(performanceCount uint64) hr, _, _ := i.Vtbl.PutPerformanceCount.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&performanceCount)), + uintptr(performanceCount), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -485,7 +498,7 @@ func (i *ICoreWebView2PointerInfo) PutButtonChangeKind(buttonChangeKind int32) e hr, _, _ := i.Vtbl.PutButtonChangeKind.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&buttonChangeKind)), + uintptr(buttonChangeKind), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -511,7 +524,7 @@ func (i *ICoreWebView2PointerInfo) PutPenFlags(penFLags uint32) error { hr, _, _ := i.Vtbl.PutPenFlags.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&penFLags)), + uintptr(penFLags), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -537,7 +550,7 @@ func (i *ICoreWebView2PointerInfo) PutPenMask(penMask uint32) error { hr, _, _ := i.Vtbl.PutPenMask.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&penMask)), + uintptr(penMask), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -563,7 +576,7 @@ func (i *ICoreWebView2PointerInfo) PutPenPressure(penPressure uint32) error { hr, _, _ := i.Vtbl.PutPenPressure.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&penPressure)), + uintptr(penPressure), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -589,7 +602,7 @@ func (i *ICoreWebView2PointerInfo) PutPenRotation(penRotation uint32) error { hr, _, _ := i.Vtbl.PutPenRotation.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&penRotation)), + uintptr(penRotation), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -615,7 +628,7 @@ func (i *ICoreWebView2PointerInfo) PutPenTiltX(penTiltX int32) error { hr, _, _ := i.Vtbl.PutPenTiltX.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&penTiltX)), + uintptr(penTiltX), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -641,7 +654,7 @@ func (i *ICoreWebView2PointerInfo) PutPenTiltY(penTiltY int32) error { hr, _, _ := i.Vtbl.PutPenTiltY.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&penTiltY)), + uintptr(penTiltY), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -667,7 +680,7 @@ func (i *ICoreWebView2PointerInfo) PutTouchFlags(touchFlags uint32) error { hr, _, _ := i.Vtbl.PutTouchFlags.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&touchFlags)), + uintptr(touchFlags), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -693,7 +706,7 @@ func (i *ICoreWebView2PointerInfo) PutTouchMask(touchMask uint32) error { hr, _, _ := i.Vtbl.PutTouchMask.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&touchMask)), + uintptr(touchMask), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -771,7 +784,7 @@ func (i *ICoreWebView2PointerInfo) PutTouchOrientation(touchOrientation uint32) hr, _, _ := i.Vtbl.PutTouchOrientation.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&touchOrientation)), + uintptr(touchOrientation), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -797,7 +810,7 @@ func (i *ICoreWebView2PointerInfo) PutTouchPressure(touchPressure uint32) error hr, _, _ := i.Vtbl.PutTouchPressure.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&touchPressure)), + uintptr(touchPressure), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2PrintSettings.go b/pkg/webview2/ICoreWebView2PrintSettings.go index 3841e6a..0c57387 100644 --- a/pkg/webview2/ICoreWebView2PrintSettings.go +++ b/pkg/webview2/ICoreWebView2PrintSettings.go @@ -4,6 +4,7 @@ package webview2 import ( "golang.org/x/sys/windows" + "math" "syscall" "unsafe" ) @@ -47,6 +48,19 @@ func (i *ICoreWebView2PrintSettings) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2PrintSettings) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2PrintSettings) GetOrientation() (COREWEBVIEW2_PRINT_ORIENTATION, error) { var orientation COREWEBVIEW2_PRINT_ORIENTATION @@ -91,7 +105,7 @@ func (i *ICoreWebView2PrintSettings) PutScaleFactor(scaleFactor float64) error { hr, _, _ := i.Vtbl.PutScaleFactor.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&scaleFactor)), + uintptr(math.Float64bits(scaleFactor)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -117,7 +131,7 @@ func (i *ICoreWebView2PrintSettings) PutPageWidth(pageWidth float64) error { hr, _, _ := i.Vtbl.PutPageWidth.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&pageWidth)), + uintptr(math.Float64bits(pageWidth)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -143,7 +157,7 @@ func (i *ICoreWebView2PrintSettings) PutPageHeight(pageHeight float64) error { hr, _, _ := i.Vtbl.PutPageHeight.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&pageHeight)), + uintptr(math.Float64bits(pageHeight)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -169,7 +183,7 @@ func (i *ICoreWebView2PrintSettings) PutMarginTop(marginTop float64) error { hr, _, _ := i.Vtbl.PutMarginTop.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&marginTop)), + uintptr(math.Float64bits(marginTop)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -195,7 +209,7 @@ func (i *ICoreWebView2PrintSettings) PutMarginBottom(marginBottom float64) error hr, _, _ := i.Vtbl.PutMarginBottom.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&marginBottom)), + uintptr(math.Float64bits(marginBottom)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -221,7 +235,7 @@ func (i *ICoreWebView2PrintSettings) PutMarginLeft(marginLeft float64) error { hr, _, _ := i.Vtbl.PutMarginLeft.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&marginLeft)), + uintptr(math.Float64bits(marginLeft)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -247,7 +261,7 @@ func (i *ICoreWebView2PrintSettings) PutMarginRight(marginRight float64) error { hr, _, _ := i.Vtbl.PutMarginRight.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&marginRight)), + uintptr(math.Float64bits(marginRight)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -275,7 +289,7 @@ func (i *ICoreWebView2PrintSettings) PutShouldPrintBackgrounds(shouldPrintBackgr hr, _, _ := i.Vtbl.PutShouldPrintBackgrounds.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&shouldPrintBackgrounds)), + boolToUintptr(shouldPrintBackgrounds), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -303,7 +317,7 @@ func (i *ICoreWebView2PrintSettings) PutShouldPrintSelectionOnly(shouldPrintSele hr, _, _ := i.Vtbl.PutShouldPrintSelectionOnly.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&shouldPrintSelectionOnly)), + boolToUintptr(shouldPrintSelectionOnly), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -331,7 +345,7 @@ func (i *ICoreWebView2PrintSettings) PutShouldPrintHeaderAndFooter(shouldPrintHe hr, _, _ := i.Vtbl.PutShouldPrintHeaderAndFooter.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&shouldPrintHeaderAndFooter)), + boolToUintptr(shouldPrintHeaderAndFooter), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -345,7 +359,7 @@ func (i *ICoreWebView2PrintSettings) GetHeaderTitle() (string, error) { hr, _, _ := i.Vtbl.GetHeaderTitle.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_headerTitle)), + uintptr(unsafe.Pointer(&_headerTitle)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -380,7 +394,7 @@ func (i *ICoreWebView2PrintSettings) GetFooterUri() (string, error) { hr, _, _ := i.Vtbl.GetFooterUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_footerUri)), + uintptr(unsafe.Pointer(&_footerUri)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2PrintSettings2.go b/pkg/webview2/ICoreWebView2PrintSettings2.go index 616f44d..80c259e 100644 --- a/pkg/webview2/ICoreWebView2PrintSettings2.go +++ b/pkg/webview2/ICoreWebView2PrintSettings2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2PrintSettings2Vtbl struct { - IUnknownVtbl + ICoreWebView2PrintSettingsVtbl GetPageRanges ComProc PutPageRanges ComProc GetPagesPerSide ComProc @@ -37,10 +37,30 @@ func (i *ICoreWebView2PrintSettings2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2PrintSettings2() *ICoreWebView2PrintSettings2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2PrintSettings2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2PrintSettings) GetICoreWebView2PrintSettings2() *ICoreWebView2PrintSettings2 { var result *ICoreWebView2PrintSettings2 iidICoreWebView2PrintSettings2 := NewGUID("{CA7F0E1F-3484-41D1-8C1A-65CD44A63F8D}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2PrintSettings2)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2PrintSettings2) GetPageRanges() (string, error) { hr, _, _ := i.Vtbl.GetPageRanges.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -102,7 +122,7 @@ func (i *ICoreWebView2PrintSettings2) PutPagesPerSide(value int32) error { hr, _, _ := i.Vtbl.PutPagesPerSide.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + uintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -128,7 +148,7 @@ func (i *ICoreWebView2PrintSettings2) PutCopies(value int32) error { hr, _, _ := i.Vtbl.PutCopies.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + uintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -246,7 +266,7 @@ func (i *ICoreWebView2PrintSettings2) GetPrinterName() (string, error) { hr, _, _ := i.Vtbl.GetPrinterName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ProcessExtendedInfo.go b/pkg/webview2/ICoreWebView2ProcessExtendedInfo.go index 55d4ba9..66e0a63 100644 --- a/pkg/webview2/ICoreWebView2ProcessExtendedInfo.go +++ b/pkg/webview2/ICoreWebView2ProcessExtendedInfo.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2ProcessExtendedInfo) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ProcessExtendedInfo) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ProcessExtendedInfo) GetProcessInfo() (*ICoreWebView2ProcessInfo, error) { var processInfo *ICoreWebView2ProcessInfo diff --git a/pkg/webview2/ICoreWebView2ProcessExtendedInfoCollection.go b/pkg/webview2/ICoreWebView2ProcessExtendedInfoCollection.go index 48a4a19..5a10376 100644 --- a/pkg/webview2/ICoreWebView2ProcessExtendedInfoCollection.go +++ b/pkg/webview2/ICoreWebView2ProcessExtendedInfoCollection.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2ProcessExtendedInfoCollection) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ProcessExtendedInfoCollection) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ProcessExtendedInfoCollection) GetCount() (uint32, error) { var value uint32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2ProcessExtendedInfoCollection) GetValueAtIndex(index uint3 hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2ProcessFailedEventArgs.go b/pkg/webview2/ICoreWebView2ProcessFailedEventArgs.go index 1f6aad6..8e0b576 100644 --- a/pkg/webview2/ICoreWebView2ProcessFailedEventArgs.go +++ b/pkg/webview2/ICoreWebView2ProcessFailedEventArgs.go @@ -22,6 +22,19 @@ func (i *ICoreWebView2ProcessFailedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ProcessFailedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ProcessFailedEventArgs) GetProcessFailedKind() (COREWEBVIEW2_PROCESS_FAILED_KIND, error) { var value COREWEBVIEW2_PROCESS_FAILED_KIND diff --git a/pkg/webview2/ICoreWebView2ProcessFailedEventArgs2.go b/pkg/webview2/ICoreWebView2ProcessFailedEventArgs2.go index 3a85b42..707847a 100644 --- a/pkg/webview2/ICoreWebView2ProcessFailedEventArgs2.go +++ b/pkg/webview2/ICoreWebView2ProcessFailedEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2ProcessFailedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2ProcessFailedEventArgsVtbl GetReason ComProc GetExitCode ComProc GetProcessDescription ComProc @@ -25,10 +25,30 @@ func (i *ICoreWebView2ProcessFailedEventArgs2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2ProcessFailedEventArgs2() *ICoreWebView2ProcessFailedEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ProcessFailedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2ProcessFailedEventArgs) GetICoreWebView2ProcessFailedEventArgs2() *ICoreWebView2ProcessFailedEventArgs2 { var result *ICoreWebView2ProcessFailedEventArgs2 iidICoreWebView2ProcessFailedEventArgs2 := NewGUID("{4dab9422-46fa-4c3e-a5d2-41d2071d3680}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2ProcessFailedEventArgs2)), @@ -51,13 +71,13 @@ func (i *ICoreWebView2ProcessFailedEventArgs2) GetReason() (COREWEBVIEW2_PROCESS return reason, nil } -func (i *ICoreWebView2ProcessFailedEventArgs2) GetExitCode() (int, error) { +func (i *ICoreWebView2ProcessFailedEventArgs2) GetExitCode() (int32, error) { - var exitCode int + var exitCode int32 hr, _, _ := i.Vtbl.GetExitCode.Call( uintptr(unsafe.Pointer(i)), - uintptr(exitCode), + uintptr(unsafe.Pointer(&exitCode)), ) if windows.Handle(hr) != windows.S_OK { return 0, syscall.Errno(hr) @@ -71,7 +91,7 @@ func (i *ICoreWebView2ProcessFailedEventArgs2) GetProcessDescription() (string, hr, _, _ := i.Vtbl.GetProcessDescription.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_processDescription)), + uintptr(unsafe.Pointer(&_processDescription)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ProcessFailedEventArgs3.go b/pkg/webview2/ICoreWebView2ProcessFailedEventArgs3.go index bd13dd3..8ed5f4a 100644 --- a/pkg/webview2/ICoreWebView2ProcessFailedEventArgs3.go +++ b/pkg/webview2/ICoreWebView2ProcessFailedEventArgs3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2ProcessFailedEventArgs3Vtbl struct { - IUnknownVtbl + ICoreWebView2ProcessFailedEventArgs2Vtbl GetFailureSourceModulePath ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2ProcessFailedEventArgs3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2ProcessFailedEventArgs3() *ICoreWebView2ProcessFailedEventArgs3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ProcessFailedEventArgs3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2ProcessFailedEventArgs) GetICoreWebView2ProcessFailedEventArgs3() *ICoreWebView2ProcessFailedEventArgs3 { var result *ICoreWebView2ProcessFailedEventArgs3 iidICoreWebView2ProcessFailedEventArgs3 := NewGUID("{ab667428-094d-5fd1-b480-8b4c0fdbdf2f}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2ProcessFailedEventArgs3)), @@ -40,7 +60,7 @@ func (i *ICoreWebView2ProcessFailedEventArgs3) GetFailureSourceModulePath() (str hr, _, _ := i.Vtbl.GetFailureSourceModulePath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ProcessInfo.go b/pkg/webview2/ICoreWebView2ProcessInfo.go index 8b52898..ff6c108 100644 --- a/pkg/webview2/ICoreWebView2ProcessInfo.go +++ b/pkg/webview2/ICoreWebView2ProcessInfo.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2ProcessInfo) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ProcessInfo) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ProcessInfo) GetProcessId() (int32, error) { var value int32 diff --git a/pkg/webview2/ICoreWebView2ProcessInfoCollection.go b/pkg/webview2/ICoreWebView2ProcessInfoCollection.go index 10707c4..a034e35 100644 --- a/pkg/webview2/ICoreWebView2ProcessInfoCollection.go +++ b/pkg/webview2/ICoreWebView2ProcessInfoCollection.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2ProcessInfoCollection) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ProcessInfoCollection) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ProcessInfoCollection) GetCount() (uint32, error) { var value uint32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2ProcessInfoCollection) GetValueAtIndex(index uint32) (*ICo hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2Profile.go b/pkg/webview2/ICoreWebView2Profile.go index 6c4568e..082bf61 100644 --- a/pkg/webview2/ICoreWebView2Profile.go +++ b/pkg/webview2/ICoreWebView2Profile.go @@ -28,13 +28,26 @@ func (i *ICoreWebView2Profile) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Profile) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Profile) GetProfileName() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetProfileName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -67,7 +80,7 @@ func (i *ICoreWebView2Profile) GetProfilePath() (string, error) { hr, _, _ := i.Vtbl.GetProfilePath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -84,7 +97,7 @@ func (i *ICoreWebView2Profile) GetDefaultDownloadFolderPath() (string, error) { hr, _, _ := i.Vtbl.GetDefaultDownloadFolderPath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Profile2.go b/pkg/webview2/ICoreWebView2Profile2.go index cef10dd..802e875 100644 --- a/pkg/webview2/ICoreWebView2Profile2.go +++ b/pkg/webview2/ICoreWebView2Profile2.go @@ -4,12 +4,13 @@ package webview2 import ( "golang.org/x/sys/windows" + "math" "syscall" "unsafe" ) type ICoreWebView2Profile2Vtbl struct { - IUnknownVtbl + ICoreWebView2ProfileVtbl ClearBrowsingData ComProc ClearBrowsingDataInTimeRange ComProc ClearBrowsingDataAll ComProc @@ -24,10 +25,30 @@ func (i *ICoreWebView2Profile2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Profile2() *ICoreWebView2Profile2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Profile2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Profile) GetICoreWebView2Profile2() *ICoreWebView2Profile2 { var result *ICoreWebView2Profile2 iidICoreWebView2Profile2 := NewGUID("{fa740d4b-5eae-4344-a8ad-74be31925397}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Profile2)), @@ -54,8 +75,8 @@ func (i *ICoreWebView2Profile2) ClearBrowsingDataInTimeRange(dataKinds COREWEBVI hr, _, _ := i.Vtbl.ClearBrowsingDataInTimeRange.Call( uintptr(unsafe.Pointer(i)), uintptr(dataKinds), - uintptr(unsafe.Pointer(&startTime)), - uintptr(unsafe.Pointer(&endTime)), + uintptr(math.Float64bits(startTime)), + uintptr(math.Float64bits(endTime)), uintptr(unsafe.Pointer(handler)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2Profile3.go b/pkg/webview2/ICoreWebView2Profile3.go index da5ccc4..4a24e67 100644 --- a/pkg/webview2/ICoreWebView2Profile3.go +++ b/pkg/webview2/ICoreWebView2Profile3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Profile3Vtbl struct { - IUnknownVtbl + ICoreWebView2Profile2Vtbl GetPreferredTrackingPreventionLevel ComProc PutPreferredTrackingPreventionLevel ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Profile3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Profile3() *ICoreWebView2Profile3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Profile3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Profile) GetICoreWebView2Profile3() *ICoreWebView2Profile3 { var result *ICoreWebView2Profile3 iidICoreWebView2Profile3 := NewGUID("{b188e659-5685-4e05-bdba-fc640e0f1992}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Profile3)), diff --git a/pkg/webview2/ICoreWebView2Profile4.go b/pkg/webview2/ICoreWebView2Profile4.go index 92e36e3..e31498a 100644 --- a/pkg/webview2/ICoreWebView2Profile4.go +++ b/pkg/webview2/ICoreWebView2Profile4.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Profile4Vtbl struct { - IUnknownVtbl + ICoreWebView2Profile3Vtbl SetPermissionState ComProc GetNonDefaultPermissionSettings ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Profile4) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Profile4() *ICoreWebView2Profile4 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Profile4) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Profile) GetICoreWebView2Profile4() *ICoreWebView2Profile4 { var result *ICoreWebView2Profile4 iidICoreWebView2Profile4 := NewGUID("{8f4ae680-192e-4ec8-833a-21cfadaef628}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Profile4)), diff --git a/pkg/webview2/ICoreWebView2Profile5.go b/pkg/webview2/ICoreWebView2Profile5.go index ecff06d..2d2174a 100644 --- a/pkg/webview2/ICoreWebView2Profile5.go +++ b/pkg/webview2/ICoreWebView2Profile5.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Profile5Vtbl struct { - IUnknownVtbl + ICoreWebView2Profile4Vtbl GetCookieManager ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2Profile5) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Profile5() *ICoreWebView2Profile5 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Profile5) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Profile) GetICoreWebView2Profile5() *ICoreWebView2Profile5 { var result *ICoreWebView2Profile5 iidICoreWebView2Profile5 := NewGUID("{2ee5b76e-6e80-4df2-bcd3-d4ec3340a01b}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Profile5)), diff --git a/pkg/webview2/ICoreWebView2Profile6.go b/pkg/webview2/ICoreWebView2Profile6.go index 1223998..e590a2d 100644 --- a/pkg/webview2/ICoreWebView2Profile6.go +++ b/pkg/webview2/ICoreWebView2Profile6.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Profile6Vtbl struct { - IUnknownVtbl + ICoreWebView2Profile5Vtbl GetIsPasswordAutosaveEnabled ComProc PutIsPasswordAutosaveEnabled ComProc GetIsGeneralAutofillEnabled ComProc @@ -25,10 +25,30 @@ func (i *ICoreWebView2Profile6) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Profile6() *ICoreWebView2Profile6 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Profile6) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Profile) GetICoreWebView2Profile6() *ICoreWebView2Profile6 { var result *ICoreWebView2Profile6 iidICoreWebView2Profile6 := NewGUID("{BD82FA6A-1D65-4C33-B2B4-0393020CC61B}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Profile6)), @@ -57,7 +77,7 @@ func (i *ICoreWebView2Profile6) PutIsPasswordAutosaveEnabled(value bool) error { hr, _, _ := i.Vtbl.PutIsPasswordAutosaveEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -85,7 +105,7 @@ func (i *ICoreWebView2Profile6) PutIsGeneralAutofillEnabled(value bool) error { hr, _, _ := i.Vtbl.PutIsGeneralAutofillEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Profile7.go b/pkg/webview2/ICoreWebView2Profile7.go index 4bc784b..b5903ce 100644 --- a/pkg/webview2/ICoreWebView2Profile7.go +++ b/pkg/webview2/ICoreWebView2Profile7.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Profile7Vtbl struct { - IUnknownVtbl + ICoreWebView2Profile6Vtbl AddBrowserExtension ComProc GetBrowserExtensions ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Profile7) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Profile7() *ICoreWebView2Profile7 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Profile7) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Profile) GetICoreWebView2Profile7() *ICoreWebView2Profile7 { var result *ICoreWebView2Profile7 iidICoreWebView2Profile7 := NewGUID("{7b4c7906-a1aa-4cb4-b723-db09f813d541}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Profile7)), diff --git a/pkg/webview2/ICoreWebView2Profile8.go b/pkg/webview2/ICoreWebView2Profile8.go index 151cce8..c489012 100644 --- a/pkg/webview2/ICoreWebView2Profile8.go +++ b/pkg/webview2/ICoreWebView2Profile8.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Profile8Vtbl struct { - IUnknownVtbl + ICoreWebView2Profile7Vtbl Delete ComProc AddDeleted ComProc RemoveDeleted ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2Profile8) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Profile8() *ICoreWebView2Profile8 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Profile8) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Profile) GetICoreWebView2Profile8() *ICoreWebView2Profile8 { var result *ICoreWebView2Profile8 iidICoreWebView2Profile8 := NewGUID("{fbf70c2f-eb1f-4383-85a0-163e92044011}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Profile8)), @@ -66,7 +86,7 @@ func (i *ICoreWebView2Profile8) RemoveDeleted(token EventRegistrationToken) erro hr, _, _ := i.Vtbl.RemoveDeleted.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2RegionRectCollectionView.go b/pkg/webview2/ICoreWebView2RegionRectCollectionView.go index bb25fec..7296baa 100644 --- a/pkg/webview2/ICoreWebView2RegionRectCollectionView.go +++ b/pkg/webview2/ICoreWebView2RegionRectCollectionView.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2RegionRectCollectionView) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2RegionRectCollectionView) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2RegionRectCollectionView) GetCount() (uint32, error) { var value uint32 @@ -43,7 +56,7 @@ func (i *ICoreWebView2RegionRectCollectionView) GetValueAtIndex(index uint32) (R hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), + uintptr(index), uintptr(unsafe.Pointer(&value)), ) if windows.Handle(hr) != windows.S_OK { diff --git a/pkg/webview2/ICoreWebView2SaveAsUIShowingEventArgs.go b/pkg/webview2/ICoreWebView2SaveAsUIShowingEventArgs.go index 0034ebc..15e76ff 100644 --- a/pkg/webview2/ICoreWebView2SaveAsUIShowingEventArgs.go +++ b/pkg/webview2/ICoreWebView2SaveAsUIShowingEventArgs.go @@ -33,13 +33,26 @@ func (i *ICoreWebView2SaveAsUIShowingEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2SaveAsUIShowingEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2SaveAsUIShowingEventArgs) GetContentMimeType() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetContentMimeType.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -54,7 +67,7 @@ func (i *ICoreWebView2SaveAsUIShowingEventArgs) PutCancel(value bool) error { hr, _, _ := i.Vtbl.PutCancel.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -82,7 +95,7 @@ func (i *ICoreWebView2SaveAsUIShowingEventArgs) PutSuppressDefaultDialog(value b hr, _, _ := i.Vtbl.PutSuppressDefaultDialog.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -144,7 +157,7 @@ func (i *ICoreWebView2SaveAsUIShowingEventArgs) GetSaveAsFilePath() (string, err hr, _, _ := i.Vtbl.GetSaveAsFilePath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -159,7 +172,7 @@ func (i *ICoreWebView2SaveAsUIShowingEventArgs) PutAllowReplace(value bool) erro hr, _, _ := i.Vtbl.PutAllowReplace.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2SaveFileSecurityCheckStartingEventArgs.go b/pkg/webview2/ICoreWebView2SaveFileSecurityCheckStartingEventArgs.go index 98990b5..cbf4bb9 100644 --- a/pkg/webview2/ICoreWebView2SaveFileSecurityCheckStartingEventArgs.go +++ b/pkg/webview2/ICoreWebView2SaveFileSecurityCheckStartingEventArgs.go @@ -29,6 +29,19 @@ func (i *ICoreWebView2SaveFileSecurityCheckStartingEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2SaveFileSecurityCheckStartingEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2SaveFileSecurityCheckStartingEventArgs) GetCancelSave() (bool, error) { // Create int32 to hold bool result var _value int32 @@ -49,7 +62,7 @@ func (i *ICoreWebView2SaveFileSecurityCheckStartingEventArgs) PutCancelSave(valu hr, _, _ := i.Vtbl.PutCancelSave.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -63,7 +76,7 @@ func (i *ICoreWebView2SaveFileSecurityCheckStartingEventArgs) GetDocumentOriginU hr, _, _ := i.Vtbl.GetDocumentOriginUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -80,7 +93,7 @@ func (i *ICoreWebView2SaveFileSecurityCheckStartingEventArgs) GetFileExtension() hr, _, _ := i.Vtbl.GetFileExtension.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -97,7 +110,7 @@ func (i *ICoreWebView2SaveFileSecurityCheckStartingEventArgs) GetFilePath() (str hr, _, _ := i.Vtbl.GetFilePath.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -128,7 +141,7 @@ func (i *ICoreWebView2SaveFileSecurityCheckStartingEventArgs) PutSuppressDefault hr, _, _ := i.Vtbl.PutSuppressDefaultPolicy.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ScreenCaptureStartingEventArgs.go b/pkg/webview2/ICoreWebView2ScreenCaptureStartingEventArgs.go index c276af4..da6f8cb 100644 --- a/pkg/webview2/ICoreWebView2ScreenCaptureStartingEventArgs.go +++ b/pkg/webview2/ICoreWebView2ScreenCaptureStartingEventArgs.go @@ -27,6 +27,19 @@ func (i *ICoreWebView2ScreenCaptureStartingEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ScreenCaptureStartingEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ScreenCaptureStartingEventArgs) GetCancel() (bool, error) { // Create int32 to hold bool result var _value int32 @@ -47,7 +60,7 @@ func (i *ICoreWebView2ScreenCaptureStartingEventArgs) PutCancel(value bool) erro hr, _, _ := i.Vtbl.PutCancel.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -75,7 +88,7 @@ func (i *ICoreWebView2ScreenCaptureStartingEventArgs) PutHandled(value bool) err hr, _, _ := i.Vtbl.PutHandled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ScriptDialogOpeningEventArgs.go b/pkg/webview2/ICoreWebView2ScriptDialogOpeningEventArgs.go index 30de940..1245b6d 100644 --- a/pkg/webview2/ICoreWebView2ScriptDialogOpeningEventArgs.go +++ b/pkg/webview2/ICoreWebView2ScriptDialogOpeningEventArgs.go @@ -29,13 +29,26 @@ func (i *ICoreWebView2ScriptDialogOpeningEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ScriptDialogOpeningEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ScriptDialogOpeningEventArgs) GetUri() (string, error) { // Create *uint16 to hold result var _uri *uint16 hr, _, _ := i.Vtbl.GetUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_uri)), + uintptr(unsafe.Pointer(&_uri)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -66,7 +79,7 @@ func (i *ICoreWebView2ScriptDialogOpeningEventArgs) GetMessage() (string, error) hr, _, _ := i.Vtbl.GetMessage.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_message)), + uintptr(unsafe.Pointer(&_message)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -94,7 +107,7 @@ func (i *ICoreWebView2ScriptDialogOpeningEventArgs) GetDefaultText() (string, er hr, _, _ := i.Vtbl.GetDefaultText.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_defaultText)), + uintptr(unsafe.Pointer(&_defaultText)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -111,7 +124,7 @@ func (i *ICoreWebView2ScriptDialogOpeningEventArgs) GetResultText() (string, err hr, _, _ := i.Vtbl.GetResultText.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_resultText)), + uintptr(unsafe.Pointer(&_resultText)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ScriptException.go b/pkg/webview2/ICoreWebView2ScriptException.go index 087dd6a..bf9781e 100644 --- a/pkg/webview2/ICoreWebView2ScriptException.go +++ b/pkg/webview2/ICoreWebView2ScriptException.go @@ -26,6 +26,19 @@ func (i *ICoreWebView2ScriptException) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ScriptException) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ScriptException) GetLineNumber() (uint32, error) { var value uint32 @@ -60,7 +73,7 @@ func (i *ICoreWebView2ScriptException) GetName() (string, error) { hr, _, _ := i.Vtbl.GetName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -77,7 +90,7 @@ func (i *ICoreWebView2ScriptException) GetMessage() (string, error) { hr, _, _ := i.Vtbl.GetMessage.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -94,7 +107,7 @@ func (i *ICoreWebView2ScriptException) GetToJson() (string, error) { hr, _, _ := i.Vtbl.GetToJson.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2ServerCertificateErrorDetectedEventArgs.go b/pkg/webview2/ICoreWebView2ServerCertificateErrorDetectedEventArgs.go index 1ff59d0..c146408 100644 --- a/pkg/webview2/ICoreWebView2ServerCertificateErrorDetectedEventArgs.go +++ b/pkg/webview2/ICoreWebView2ServerCertificateErrorDetectedEventArgs.go @@ -27,6 +27,19 @@ func (i *ICoreWebView2ServerCertificateErrorDetectedEventArgs) AddRef() uintptr return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ServerCertificateErrorDetectedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2ServerCertificateErrorDetectedEventArgs) GetErrorStatus() (COREWEBVIEW2_WEB_ERROR_STATUS, error) { var value COREWEBVIEW2_WEB_ERROR_STATUS @@ -47,7 +60,7 @@ func (i *ICoreWebView2ServerCertificateErrorDetectedEventArgs) GetRequestUri() ( hr, _, _ := i.Vtbl.GetRequestUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Settings.go b/pkg/webview2/ICoreWebView2Settings.go index c86a892..2cc9c09 100644 --- a/pkg/webview2/ICoreWebView2Settings.go +++ b/pkg/webview2/ICoreWebView2Settings.go @@ -39,6 +39,19 @@ func (i *ICoreWebView2Settings) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2Settings) GetIsScriptEnabled() (bool, error) { // Create int32 to hold bool result var _isScriptEnabled int32 @@ -59,7 +72,7 @@ func (i *ICoreWebView2Settings) PutIsScriptEnabled(isScriptEnabled bool) error { hr, _, _ := i.Vtbl.PutIsScriptEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&isScriptEnabled)), + boolToUintptr(isScriptEnabled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -87,7 +100,7 @@ func (i *ICoreWebView2Settings) PutIsWebMessageEnabled(isWebMessageEnabled bool) hr, _, _ := i.Vtbl.PutIsWebMessageEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&isWebMessageEnabled)), + boolToUintptr(isWebMessageEnabled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -115,7 +128,7 @@ func (i *ICoreWebView2Settings) PutAreDefaultScriptDialogsEnabled(areDefaultScri hr, _, _ := i.Vtbl.PutAreDefaultScriptDialogsEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)), + boolToUintptr(areDefaultScriptDialogsEnabled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -143,7 +156,7 @@ func (i *ICoreWebView2Settings) PutIsStatusBarEnabled(isStatusBarEnabled bool) e hr, _, _ := i.Vtbl.PutIsStatusBarEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&isStatusBarEnabled)), + boolToUintptr(isStatusBarEnabled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -171,7 +184,7 @@ func (i *ICoreWebView2Settings) PutAreDevToolsEnabled(areDevToolsEnabled bool) e hr, _, _ := i.Vtbl.PutAreDevToolsEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&areDevToolsEnabled)), + boolToUintptr(areDevToolsEnabled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -199,7 +212,7 @@ func (i *ICoreWebView2Settings) PutAreDefaultContextMenusEnabled(enabled bool) e hr, _, _ := i.Vtbl.PutAreDefaultContextMenusEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&enabled)), + boolToUintptr(enabled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -227,7 +240,7 @@ func (i *ICoreWebView2Settings) PutAreHostObjectsAllowed(allowed bool) error { hr, _, _ := i.Vtbl.PutAreHostObjectsAllowed.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&allowed)), + boolToUintptr(allowed), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -255,7 +268,7 @@ func (i *ICoreWebView2Settings) PutIsZoomControlEnabled(enabled bool) error { hr, _, _ := i.Vtbl.PutIsZoomControlEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&enabled)), + boolToUintptr(enabled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -283,7 +296,7 @@ func (i *ICoreWebView2Settings) PutIsBuiltInErrorPageEnabled(enabled bool) error hr, _, _ := i.Vtbl.PutIsBuiltInErrorPageEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&enabled)), + boolToUintptr(enabled), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Settings2.go b/pkg/webview2/ICoreWebView2Settings2.go index 4151843..c02772c 100644 --- a/pkg/webview2/ICoreWebView2Settings2.go +++ b/pkg/webview2/ICoreWebView2Settings2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Settings2Vtbl struct { - IUnknownVtbl + ICoreWebView2SettingsVtbl GetUserAgent ComProc PutUserAgent ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Settings2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Settings2() *ICoreWebView2Settings2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Settings) GetICoreWebView2Settings2() *ICoreWebView2Settings2 { var result *ICoreWebView2Settings2 iidICoreWebView2Settings2 := NewGUID("{ee9a0f68-f46c-4e32-ac23-ef8cac224d2a}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Settings2)), @@ -41,7 +61,7 @@ func (i *ICoreWebView2Settings2) GetUserAgent() (string, error) { hr, _, _ := i.Vtbl.GetUserAgent.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Settings3.go b/pkg/webview2/ICoreWebView2Settings3.go index 71c74ef..c1f52e4 100644 --- a/pkg/webview2/ICoreWebView2Settings3.go +++ b/pkg/webview2/ICoreWebView2Settings3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Settings3Vtbl struct { - IUnknownVtbl + ICoreWebView2Settings2Vtbl GetAreBrowserAcceleratorKeysEnabled ComProc PutAreBrowserAcceleratorKeysEnabled ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Settings3) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Settings3() *ICoreWebView2Settings3 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Settings) GetICoreWebView2Settings3() *ICoreWebView2Settings3 { var result *ICoreWebView2Settings3 iidICoreWebView2Settings3 := NewGUID("{fdb5ab74-af33-4854-84f0-0a631deb5eba}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Settings3)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2Settings3) PutAreBrowserAcceleratorKeysEnabled(value bool) hr, _, _ := i.Vtbl.PutAreBrowserAcceleratorKeysEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Settings4.go b/pkg/webview2/ICoreWebView2Settings4.go index 0d81a6e..86263ce 100644 --- a/pkg/webview2/ICoreWebView2Settings4.go +++ b/pkg/webview2/ICoreWebView2Settings4.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Settings4Vtbl struct { - IUnknownVtbl + ICoreWebView2Settings3Vtbl GetIsPasswordAutosaveEnabled ComProc PutIsPasswordAutosaveEnabled ComProc GetIsGeneralAutofillEnabled ComProc @@ -25,10 +25,30 @@ func (i *ICoreWebView2Settings4) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Settings4() *ICoreWebView2Settings4 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings4) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Settings) GetICoreWebView2Settings4() *ICoreWebView2Settings4 { var result *ICoreWebView2Settings4 iidICoreWebView2Settings4 := NewGUID("{cb56846c-4168-4d53-b04f-03b6d6796ff2}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Settings4)), @@ -57,7 +77,7 @@ func (i *ICoreWebView2Settings4) PutIsPasswordAutosaveEnabled(value bool) error hr, _, _ := i.Vtbl.PutIsPasswordAutosaveEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -85,7 +105,7 @@ func (i *ICoreWebView2Settings4) PutIsGeneralAutofillEnabled(value bool) error { hr, _, _ := i.Vtbl.PutIsGeneralAutofillEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Settings5.go b/pkg/webview2/ICoreWebView2Settings5.go index 88db9de..f13b524 100644 --- a/pkg/webview2/ICoreWebView2Settings5.go +++ b/pkg/webview2/ICoreWebView2Settings5.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Settings5Vtbl struct { - IUnknownVtbl + ICoreWebView2Settings4Vtbl GetIsPinchZoomEnabled ComProc PutIsPinchZoomEnabled ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Settings5) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Settings5() *ICoreWebView2Settings5 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings5) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Settings) GetICoreWebView2Settings5() *ICoreWebView2Settings5 { var result *ICoreWebView2Settings5 iidICoreWebView2Settings5 := NewGUID("{183e7052-1d03-43a0-ab99-98e043b66b39}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Settings5)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2Settings5) PutIsPinchZoomEnabled(value bool) error { hr, _, _ := i.Vtbl.PutIsPinchZoomEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Settings6.go b/pkg/webview2/ICoreWebView2Settings6.go index 8e91efc..7bec758 100644 --- a/pkg/webview2/ICoreWebView2Settings6.go +++ b/pkg/webview2/ICoreWebView2Settings6.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Settings6Vtbl struct { - IUnknownVtbl + ICoreWebView2Settings5Vtbl GetIsSwipeNavigationEnabled ComProc PutIsSwipeNavigationEnabled ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Settings6) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Settings6() *ICoreWebView2Settings6 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings6) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Settings) GetICoreWebView2Settings6() *ICoreWebView2Settings6 { var result *ICoreWebView2Settings6 iidICoreWebView2Settings6 := NewGUID("{11cb3acd-9bc8-43b8-83bf-f40753714f87}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Settings6)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2Settings6) PutIsSwipeNavigationEnabled(value bool) error { hr, _, _ := i.Vtbl.PutIsSwipeNavigationEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Settings7.go b/pkg/webview2/ICoreWebView2Settings7.go index 1d1a6fe..5cd80ef 100644 --- a/pkg/webview2/ICoreWebView2Settings7.go +++ b/pkg/webview2/ICoreWebView2Settings7.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Settings7Vtbl struct { - IUnknownVtbl + ICoreWebView2Settings6Vtbl GetHiddenPdfToolbarItems ComProc PutHiddenPdfToolbarItems ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Settings7) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Settings7() *ICoreWebView2Settings7 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings7) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Settings) GetICoreWebView2Settings7() *ICoreWebView2Settings7 { var result *ICoreWebView2Settings7 iidICoreWebView2Settings7 := NewGUID("{488dc902-35ef-42d2-bc7d-94b65c4bc49c}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Settings7)), diff --git a/pkg/webview2/ICoreWebView2Settings8.go b/pkg/webview2/ICoreWebView2Settings8.go index d4697a3..830cb1b 100644 --- a/pkg/webview2/ICoreWebView2Settings8.go +++ b/pkg/webview2/ICoreWebView2Settings8.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Settings8Vtbl struct { - IUnknownVtbl + ICoreWebView2Settings7Vtbl GetIsReputationCheckingRequired ComProc PutIsReputationCheckingRequired ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Settings8) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Settings8() *ICoreWebView2Settings8 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings8) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Settings) GetICoreWebView2Settings8() *ICoreWebView2Settings8 { var result *ICoreWebView2Settings8 iidICoreWebView2Settings8 := NewGUID("{9e6b0e8f-86ad-4e81-8147-a9b5edb68650}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Settings8)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2Settings8) PutIsReputationCheckingRequired(value bool) err hr, _, _ := i.Vtbl.PutIsReputationCheckingRequired.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2Settings9.go b/pkg/webview2/ICoreWebView2Settings9.go index da9ac91..7d33b72 100644 --- a/pkg/webview2/ICoreWebView2Settings9.go +++ b/pkg/webview2/ICoreWebView2Settings9.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2Settings9Vtbl struct { - IUnknownVtbl + ICoreWebView2Settings8Vtbl GetIsNonClientRegionSupportEnabled ComProc PutIsNonClientRegionSupportEnabled ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2Settings9) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2Settings9() *ICoreWebView2Settings9 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2Settings9) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2Settings) GetICoreWebView2Settings9() *ICoreWebView2Settings9 { var result *ICoreWebView2Settings9 iidICoreWebView2Settings9 := NewGUID("{0528a73b-e92d-49f4-927a-e547dddaa37d}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2Settings9)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2Settings9) PutIsNonClientRegionSupportEnabled(value bool) hr, _, _ := i.Vtbl.PutIsNonClientRegionSupportEnabled.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2SharedBuffer.go b/pkg/webview2/ICoreWebView2SharedBuffer.go index dcc4945..1cba3d6 100644 --- a/pkg/webview2/ICoreWebView2SharedBuffer.go +++ b/pkg/webview2/ICoreWebView2SharedBuffer.go @@ -26,6 +26,19 @@ func (i *ICoreWebView2SharedBuffer) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2SharedBuffer) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2SharedBuffer) GetSize() (uint64, error) { var value uint64 diff --git a/pkg/webview2/ICoreWebView2SourceChangedEventArgs.go b/pkg/webview2/ICoreWebView2SourceChangedEventArgs.go index af64cb8..3f3e9e2 100644 --- a/pkg/webview2/ICoreWebView2SourceChangedEventArgs.go +++ b/pkg/webview2/ICoreWebView2SourceChangedEventArgs.go @@ -22,6 +22,19 @@ func (i *ICoreWebView2SourceChangedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2SourceChangedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2SourceChangedEventArgs) GetIsNewDocument() (bool, error) { // Create int32 to hold bool result var _value int32 diff --git a/pkg/webview2/ICoreWebView2StringCollection.go b/pkg/webview2/ICoreWebView2StringCollection.go index fb3afe4..ab1a2a7 100644 --- a/pkg/webview2/ICoreWebView2StringCollection.go +++ b/pkg/webview2/ICoreWebView2StringCollection.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2StringCollection) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2StringCollection) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2StringCollection) GetCount() (uint32, error) { var value uint32 @@ -43,8 +56,8 @@ func (i *ICoreWebView2StringCollection) GetValueAtIndex(index uint32) (string, e hr, _, _ := i.Vtbl.GetValueAtIndex.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&index)), - uintptr(unsafe.Pointer(_value)), + uintptr(index), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2WebMessageReceivedEventArgs.go b/pkg/webview2/ICoreWebView2WebMessageReceivedEventArgs.go index 3de78bb..7214b06 100644 --- a/pkg/webview2/ICoreWebView2WebMessageReceivedEventArgs.go +++ b/pkg/webview2/ICoreWebView2WebMessageReceivedEventArgs.go @@ -24,13 +24,26 @@ func (i *ICoreWebView2WebMessageReceivedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WebMessageReceivedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2WebMessageReceivedEventArgs) GetSource() (string, error) { // Create *uint16 to hold result var _value *uint16 hr, _, _ := i.Vtbl.GetSource.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -47,7 +60,7 @@ func (i *ICoreWebView2WebMessageReceivedEventArgs) GetWebMessageAsJson() (string hr, _, _ := i.Vtbl.GetWebMessageAsJson.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -64,7 +77,7 @@ func (i *ICoreWebView2WebMessageReceivedEventArgs) TryGetWebMessageAsString() (s hr, _, _ := i.Vtbl.TryGetWebMessageAsString.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2WebMessageReceivedEventArgs2.go b/pkg/webview2/ICoreWebView2WebMessageReceivedEventArgs2.go index 19ae626..c5ca298 100644 --- a/pkg/webview2/ICoreWebView2WebMessageReceivedEventArgs2.go +++ b/pkg/webview2/ICoreWebView2WebMessageReceivedEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2WebMessageReceivedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2WebMessageReceivedEventArgsVtbl GetAdditionalObjects ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2WebMessageReceivedEventArgs2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2WebMessageReceivedEventArgs2() *ICoreWebView2WebMessageReceivedEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WebMessageReceivedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2WebMessageReceivedEventArgs) GetICoreWebView2WebMessageReceivedEventArgs2() *ICoreWebView2WebMessageReceivedEventArgs2 { var result *ICoreWebView2WebMessageReceivedEventArgs2 iidICoreWebView2WebMessageReceivedEventArgs2 := NewGUID("{06fc7ab7-c90c-4297-9389-33ca01cf6d5e}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2WebMessageReceivedEventArgs2)), diff --git a/pkg/webview2/ICoreWebView2WebResourceRequest.go b/pkg/webview2/ICoreWebView2WebResourceRequest.go index e6f467f..c34e57d 100644 --- a/pkg/webview2/ICoreWebView2WebResourceRequest.go +++ b/pkg/webview2/ICoreWebView2WebResourceRequest.go @@ -28,13 +28,26 @@ func (i *ICoreWebView2WebResourceRequest) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WebResourceRequest) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2WebResourceRequest) GetUri() (string, error) { // Create *uint16 to hold result var _uri *uint16 hr, _, _ := i.Vtbl.GetUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_uri)), + uintptr(unsafe.Pointer(&_uri)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -69,7 +82,7 @@ func (i *ICoreWebView2WebResourceRequest) GetMethod() (string, error) { hr, _, _ := i.Vtbl.GetMethod.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_method)), + uintptr(unsafe.Pointer(&_method)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2WebResourceRequestedEventArgs.go b/pkg/webview2/ICoreWebView2WebResourceRequestedEventArgs.go index 6438175..2fdb137 100644 --- a/pkg/webview2/ICoreWebView2WebResourceRequestedEventArgs.go +++ b/pkg/webview2/ICoreWebView2WebResourceRequestedEventArgs.go @@ -26,6 +26,19 @@ func (i *ICoreWebView2WebResourceRequestedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WebResourceRequestedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2WebResourceRequestedEventArgs) GetRequest() (*ICoreWebView2WebResourceRequest, error) { var request *ICoreWebView2WebResourceRequest diff --git a/pkg/webview2/ICoreWebView2WebResourceRequestedEventArgs2.go b/pkg/webview2/ICoreWebView2WebResourceRequestedEventArgs2.go index 1a50c69..053dc15 100644 --- a/pkg/webview2/ICoreWebView2WebResourceRequestedEventArgs2.go +++ b/pkg/webview2/ICoreWebView2WebResourceRequestedEventArgs2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2WebResourceRequestedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2WebResourceRequestedEventArgsVtbl GetRequestedSourceKind ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2WebResourceRequestedEventArgs2) AddRef() uintptr { return refCounter } -func (i *ICoreWebView2) GetICoreWebView2WebResourceRequestedEventArgs2() *ICoreWebView2WebResourceRequestedEventArgs2 { +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WebResourceRequestedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + +func (i *ICoreWebView2WebResourceRequestedEventArgs) GetICoreWebView2WebResourceRequestedEventArgs2() *ICoreWebView2WebResourceRequestedEventArgs2 { var result *ICoreWebView2WebResourceRequestedEventArgs2 iidICoreWebView2WebResourceRequestedEventArgs2 := NewGUID("{9c562c24-b219-4d7f-92f6-b187fbbadd56}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2WebResourceRequestedEventArgs2)), diff --git a/pkg/webview2/ICoreWebView2WebResourceResponse.go b/pkg/webview2/ICoreWebView2WebResourceResponse.go index acb5639..60489bf 100644 --- a/pkg/webview2/ICoreWebView2WebResourceResponse.go +++ b/pkg/webview2/ICoreWebView2WebResourceResponse.go @@ -28,6 +28,19 @@ func (i *ICoreWebView2WebResourceResponse) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WebResourceResponse) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2WebResourceResponse) GetContent() (*IStream, error) { var content *IStream @@ -68,13 +81,13 @@ func (i *ICoreWebView2WebResourceResponse) GetHeaders() (*ICoreWebView2HttpRespo return headers, nil } -func (i *ICoreWebView2WebResourceResponse) GetStatusCode() (int, error) { +func (i *ICoreWebView2WebResourceResponse) GetStatusCode() (int32, error) { - var statusCode int + var statusCode int32 hr, _, _ := i.Vtbl.GetStatusCode.Call( uintptr(unsafe.Pointer(i)), - uintptr(statusCode), + uintptr(unsafe.Pointer(&statusCode)), ) if windows.Handle(hr) != windows.S_OK { return 0, syscall.Errno(hr) @@ -82,7 +95,7 @@ func (i *ICoreWebView2WebResourceResponse) GetStatusCode() (int, error) { return statusCode, nil } -func (i *ICoreWebView2WebResourceResponse) PutStatusCode(statusCode int) error { +func (i *ICoreWebView2WebResourceResponse) PutStatusCode(statusCode int32) error { hr, _, _ := i.Vtbl.PutStatusCode.Call( uintptr(unsafe.Pointer(i)), @@ -100,7 +113,7 @@ func (i *ICoreWebView2WebResourceResponse) GetReasonPhrase() (string, error) { hr, _, _ := i.Vtbl.GetReasonPhrase.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_reasonPhrase)), + uintptr(unsafe.Pointer(&_reasonPhrase)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2WebResourceResponseReceivedEventArgs.go b/pkg/webview2/ICoreWebView2WebResourceResponseReceivedEventArgs.go index a4fbcf9..ba6daf1 100644 --- a/pkg/webview2/ICoreWebView2WebResourceResponseReceivedEventArgs.go +++ b/pkg/webview2/ICoreWebView2WebResourceResponseReceivedEventArgs.go @@ -23,6 +23,19 @@ func (i *ICoreWebView2WebResourceResponseReceivedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WebResourceResponseReceivedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2WebResourceResponseReceivedEventArgs) GetRequest() (*ICoreWebView2WebResourceRequest, error) { var value *ICoreWebView2WebResourceRequest diff --git a/pkg/webview2/ICoreWebView2WebResourceResponseView.go b/pkg/webview2/ICoreWebView2WebResourceResponseView.go index 92eff95..aa5a9df 100644 --- a/pkg/webview2/ICoreWebView2WebResourceResponseView.go +++ b/pkg/webview2/ICoreWebView2WebResourceResponseView.go @@ -25,6 +25,19 @@ func (i *ICoreWebView2WebResourceResponseView) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WebResourceResponseView) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2WebResourceResponseView) GetHeaders() (*ICoreWebView2HttpResponseHeaders, error) { var headers *ICoreWebView2HttpResponseHeaders @@ -39,13 +52,13 @@ func (i *ICoreWebView2WebResourceResponseView) GetHeaders() (*ICoreWebView2HttpR return headers, nil } -func (i *ICoreWebView2WebResourceResponseView) GetStatusCode() (int, error) { +func (i *ICoreWebView2WebResourceResponseView) GetStatusCode() (int32, error) { - var statusCode int + var statusCode int32 hr, _, _ := i.Vtbl.GetStatusCode.Call( uintptr(unsafe.Pointer(i)), - uintptr(statusCode), + uintptr(unsafe.Pointer(&statusCode)), ) if windows.Handle(hr) != windows.S_OK { return 0, syscall.Errno(hr) @@ -59,7 +72,7 @@ func (i *ICoreWebView2WebResourceResponseView) GetReasonPhrase() (string, error) hr, _, _ := i.Vtbl.GetReasonPhrase.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_reasonPhrase)), + uintptr(unsafe.Pointer(&_reasonPhrase)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2WindowFeatures.go b/pkg/webview2/ICoreWebView2WindowFeatures.go index 9dac4b7..1bd776a 100644 --- a/pkg/webview2/ICoreWebView2WindowFeatures.go +++ b/pkg/webview2/ICoreWebView2WindowFeatures.go @@ -31,6 +31,19 @@ func (i *ICoreWebView2WindowFeatures) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2WindowFeatures) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2WindowFeatures) GetHasPosition() (bool, error) { // Create int32 to hold bool result var _value int32 diff --git a/pkg/webview2/ICoreWebView2_10.go b/pkg/webview2/ICoreWebView2_10.go index b30cff8..58799f9 100644 --- a/pkg/webview2/ICoreWebView2_10.go +++ b/pkg/webview2/ICoreWebView2_10.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_10Vtbl struct { - IUnknownVtbl + ICoreWebView2_9Vtbl AddBasicAuthenticationRequested ComProc RemoveBasicAuthenticationRequested ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2_10) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_10) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_10() *ICoreWebView2_10 { var result *ICoreWebView2_10 iidICoreWebView2_10 := NewGUID("{b1690564-6f5a-4983-8e48-31d1143fecdb}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_10)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2_10) RemoveBasicAuthenticationRequested(token EventRegistr hr, _, _ := i.Vtbl.RemoveBasicAuthenticationRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_11.go b/pkg/webview2/ICoreWebView2_11.go index 1588de4..552fe37 100644 --- a/pkg/webview2/ICoreWebView2_11.go +++ b/pkg/webview2/ICoreWebView2_11.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_11Vtbl struct { - IUnknownVtbl + ICoreWebView2_10Vtbl CallDevToolsProtocolMethodForSession ComProc AddContextMenuRequested ComProc RemoveContextMenuRequested ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2_11) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_11) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_11() *ICoreWebView2_11 { var result *ICoreWebView2_11 iidICoreWebView2_11 := NewGUID("{0be78e56-c193-4051-b943-23b460c08bdb}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_11)), @@ -86,7 +106,7 @@ func (i *ICoreWebView2_11) RemoveContextMenuRequested(token EventRegistrationTok hr, _, _ := i.Vtbl.RemoveContextMenuRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_12.go b/pkg/webview2/ICoreWebView2_12.go index 93dd2de..69e6e93 100644 --- a/pkg/webview2/ICoreWebView2_12.go +++ b/pkg/webview2/ICoreWebView2_12.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_12Vtbl struct { - IUnknownVtbl + ICoreWebView2_11Vtbl AddStatusBarTextChanged ComProc RemoveStatusBarTextChanged ComProc GetStatusBarText ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2_12) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_12) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_12() *ICoreWebView2_12 { var result *ICoreWebView2_12 iidICoreWebView2_12 := NewGUID("{35D69927-BCFA-4566-9349-6B3E0D154CAC}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_12)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2_12) RemoveStatusBarTextChanged(token EventRegistrationTok hr, _, _ := i.Vtbl.RemoveStatusBarTextChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -69,7 +89,7 @@ func (i *ICoreWebView2_12) GetStatusBarText() (string, error) { hr, _, _ := i.Vtbl.GetStatusBarText.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_13.go b/pkg/webview2/ICoreWebView2_13.go index a7c973b..ba548c9 100644 --- a/pkg/webview2/ICoreWebView2_13.go +++ b/pkg/webview2/ICoreWebView2_13.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_13Vtbl struct { - IUnknownVtbl + ICoreWebView2_12Vtbl GetProfile ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2_13) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_13) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_13() *ICoreWebView2_13 { var result *ICoreWebView2_13 iidICoreWebView2_13 := NewGUID("{f75f09a8-667e-4983-88d6-c8773f315e84}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_13)), diff --git a/pkg/webview2/ICoreWebView2_14.go b/pkg/webview2/ICoreWebView2_14.go index 3b82850..5d5622a 100644 --- a/pkg/webview2/ICoreWebView2_14.go +++ b/pkg/webview2/ICoreWebView2_14.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_14Vtbl struct { - IUnknownVtbl + ICoreWebView2_13Vtbl AddServerCertificateErrorDetected ComProc RemoveServerCertificateErrorDetected ComProc ClearServerCertificateErrorActions ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2_14) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_14) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_14() *ICoreWebView2_14 { var result *ICoreWebView2_14 iidICoreWebView2_14 := NewGUID("{6daa4f10-4a90-4753-8898-77c5df534165}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_14)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2_14) RemoveServerCertificateErrorDetected(token EventRegis hr, _, _ := i.Vtbl.RemoveServerCertificateErrorDetected.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_15.go b/pkg/webview2/ICoreWebView2_15.go index e85a801..ac98114 100644 --- a/pkg/webview2/ICoreWebView2_15.go +++ b/pkg/webview2/ICoreWebView2_15.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_15Vtbl struct { - IUnknownVtbl + ICoreWebView2_14Vtbl AddFaviconChanged ComProc RemoveFaviconChanged ComProc GetFaviconUri ComProc @@ -25,10 +25,30 @@ func (i *ICoreWebView2_15) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_15) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_15() *ICoreWebView2_15 { var result *ICoreWebView2_15 iidICoreWebView2_15 := NewGUID("{517B2D1D-7DAE-4A66-A4F4-10352FFB9518}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_15)), @@ -56,7 +76,7 @@ func (i *ICoreWebView2_15) RemoveFaviconChanged(token EventRegistrationToken) er hr, _, _ := i.Vtbl.RemoveFaviconChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -70,7 +90,7 @@ func (i *ICoreWebView2_15) GetFaviconUri() (string, error) { hr, _, _ := i.Vtbl.GetFaviconUri.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_value)), + uintptr(unsafe.Pointer(&_value)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_16.go b/pkg/webview2/ICoreWebView2_16.go index 855dedb..0c63fc5 100644 --- a/pkg/webview2/ICoreWebView2_16.go +++ b/pkg/webview2/ICoreWebView2_16.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_16Vtbl struct { - IUnknownVtbl + ICoreWebView2_15Vtbl Print ComProc ShowPrintUI ComProc PrintToPdfStream ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2_16) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_16) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_16() *ICoreWebView2_16 { var result *ICoreWebView2_16 iidICoreWebView2_16 := NewGUID("{0EB34DC9-9F91-41E1-8639-95CD5943906B}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_16)), diff --git a/pkg/webview2/ICoreWebView2_17.go b/pkg/webview2/ICoreWebView2_17.go index 71c5841..4b6eb13 100644 --- a/pkg/webview2/ICoreWebView2_17.go +++ b/pkg/webview2/ICoreWebView2_17.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_17Vtbl struct { - IUnknownVtbl + ICoreWebView2_16Vtbl PostSharedBufferToScript ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2_17) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_17) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_17() *ICoreWebView2_17 { var result *ICoreWebView2_17 iidICoreWebView2_17 := NewGUID("{702e75d4-fd44-434d-9d70-1a68a6b1192a}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_17)), diff --git a/pkg/webview2/ICoreWebView2_18.go b/pkg/webview2/ICoreWebView2_18.go index 7e61d04..b061236 100644 --- a/pkg/webview2/ICoreWebView2_18.go +++ b/pkg/webview2/ICoreWebView2_18.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_18Vtbl struct { - IUnknownVtbl + ICoreWebView2_17Vtbl AddLaunchingExternalUriScheme ComProc RemoveLaunchingExternalUriScheme ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2_18) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_18) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_18() *ICoreWebView2_18 { var result *ICoreWebView2_18 iidICoreWebView2_18 := NewGUID("{7a626017-28be-49b2-b865-3ba2b3522d90}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_18)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2_18) RemoveLaunchingExternalUriScheme(token EventRegistrat hr, _, _ := i.Vtbl.RemoveLaunchingExternalUriScheme.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_19.go b/pkg/webview2/ICoreWebView2_19.go index 9b95eb0..4aea6bf 100644 --- a/pkg/webview2/ICoreWebView2_19.go +++ b/pkg/webview2/ICoreWebView2_19.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_19Vtbl struct { - IUnknownVtbl + ICoreWebView2_18Vtbl GetMemoryUsageTargetLevel ComProc PutMemoryUsageTargetLevel ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2_19) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_19) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_19() *ICoreWebView2_19 { var result *ICoreWebView2_19 iidICoreWebView2_19 := NewGUID("{6921f954-79b0-437f-a997-c85811897c68}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_19)), diff --git a/pkg/webview2/ICoreWebView2_2.go b/pkg/webview2/ICoreWebView2_2.go index 45a2b79..b2180a9 100644 --- a/pkg/webview2/ICoreWebView2_2.go +++ b/pkg/webview2/ICoreWebView2_2.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_2Vtbl struct { - IUnknownVtbl + ICoreWebView2Vtbl AddWebResourceResponseReceived ComProc RemoveWebResourceResponseReceived ComProc NavigateWithWebResourceRequest ComProc @@ -28,10 +28,30 @@ func (i *ICoreWebView2_2) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_2() *ICoreWebView2_2 { var result *ICoreWebView2_2 iidICoreWebView2_2 := NewGUID("{9E8F0CF8-E670-4B5E-B2BC-73E061E3184C}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_2)), @@ -59,7 +79,7 @@ func (i *ICoreWebView2_2) RemoveWebResourceResponseReceived(token EventRegistrat hr, _, _ := i.Vtbl.RemoveWebResourceResponseReceived.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -98,7 +118,7 @@ func (i *ICoreWebView2_2) RemoveDOMContentLoaded(token EventRegistrationToken) e hr, _, _ := i.Vtbl.RemoveDOMContentLoaded.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_20.go b/pkg/webview2/ICoreWebView2_20.go index fbf69ff..db1e405 100644 --- a/pkg/webview2/ICoreWebView2_20.go +++ b/pkg/webview2/ICoreWebView2_20.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_20Vtbl struct { - IUnknownVtbl + ICoreWebView2_19Vtbl GetFrameId ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2_20) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_20) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_20() *ICoreWebView2_20 { var result *ICoreWebView2_20 iidICoreWebView2_20 := NewGUID("{b4bc1926-7305-11ee-b962-0242ac120002}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_20)), diff --git a/pkg/webview2/ICoreWebView2_21.go b/pkg/webview2/ICoreWebView2_21.go index 54a52d3..9c249c8 100644 --- a/pkg/webview2/ICoreWebView2_21.go +++ b/pkg/webview2/ICoreWebView2_21.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_21Vtbl struct { - IUnknownVtbl + ICoreWebView2_20Vtbl ExecuteScriptWithResult ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2_21) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_21) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_21() *ICoreWebView2_21 { var result *ICoreWebView2_21 iidICoreWebView2_21 := NewGUID("{c4980dea-587b-43b9-8143-3ef3bf552d95}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_21)), diff --git a/pkg/webview2/ICoreWebView2_22.go b/pkg/webview2/ICoreWebView2_22.go index 9107307..3cc7c10 100644 --- a/pkg/webview2/ICoreWebView2_22.go +++ b/pkg/webview2/ICoreWebView2_22.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_22Vtbl struct { - IUnknownVtbl + ICoreWebView2_21Vtbl AddWebResourceRequestedFilterWithRequestSourceKinds ComProc RemoveWebResourceRequestedFilterWithRequestSourceKinds ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2_22) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_22) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_22() *ICoreWebView2_22 { var result *ICoreWebView2_22 iidICoreWebView2_22 := NewGUID("{db75dfc7-a857-4632-a398-6969dde26c0a}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_22)), diff --git a/pkg/webview2/ICoreWebView2_23.go b/pkg/webview2/ICoreWebView2_23.go index 6696cfc..08d75f0 100644 --- a/pkg/webview2/ICoreWebView2_23.go +++ b/pkg/webview2/ICoreWebView2_23.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_23Vtbl struct { - IUnknownVtbl + ICoreWebView2_22Vtbl PostWebMessageAsJsonWithAdditionalObjects ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2_23) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_23) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_23() *ICoreWebView2_23 { var result *ICoreWebView2_23 iidICoreWebView2_23 := NewGUID("{508f0db5-90c4-5872-90a7-267a91377502}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_23)), diff --git a/pkg/webview2/ICoreWebView2_24.go b/pkg/webview2/ICoreWebView2_24.go index 88ca87a..0dd78a8 100644 --- a/pkg/webview2/ICoreWebView2_24.go +++ b/pkg/webview2/ICoreWebView2_24.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_24Vtbl struct { - IUnknownVtbl + ICoreWebView2_23Vtbl AddNotificationReceived ComProc RemoveNotificationReceived ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2_24) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_24) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_24() *ICoreWebView2_24 { var result *ICoreWebView2_24 iidICoreWebView2_24 := NewGUID("{39a7ad55-4287-5cc1-88a1-c6f458593824}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_24)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2_24) RemoveNotificationReceived(token EventRegistrationTok hr, _, _ := i.Vtbl.RemoveNotificationReceived.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_25.go b/pkg/webview2/ICoreWebView2_25.go index 8bff273..b0576d5 100644 --- a/pkg/webview2/ICoreWebView2_25.go +++ b/pkg/webview2/ICoreWebView2_25.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_25Vtbl struct { - IUnknownVtbl + ICoreWebView2_24Vtbl AddSaveAsUIShowing ComProc RemoveSaveAsUIShowing ComProc ShowSaveAsUI ComProc @@ -24,10 +24,30 @@ func (i *ICoreWebView2_25) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_25) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_25() *ICoreWebView2_25 { var result *ICoreWebView2_25 iidICoreWebView2_25 := NewGUID("{b5a86092-df50-5b4f-a17b-6c8f8b40b771}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_25)), @@ -55,7 +75,7 @@ func (i *ICoreWebView2_25) RemoveSaveAsUIShowing(token EventRegistrationToken) e hr, _, _ := i.Vtbl.RemoveSaveAsUIShowing.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_26.go b/pkg/webview2/ICoreWebView2_26.go index e8bf63f..5f80ece 100644 --- a/pkg/webview2/ICoreWebView2_26.go +++ b/pkg/webview2/ICoreWebView2_26.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_26Vtbl struct { - IUnknownVtbl + ICoreWebView2_25Vtbl AddSaveFileSecurityCheckStarting ComProc RemoveSaveFileSecurityCheckStarting ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2_26) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_26) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_26() *ICoreWebView2_26 { var result *ICoreWebView2_26 iidICoreWebView2_26 := NewGUID("{806268b8-f897-5685-88e5-c45fca0b1a48}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_26)), @@ -36,6 +56,7 @@ func (i *ICoreWebView2) GetICoreWebView2_26() *ICoreWebView2_26 { } func (i *ICoreWebView2_26) AddSaveFileSecurityCheckStarting(eventHandler *ICoreWebView2SaveFileSecurityCheckStartingEventHandler) (EventRegistrationToken, error) { + var token EventRegistrationToken hr, _, _ := i.Vtbl.AddSaveFileSecurityCheckStarting.Call( @@ -50,9 +71,10 @@ func (i *ICoreWebView2_26) AddSaveFileSecurityCheckStarting(eventHandler *ICoreW } func (i *ICoreWebView2_26) RemoveSaveFileSecurityCheckStarting(token EventRegistrationToken) error { + hr, _, _ := i.Vtbl.RemoveSaveFileSecurityCheckStarting.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_27.go b/pkg/webview2/ICoreWebView2_27.go index 09e1923..c4332f6 100644 --- a/pkg/webview2/ICoreWebView2_27.go +++ b/pkg/webview2/ICoreWebView2_27.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_27Vtbl struct { - IUnknownVtbl + ICoreWebView2_26Vtbl AddScreenCaptureStarting ComProc RemoveScreenCaptureStarting ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2_27) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_27) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_27() *ICoreWebView2_27 { var result *ICoreWebView2_27 iidICoreWebView2_27 := NewGUID("{00fbe33b-8c07-517c-aa23-0ddd4b5f6fa0}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_27)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2_27) RemoveScreenCaptureStarting(token EventRegistrationTo hr, _, _ := i.Vtbl.RemoveScreenCaptureStarting.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_3.go b/pkg/webview2/ICoreWebView2_3.go index f08d23f..6f555dc 100644 --- a/pkg/webview2/ICoreWebView2_3.go +++ b/pkg/webview2/ICoreWebView2_3.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_3Vtbl struct { - IUnknownVtbl + ICoreWebView2_2Vtbl TrySuspend ComProc Resume ComProc GetIsSuspended ComProc @@ -26,10 +26,30 @@ func (i *ICoreWebView2_3) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 { var result *ICoreWebView2_3 iidICoreWebView2_3 := NewGUID("{A0D6DF20-3B92-416D-AA0C-437A9C727857}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_3)), diff --git a/pkg/webview2/ICoreWebView2_4.go b/pkg/webview2/ICoreWebView2_4.go index e513d4f..c5504ad 100644 --- a/pkg/webview2/ICoreWebView2_4.go +++ b/pkg/webview2/ICoreWebView2_4.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_4Vtbl struct { - IUnknownVtbl + ICoreWebView2_3Vtbl AddFrameCreated ComProc RemoveFrameCreated ComProc AddDownloadStarting ComProc @@ -25,10 +25,30 @@ func (i *ICoreWebView2_4) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_4) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_4() *ICoreWebView2_4 { var result *ICoreWebView2_4 iidICoreWebView2_4 := NewGUID("{20d02d59-6df2-42dc-bd06-f98a694b1302}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_4)), @@ -56,7 +76,7 @@ func (i *ICoreWebView2_4) RemoveFrameCreated(token EventRegistrationToken) error hr, _, _ := i.Vtbl.RemoveFrameCreated.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -83,7 +103,7 @@ func (i *ICoreWebView2_4) RemoveDownloadStarting(token EventRegistrationToken) e hr, _, _ := i.Vtbl.RemoveDownloadStarting.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_5.go b/pkg/webview2/ICoreWebView2_5.go index 6c0b39d..1ad7055 100644 --- a/pkg/webview2/ICoreWebView2_5.go +++ b/pkg/webview2/ICoreWebView2_5.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_5Vtbl struct { - IUnknownVtbl + ICoreWebView2_4Vtbl AddClientCertificateRequested ComProc RemoveClientCertificateRequested ComProc } @@ -23,10 +23,30 @@ func (i *ICoreWebView2_5) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_5) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_5() *ICoreWebView2_5 { var result *ICoreWebView2_5 iidICoreWebView2_5 := NewGUID("{bedb11b8-d63c-11eb-b8bc-0242ac130003}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_5)), @@ -54,7 +74,7 @@ func (i *ICoreWebView2_5) RemoveClientCertificateRequested(token EventRegistrati hr, _, _ := i.Vtbl.RemoveClientCertificateRequested.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_6.go b/pkg/webview2/ICoreWebView2_6.go index 1b93eb1..47a216f 100644 --- a/pkg/webview2/ICoreWebView2_6.go +++ b/pkg/webview2/ICoreWebView2_6.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_6Vtbl struct { - IUnknownVtbl + ICoreWebView2_5Vtbl OpenTaskManagerWindow ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2_6) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_6) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_6() *ICoreWebView2_6 { var result *ICoreWebView2_6 iidICoreWebView2_6 := NewGUID("{499aadac-d92c-4589-8a75-111bfc167795}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_6)), diff --git a/pkg/webview2/ICoreWebView2_7.go b/pkg/webview2/ICoreWebView2_7.go index 19b012b..8a3d4f0 100644 --- a/pkg/webview2/ICoreWebView2_7.go +++ b/pkg/webview2/ICoreWebView2_7.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_7Vtbl struct { - IUnknownVtbl + ICoreWebView2_6Vtbl PrintToPdf ComProc } @@ -22,10 +22,30 @@ func (i *ICoreWebView2_7) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_7) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_7() *ICoreWebView2_7 { var result *ICoreWebView2_7 iidICoreWebView2_7 := NewGUID("{79c24d83-09a3-45ae-9418-487f32a58740}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_7)), diff --git a/pkg/webview2/ICoreWebView2_8.go b/pkg/webview2/ICoreWebView2_8.go index a52aa66..c372d14 100644 --- a/pkg/webview2/ICoreWebView2_8.go +++ b/pkg/webview2/ICoreWebView2_8.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_8Vtbl struct { - IUnknownVtbl + ICoreWebView2_7Vtbl AddIsMutedChanged ComProc RemoveIsMutedChanged ComProc GetIsMuted ComProc @@ -28,10 +28,30 @@ func (i *ICoreWebView2_8) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_8) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_8() *ICoreWebView2_8 { var result *ICoreWebView2_8 iidICoreWebView2_8 := NewGUID("{E9632730-6E1E-43AB-B7B8-7B2C9E62E094}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_8)), @@ -59,7 +79,7 @@ func (i *ICoreWebView2_8) RemoveIsMutedChanged(token EventRegistrationToken) err hr, _, _ := i.Vtbl.RemoveIsMutedChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -87,7 +107,7 @@ func (i *ICoreWebView2_8) PutIsMuted(value bool) error { hr, _, _ := i.Vtbl.PutIsMuted.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + boolToUintptr(value), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -114,7 +134,7 @@ func (i *ICoreWebView2_8) RemoveIsDocumentPlayingAudioChanged(token EventRegistr hr, _, _ := i.Vtbl.RemoveIsDocumentPlayingAudioChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/ICoreWebView2_9.go b/pkg/webview2/ICoreWebView2_9.go index c93fee5..7d121c8 100644 --- a/pkg/webview2/ICoreWebView2_9.go +++ b/pkg/webview2/ICoreWebView2_9.go @@ -9,7 +9,7 @@ import ( ) type ICoreWebView2_9Vtbl struct { - IUnknownVtbl + ICoreWebView2_8Vtbl AddIsDefaultDownloadDialogOpenChanged ComProc RemoveIsDefaultDownloadDialogOpenChanged ComProc GetIsDefaultDownloadDialogOpen ComProc @@ -30,10 +30,30 @@ func (i *ICoreWebView2_9) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_9) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} + func (i *ICoreWebView2) GetICoreWebView2_9() *ICoreWebView2_9 { var result *ICoreWebView2_9 iidICoreWebView2_9 := NewGUID("{4d7b2eab-9fdc-468d-b998-a9260b5ed651}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_9)), @@ -61,7 +81,7 @@ func (i *ICoreWebView2_9) RemoveIsDefaultDownloadDialogOpenChanged(token EventRe hr, _, _ := i.Vtbl.RemoveIsDefaultDownloadDialogOpenChanged.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&token)), + uintptr(*(*uint64)(unsafe.Pointer(&token))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) @@ -151,7 +171,7 @@ func (i *ICoreWebView2_9) PutDefaultDownloadDialogMargin(value POINT) error { hr, _, _ := i.Vtbl.PutDefaultDownloadDialogMargin.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&value)), + uintptr(*(*uint64)(unsafe.Pointer(&value))), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) diff --git a/pkg/webview2/com.go b/pkg/webview2/com.go index 125ba21..c3083e3 100644 --- a/pkg/webview2/com.go +++ b/pkg/webview2/com.go @@ -32,6 +32,12 @@ type IUnknownVtbl struct { Release ComProc } +// CallRelease returns the new reference count, which is what IUnknown::Release returns. +// +// This used to return error, built from the Errno that LazyProc.Call yields -- which is +// non-nil on success, so `err != windows.ERROR_SUCCESS` was true for every successful +// Release and the refcount was thrown away. pkg/edge/com.go and the committed +// pkg/webview2/com.go both already carry this corrected form; only the template did not. func (i *IUnknownVtbl) CallRelease(this unsafe.Pointer) uint32 { ret, _, _ := i.Release.Call( uintptr(this), @@ -360,3 +366,16 @@ func (i *IStream) Read(p []byte) (int, error) { return 0, syscall.Errno(res) } } + +// boolToUintptr converts a Go bool to a Win32 BOOL passed by value. +// +// A COM in-parameter declared BOOL is a 4-byte integer passed BY VALUE. Handing over the +// address of a Go bool instead makes the callee read a pointer as an integer -- wrong, and +// wrong differently on each call. uintptr(b) is not a legal Go conversion, so the branch in +// Param.processVtableCallInput emits a call to this instead. +func boolToUintptr(b bool) uintptr { + if b { + return 1 + } + return 0 +} diff --git a/pkg/webview2/marshal_windows_test.go b/pkg/webview2/marshal_windows_test.go new file mode 100644 index 0000000..a354580 --- /dev/null +++ b/pkg/webview2/marshal_windows_test.go @@ -0,0 +1,324 @@ +//go:build windows + +package webview2 + +// Every correctness claim about this package's argument marshalling has, until now, been an argument +// about the Windows x64 calling convention rather than an observation. That is how eight families of +// marshalling bug survived here: the wrong code compiles, links, runs and returns S_OK, so reading it +// is the only check there was, and reading it is what failed. +// +// These tests execute it instead. The trick is that a COM object is nothing but a pointer to a table +// of function pointers, so one can be built entirely out of Go: fill a generated Vtbl struct with +// NewComProc(someGoFunc) and hand its address to the generated wrapper. The wrapper marshals exactly +// as it would for a real WebView2, the fake callee receives whatever actually arrived, and the test +// asserts on it. +// +// The consequence worth noticing: this needs no WebView2 Runtime, no display, no Edge install, no +// network. It needs Windows and nothing else, so it runs on a stock windows-latest CI runner -- which +// is the difference between "we reasoned carefully" and "we know". +// +// Each test below names the family it pins and what the pre-fix code did instead. + +import ( + "math" + "testing" + "unsafe" +) + +const sOK = 0 + +// nativePhysicalKeyStatus is COREWEBVIEW2_PHYSICAL_KEY_STATUS as the C header declares it: a BOOL is +// a 4-byte int, so this is 24 bytes. The generated Go struct must match it exactly, because the callee +// writes this layout through the pointer the caller supplies. +type nativePhysicalKeyStatus struct { + RepeatCount, ScanCode uint32 + IsExtendedKey, IsMenuKeyDown, WasKeyDown, IsKeyReleased int32 +} + +// --- by-value BOOL ----------------------------------------------------------------------------- + +// A COM BOOL in-parameter is a 4-byte integer passed by value. The generator used to hand over the +// ADDRESS of a Go bool, so the callee read a pointer as an integer: nonzero, therefore always true, +// and a different value on every call. +func TestBoolInParamArrivesByValue(t *testing.T) { + for _, want := range []bool{true, false} { + var got uintptr = 0xDEAD + vtbl := ICoreWebView2SettingsVtbl{} + vtbl.PutIsScriptEnabled = NewComProc(func(this *ICoreWebView2Settings, v uintptr) uintptr { + got = v + return sOK + }) + obj := &ICoreWebView2Settings{Vtbl: &vtbl} + + if err := obj.PutIsScriptEnabled(want); err != nil { + t.Fatal(err) + } + wantN := uintptr(0) + if want { + wantN = 1 + } + if got != wantN { + t.Errorf("PutIsScriptEnabled(%v): callee saw %#x, want %#x "+ + "(a large value means it received an address)", want, got, wantN) + } + } +} + +// --- by-value 8-byte aggregate ---------------------------------------------------------------- + +// EventRegistrationToken is struct{ int64 }, so it goes in a register as that int64. Every one of the +// 61 remove_* methods used to pass its address, which is why no event handler could be removed -- and +// remove_ still returned S_OK, so nothing looked wrong. +func TestEventRegistrationTokenArrivesByValue(t *testing.T) { + var got uintptr + vtbl := ICoreWebView2Vtbl{} + vtbl.RemoveNavigationCompleted = NewComProc(func(this *ICoreWebView2, v uintptr) uintptr { + got = v + return sOK + }) + obj := &ICoreWebView2{Vtbl: &vtbl} + + token := EventRegistrationToken{value: 0x0123456789ABCDEF} + if err := obj.RemoveNavigationCompleted(token); err != nil { + t.Fatal(err) + } + if got != uintptr(0x0123456789ABCDEF) { + t.Errorf("RemoveNavigationCompleted: callee saw %#x, want %#x", got, uintptr(0x0123456789ABCDEF)) + } +} + +// POINT is two int32s -- 8 bytes, so also register-passed, with X in the low half. RECT (16 bytes) is +// the opposite case and is passed by address; the two are the reason a single rule cannot cover +// aggregates. +func TestPointArrivesByValueWithFieldOrderIntact(t *testing.T) { + var got uintptr + vtbl := ICoreWebView2PointerInfoVtbl{} + vtbl.PutPixelLocation = NewComProc(func(this *ICoreWebView2PointerInfo, v uintptr) uintptr { + got = v + return sOK + }) + obj := &ICoreWebView2PointerInfo{Vtbl: &vtbl} + + if err := obj.PutPixelLocation(POINT{X: 0x11112222, Y: 0x33334444}); err != nil { + t.Fatal(err) + } + if lo, hi := uint32(got), uint32(got>>32); lo != 0x11112222 || hi != 0x33334444 { + t.Errorf("PutPixelLocation: callee saw X=%#x Y=%#x, want X=0x11112222 Y=0x33334444", lo, hi) + } +} + +// --- by-value double --------------------------------------------------------------------------- + +// A double is passed in XMM0-XMM3 for the first four arguments, and Go's syscall assembly copies each +// of those argument slots into both the integer register and the matching XMM register -- which is +// what makes math.Float64bits work here. The callback observes the integer register, so it sees the +// same bits the callee's XMM register receives. +// +// Twelve methods take a double, and each used to pass the ADDRESS of a Go float64, so the callee read +// a heap address as an IEEE-754 double: a denormal, or roughly 1e-300. +func TestDoubleInParamArrivesAsItsBits(t *testing.T) { + var got uintptr + vtbl := ICoreWebView2ControllerVtbl{} + vtbl.PutZoomFactor = NewComProc(func(this *ICoreWebView2Controller, v uintptr) uintptr { + got = v + return sOK + }) + obj := &ICoreWebView2Controller{Vtbl: &vtbl} + + const zoom = 1.75 + if err := obj.PutZoomFactor(zoom); err != nil { + t.Fatal(err) + } + if got != uintptr(math.Float64bits(zoom)) { + t.Errorf("PutZoomFactor(%v): callee saw %#x, want %#x (%v as observed by the callee)", + zoom, got, math.Float64bits(zoom), math.Float64frombits(uint64(got))) + } +} + +// --- 32-bit out-parameter ---------------------------------------------------------------------- + +// The callee writes four bytes through the pointer we supply. When the local was Go's 64-bit int, the +// high half stayed zero and the sign never extended, so a negative NTSTATUS came back as a large +// positive: GetExitCode returned 3221225477 for STATUS_ACCESS_VIOLATION. +func TestInt32OutParamKeepsItsSign(t *testing.T) { + const wantExit = int32(-1073741819) // 0xC0000005, STATUS_ACCESS_VIOLATION + + vtbl := ICoreWebView2ProcessFailedEventArgs2Vtbl{} + // The callback declares its out-parameter as *int32 rather than uintptr. A callback may take + // pointer arguments directly, so nothing has to be converted back from an integer -- which keeps + // this test out of the unsafe.Pointer rules it is meant to be checking. + vtbl.GetExitCode = NewComProc(func(this *ICoreWebView2ProcessFailedEventArgs2, out *int32) uintptr { + *out = wantExit + return sOK + }) + obj := &ICoreWebView2ProcessFailedEventArgs2{Vtbl: &vtbl} + + got, err := obj.GetExitCode() + if err != nil { + t.Fatal(err) + } + if got != wantExit { + t.Errorf("GetExitCode: got %d, want %d", got, wantExit) + } +} + +// --- string out-parameter ---------------------------------------------------------------------- + +// An out-parameter string is declared LPWSTR*: the callee writes a string POINTER into storage we +// own, so it needs the address of our local *uint16. Passing the local's nil VALUE instead gave the +// callee a null to write through, so all 109 string getters returned "" -- with S_OK. +// +// The assertion that matters is therefore that the callee is given somewhere to write. This writes nil +// rather than a real string on purpose: a real one would have to come from CoTaskMemAlloc, because the +// generated cleanup frees it with CoTaskMemFree and handing that a Go pointer corrupts the COM heap -- +// and reading a syscall's returned address back into an unsafe.Pointer is the one pattern `go vet` +// cannot verify, which would make this file fail the vet step it is meant to pass. CoTaskMemFree(nil) +// and UTF16PtrToString(nil) are both defined no-ops, so the path runs end to end with no allocation. +// The conversion itself is library code rather than generated code, and the in-parameter test below +// covers a real round-trip in the other direction. +func TestStringOutParamIsGivenSomewhereToWrite(t *testing.T) { + received := false + + vtbl := ICoreWebView2Vtbl{} + vtbl.GetSource = NewComProc(func(this *ICoreWebView2, out **uint16) uintptr { + received = out != nil + *out = nil + return sOK + }) + obj := &ICoreWebView2{Vtbl: &vtbl} + + got, err := obj.GetSource() + if err != nil { + t.Fatal(err) + } + if !received { + t.Error("GetSource: callee received a NULL out-parameter, so it had nowhere to write -- " + + "the local's value was passed instead of its address") + } + if got != "" { + t.Errorf("GetSource: got %q from a nil write, want the empty string", got) + } +} + +// A string IN-parameter is already the *uint16 that UTF16PtrFromString produced and is passed as-is. +func TestStringInParamArrivesAsAUTF16Pointer(t *testing.T) { + const want = "https://example.invalid/" + + var got string + vtbl := ICoreWebView2Vtbl{} + vtbl.Navigate = NewComProc(func(this *ICoreWebView2, uri *uint16) uintptr { + got = UTF16PtrToString(uri) + return sOK + }) + obj := &ICoreWebView2{Vtbl: &vtbl} + + if err := obj.Navigate(want); err != nil { + t.Fatal(err) + } + if got != want { + t.Errorf("Navigate: callee saw %q, want %q", got, want) + } +} + +// --- aggregate out-parameter, and the width of a struct field --------------------------------- + +// COREWEBVIEW2_PHYSICAL_KEY_STATUS is 24 bytes: two UINT32 and four BOOL, where a BOOL is a 4-byte +// int. Generating those flags as Go's 1-byte bool made the struct 12 bytes, so the callee's 24-byte +// write ran 12 bytes past the end of the local, and the last three flags were read from padding and +// so were permanently false. +// +// The write below is deliberately a full 24 bytes at the offsets a real callee uses, so this test +// fails -- by corrupting memory or by returning false flags -- if the field widths regress. +func TestAggregateOutParamMatchesTheNativeLayout(t *testing.T) { + if got, want := unsafe.Sizeof(COREWEBVIEW2_PHYSICAL_KEY_STATUS{}), uintptr(24); got != want { + t.Fatalf("COREWEBVIEW2_PHYSICAL_KEY_STATUS is %d bytes, want %d: a BOOL field is 4 bytes, "+ + "and the callee writes the native layout regardless of what Go declares", got, want) + } + + vtbl := ICoreWebView2AcceleratorKeyPressedEventArgsVtbl{} + vtbl.GetPhysicalKeyStatus = NewComProc(func(this *ICoreWebView2AcceleratorKeyPressedEventArgs, native *nativePhysicalKeyStatus) uintptr { + native.RepeatCount = 7 + native.ScanCode = 0x1E + native.IsExtendedKey = 1 + native.IsMenuKeyDown = 0 + native.WasKeyDown = 1 + native.IsKeyReleased = 1 + return sOK + }) + obj := &ICoreWebView2AcceleratorKeyPressedEventArgs{Vtbl: &vtbl} + + got, err := obj.GetPhysicalKeyStatus() + if err != nil { + t.Fatal(err) + } + switch { + case got.RepeatCount != 7 || got.ScanCode != 0x1E: + t.Errorf("GetPhysicalKeyStatus: RepeatCount=%d ScanCode=%#x, want 7 and 0x1e", + got.RepeatCount, got.ScanCode) + case got.IsExtendedKey == 0 || got.WasKeyDown == 0 || got.IsKeyReleased == 0: + t.Errorf("GetPhysicalKeyStatus: flags read from the wrong offsets: %+v", got) + case got.IsMenuKeyDown != 0: + t.Errorf("GetPhysicalKeyStatus: IsMenuKeyDown should be 0, got %d", got.IsMenuKeyDown) + } +} + +// --- uintptr typedef --------------------------------------------------------------------------- + +// HWND is `type HWND uintptr` -- an integer, so the value IS the argument. Passing its address gave +// WebView2 a garbage window handle. +func TestHandleTypedefArrivesByValue(t *testing.T) { + const want = uintptr(0x00CAFE00) + + var got uintptr + vtbl := ICoreWebView2EnvironmentVtbl{} + vtbl.CreateCoreWebView2Controller = NewComProc( + func(this *ICoreWebView2Environment, hwnd uintptr, handler uintptr) uintptr { + got = hwnd + return sOK + }) + obj := &ICoreWebView2Environment{Vtbl: &vtbl} + + if err := obj.CreateCoreWebView2Controller(HWND(want), nil); err != nil { + t.Fatal(err) + } + if got != want { + t.Errorf("CreateCoreWebView2Controller: callee saw hwnd=%#x, want %#x", got, want) + } +} + +// --- the HRESULT contract ---------------------------------------------------------------------- + +// ComProc.Call's third result is a syscall.Errno that is non-nil on success, so returning it made +// every successful call look like a failure. The HRESULT is the status, and a failing one must come +// back as the error while the out-parameters stay at their zero values. +func TestHResultDecidesTheError(t *testing.T) { + const eFail = 0x80004005 // E_FAIL + + vtbl := ICoreWebView2ProcessFailedEventArgs2Vtbl{} + vtbl.GetExitCode = NewComProc(func(this *ICoreWebView2ProcessFailedEventArgs2, out *int32) uintptr { + *out = 42 // written, but the call fails + return eFail + }) + obj := &ICoreWebView2ProcessFailedEventArgs2{Vtbl: &vtbl} + + got, err := obj.GetExitCode() + if err == nil { + t.Fatal("GetExitCode returned nil error for E_FAIL") + } + if got != 0 { + t.Errorf("GetExitCode returned %d alongside an error; want the zero value", got) + } + + // And the success path must produce a nil error, not Errno(0) boxed into a non-nil interface. + vtbl.GetExitCode = NewComProc(func(this *ICoreWebView2ProcessFailedEventArgs2, out *int32) uintptr { + *out = 42 + return sOK + }) + got, err = obj.GetExitCode() + if err != nil { + t.Fatalf("GetExitCode returned a non-nil error on S_OK: %v", err) + } + if got != 42 { + t.Errorf("GetExitCode: got %d, want 42", got) + } +} diff --git a/scripts/generator/enum_test.go b/scripts/generator/enum_test.go index ce9aa84..4e21516 100644 --- a/scripts/generator/enum_test.go +++ b/scripts/generator/enum_test.go @@ -4,8 +4,11 @@ import ( "bytes" "embed" _ "embed" + "flag" "github.com/matryer/is" "github.com/stretchr/testify/require" + "os" + "path/filepath" "strings" "testing" "updater/generator/types" @@ -22,6 +25,36 @@ func testfile(path string) *bytes.Buffer { return bytes.NewBuffer(f) } +// update rewrites the goldens in testfiles/ from the generator's current output: +// +// go test ./generator -update # then review the diff, then run without -update +// +// The goldens are the only executable record of what the templates are supposed to produce, so a +// template change is not finished until they are regenerated and the diff read. Every test used to +// carry this as a commented-out os.WriteFile loop, which made regenerating them an edit-run-revert +// cycle across seven files -- enough friction that fixing generated output by hand looks like the +// cheaper option. It is not: the next regeneration silently reverts it. +var update = flag.Bool("update", false, "rewrite testfiles/ goldens from generator output") + +// updateGoldens writes each generated file as its golden when -update is set, and reports whether +// it did. Callers return immediately if so: the goldens are embedded at compile time, so the +// assertions in the same run would still be comparing against the previous build's copies. +// Call it after the com.go strip, or com.go acquires a golden no test asserts on. +func updateGoldens(t *testing.T, files []*types.GeneratedFile) bool { + t.Helper() + if !*update { + return false + } + for _, f := range files { + name := filepath.Join("testfiles", f.FileName+".txt") + if err := os.WriteFile(name, f.Content.Bytes(), 0o644); err != nil { + t.Fatal(err) + } + t.Logf("updated %s", name) + } + return true +} + func makeOutput(input string) *bytes.Buffer { var buf bytes.Buffer // Normalise newlines @@ -94,6 +127,10 @@ func TestEnum(t *testing.T) { // Remove the `com.go` filename files = files[1:] + if updateGoldens(t, files) { + return + } + expected := []*types.GeneratedFile{ { FileName: "COREWEBVIEW2_PREFERRED_COLOR_SCHEME.go", diff --git a/scripts/generator/interface_bool_test.go b/scripts/generator/interface_bool_test.go index bd1407f..1144036 100644 --- a/scripts/generator/interface_bool_test.go +++ b/scripts/generator/interface_bool_test.go @@ -39,9 +39,9 @@ func TestInterfaceBool(t *testing.T) { // Remove the `com.go` filename files = files[1:] - //for _, file := range files { - // os.WriteFile("testfiles/"+file.FileName+".txt", file.Content.Bytes(), 0644) - //} + if updateGoldens(t, files) { + return + } expected := []*types.GeneratedFile{ { diff --git a/scripts/generator/interface_enum_test.go b/scripts/generator/interface_enum_test.go index 6aef8d1..383d48a 100644 --- a/scripts/generator/interface_enum_test.go +++ b/scripts/generator/interface_enum_test.go @@ -47,9 +47,9 @@ func TestInterfaceEnum(t *testing.T) { // Remove the `com.go` filename files = files[1:] - //for _, file := range files { - // os.WriteFile("testfiles/"+file.FileName+".txt", file.Content.Bytes(), 0644) - //} + if updateGoldens(t, files) { + return + } expected := []*types.GeneratedFile{ { diff --git a/scripts/generator/interface_int_test.go b/scripts/generator/interface_int_test.go index a9aa288..ab7b634 100644 --- a/scripts/generator/interface_int_test.go +++ b/scripts/generator/interface_int_test.go @@ -39,6 +39,10 @@ library WebView2 { // Remove the `com.go` filename files = files[1:] + if updateGoldens(t, files) { + return + } + expected := []*types.GeneratedFile{ { FileName: "ICoreWebView2ProcessFailedEventArgs2.go", diff --git a/scripts/generator/interface_pointers_test.go b/scripts/generator/interface_pointers_test.go index 013ff58..e2268e3 100644 --- a/scripts/generator/interface_pointers_test.go +++ b/scripts/generator/interface_pointers_test.go @@ -44,6 +44,10 @@ library WebView2 { // Remove the `com.go` filename files = files[1:] + if updateGoldens(t, files) { + return + } + expected := []*types.GeneratedFile{ { FileName: "ICoreWebView2.go", diff --git a/scripts/generator/interface_string_pointer_test.go b/scripts/generator/interface_string_pointer_test.go index f5d9d3b..d4b2ca4 100644 --- a/scripts/generator/interface_string_pointer_test.go +++ b/scripts/generator/interface_string_pointer_test.go @@ -41,9 +41,9 @@ library WebView2 { // Remove the `com.go` filename files = files[1:] - //for _, file := range files { - // os.WriteFile("testfiles/"+file.FileName+".txt", file.Content.Bytes(), 0644) - //} + if updateGoldens(t, files) { + return + } expected := []*types.GeneratedFile{ { diff --git a/scripts/generator/interface_string_test.go b/scripts/generator/interface_string_test.go index d10d178..b9e3a99 100644 --- a/scripts/generator/interface_string_test.go +++ b/scripts/generator/interface_string_test.go @@ -40,9 +40,9 @@ library WebView2 { // Remove the `com.go` filename files = files[1:] - //for _, file := range files { - // os.WriteFile("testfiles/"+file.FileName+".txt", file.Content.Bytes(), 0644) - //} + if updateGoldens(t, files) { + return + } expected := []*types.GeneratedFile{ { diff --git a/scripts/generator/invariants_test.go b/scripts/generator/invariants_test.go new file mode 100644 index 0000000..c287528 --- /dev/null +++ b/scripts/generator/invariants_test.go @@ -0,0 +1,428 @@ +package generator + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +// These are properties of the WHOLE generated binding, checked against the pinned IDL, rather than +// goldens for one interface. Each corresponds to a defect family that shipped for months, and the +// reason none was caught by review is the same in every case: the wrong output is valid Go that +// compiles, links and returns S_OK. A golden file records what one interface looked like on the day +// it was written; only a property says what must be true of all 300 of them. +// +// They also fail loudly if a template change is right for the interface a golden covers and wrong +// elsewhere -- which is the shape of every hand-patched fix in this package's history. + +// pinnedIDL reads the version from latest_version.txt rather than repeating it, because every +// older IDL is still in the tree: a hand-copied constant would keep passing against 2903.40 long +// after update_version_mapping.go moved the pin, and the tests would be asserting about output +// nobody ships. +func pinnedIDL(t *testing.T) string { + t.Helper() + version, err := os.ReadFile(filepath.Join("..", "latest_version.txt")) + require.NoError(t, err) + return "WebView2." + strings.TrimSpace(string(version)) + ".idl" +} + +func generateFromPinnedIDL(t *testing.T) map[string]string { + t.Helper() + data, err := os.ReadFile(filepath.Join("..", pinnedIDL(t))) + require.NoError(t, err) + files, err := ParseIDL(data) + require.NoError(t, err) + require.NotEmpty(t, files) + out := make(map[string]string, len(files)) + for _, f := range files { + out[f.FileName] = f.Content.String() + } + return out +} + +// interfaceBases returns each interface's declared base, straight from the IDL. The IDL is the only +// authority on this: the version-suffixed names invite inferring the chain from the numbering, and +// ICoreWebView2EnvironmentOptions2 through 8 are exactly where that inference is wrong -- each of +// those derives from IUnknown, not from its predecessor. +func interfaceBases(t *testing.T) map[string]string { + t.Helper() + data, err := os.ReadFile(filepath.Join("..", pinnedIDL(t))) + require.NoError(t, err) + idl, err := Parser.ParseBytes("", data) + require.NoError(t, err) + require.NoError(t, idl.Process()) + + bases := map[string]string{} + for _, lib := range idl.Libraries { + for _, d := range lib.Declarations { + if d.Interface != nil { + bases[d.Interface.Name] = d.Interface.BaseClass + } + } + } + require.NotEmpty(t, bases) + return bases +} + +// TestVtableEmbedsDeclaredBase is the regression test for the worst defect in this package's +// history, and it is a property rather than a slot-offset assertion on purpose. +// +// A COM vtable is flat: a derived interface's vtable begins with its ENTIRE base chain, then its own +// methods. Every derived vtable was generated as IUnknownVtbl plus its own methods, so each method +// sat too early by however many methods the chain above it declares, and a call landed on whichever +// unrelated function occupies that offset. ICoreWebView2_14's AddServerCertificateErrorDetected +// dispatched at slot 4 -- ICoreWebView2::get_Settings, which has one out-parameter and therefore +// wrote the Settings pointer over the caller's event-handler struct -- instead of slot 107. It +// returned S_OK, so registration "succeeded" and the event never fired. 88 interfaces were affected. +// +// Asserting embedding rather than computed offsets is deliberate: embedding the immediate base is +// sufficient by induction, and a test that recomputes the offsets would be asserting its own +// arithmetic against itself. +func TestVtableEmbedsDeclaredBase(t *testing.T) { + files := generateFromPinnedIDL(t) + bases := interfaceBases(t) + + checked := 0 + for name, base := range bases { + content, ok := files[name+".go"] + require.True(t, ok, "%s is declared but generated no file", name) + want := base + "Vtbl" + if base == "IUnknown" { + want = "IUnknownVtbl" + } + // The embedded field is the first line of the vtable struct. + decl := name + "Vtbl struct {\n\t" + idx := strings.Index(content, decl) + require.NotEqual(t, -1, idx, "%s has no vtable struct", name) + rest := content[idx+len(decl):] + got := rest[:strings.IndexByte(rest, '\n')] + require.Equal(t, want, got, + "%sVtbl must embed %s: the IDL declares %s : %s, and a vtable that omits an "+ + "intermediate interface's slots shifts every later method to the wrong offset", + name, want, name, base) + checked++ + } + // Exact, not a floor. A floor with two units of headroom would let one interface silently stop + // generating a file: the inner assertions are skipped for it and the count still clears the bar. + require.Equal(t, len(bases), checked, "every declared interface must have been checked") + require.NotZero(t, checked, "no interfaces were checked at all") +} + +// TestQueryInterfaceAccessorReceiver checks the other half of the same mistake, with the rule that +// actually applies: QueryInterface asks an OBJECT for another of its interfaces, so the accessor +// belongs on an interface of the object that can answer -- which the declared chain's ROOT names, +// not the immediate base. +// +// Every accessor was emitted on ICoreWebView2. For the ICoreWebView2_N chain that is correct, since +// it is all one object. For every other chain it is useless: GetICoreWebView2Controller2 hung off +// ICoreWebView2, a different object, so it could only fail, while ICoreWebView2Controller had no +// accessor at all. 56 accessors were misrooted; the 26 on ICoreWebView2 stay put, so no existing +// caller breaks. +// +// Interfaces whose base is IUnknown keep the ICoreWebView2 receiver they ship with -- there is no +// sibling interface to reach them from, and re-rooting them onto IUnknown would move ~170 methods +// onto it and delete accessors that already ship. That is an API break, not a bug fix. +func TestQueryInterfaceAccessorReceiver(t *testing.T) { + files := generateFromPinnedIDL(t) + bases := interfaceBases(t) + + // root walks the declared chain to the ancestor whose own base is IUnknown. The seen-set is not + // pedantry: production code grew the same guard, and without it a cyclic IDL would hang this + // test instead of failing it. + root := func(name string) string { + out := "" + seen := map[string]bool{name: true} + for { + base, ok := bases[name] + if !ok || base == "IUnknown" { + return out + } + require.False(t, seen[base], "inheritance cycle at %s", base) + seen[base] = true + out, name = base, base + } + } + + // An accessor is generated exactly when the IDL base is not IUnknown -- interfacevtbl.tmpl + // guards on BaseClass, which generateVtbl blanks for IUnknown. Deriving the expected count from + // that rule, rather than from a magic floor, is what makes a silently-missing accessor fail. + wantAccessors := 0 + for _, base := range bases { + if base != "IUnknown" { + wantAccessors++ + } + } + + checked, rerooted := 0, 0 + for name, base := range bases { + content, ok := files[name+".go"] + require.True(t, ok, "%s is declared but generated no file", name) + if base == "IUnknown" { + require.NotContains(t, content, fmt.Sprintf(") Get%s() *%s {", name, name), + "%s derives from IUnknown, so no accessor should be generated for it", name) + continue + } + receiver := root(name) + if receiver == "" { + receiver = "ICoreWebView2" // base is IUnknown; see above + } + require.Contains(t, content, + fmt.Sprintf("func (i *%s) Get%s() *%s {", receiver, name, name), + "Get%s must be a method on %s, the object a caller can QueryInterface from", name, receiver) + if receiver != "ICoreWebView2" { + rerooted++ + } + checked++ + } + require.Equal(t, wantAccessors, checked, + "every interface with a non-IUnknown base must have an accessor") + require.NotZero(t, rerooted, + "expected the Controller/Environment/Profile/Settings/Frame chains to root on their own object") +} + +var invokeSignature = regexp.MustCompile(`(?m)^func \w+Invoke\(this \*\w+(?:, ([^)]*))?\) uintptr \{`) + +// TestCallbackParamsFitInAUintptr is the regression test for the family PR #36 patched in the +// output. A callback reached through syscall.NewCallback may not declare a parameter wider than a +// uintptr, and NewCallback checks this at CALLBACK CONSTRUCTION time -- which happens in a +// package-level var initialiser, so a violation panics during package init for any program that +// merely imports pkg/webview2, used or not: +// +// panic: compileCallback: argument size is larger than uintptr +// +// A Go string is a 16-byte header, and three CompletedHandlers declared their LPCWSTR result as one. +// That makes this property the difference between the package being importable and not, which is +// also why it is worth a test rather than trusting three goldens. +func TestCallbackParamsFitInAUintptr(t *testing.T) { + files := generateFromPinnedIDL(t) + + checked := 0 + for fileName, content := range files { + for _, m := range invokeSignature.FindAllStringSubmatch(content, -1) { + if m[1] == "" { + continue + } + for _, param := range strings.Split(m[1], ",") { + fields := strings.Fields(strings.TrimSpace(param)) + require.Len(t, fields, 2, "unexpected parameter %q in %s", param, fileName) + typ := fields[1] + require.NotEqual(t, "string", typ, + "%s: callback parameter %q is a Go string (16 bytes); LPCWSTR arrives as a "+ + "pointer, so it must be declared *uint16 or syscall.NewCallback rejects "+ + "the whole vtable at init", fileName, fields[0]) + // NewCallback rejects floats outright, with its own panic + // ("compileCallback: float arguments not supported"), so they fail at init exactly + // as an oversized argument does. + require.NotContains(t, []string{"float32", "float64"}, typ, + "%s: callback parameter %q is a float; syscall.NewCallback refuses to build "+ + "the callback at all", fileName, fields[0]) + // Anything wider than a register fails the same way, not just a string. These two + // are the aggregates maps.go classifies as too wide to pass in one -- keep the + // lists together if either changes. + for _, wide := range []string{"RECT", "COREWEBVIEW2_PHYSICAL_KEY_STATUS"} { + require.NotEqual(t, wide, typ, + "%s: callback parameter %q is a %s, which exceeds a register; "+ + "syscall.NewCallback rejects the whole vtable at init", + fileName, fields[0], wide) + } + require.False(t, strings.HasPrefix(typ, "[]") || strings.Contains(typ, "interface{"), + "%s: callback parameter %q has type %s, which is wider than a uintptr", + fileName, fields[0], typ) + } + checked++ + } + } + require.Greater(t, checked, 50, "expected the pinned IDL to yield many handler Invoke functions") +} + +// TestCallErrnoIsNeverReturnedAsError guards the fix that upstream applied to the generated output +// twice by hand and never to the template. ComProc.Call's third result is a syscall.Errno, which is +// non-nil on SUCCESS ("The operation completed successfully"), so binding it to err and returning it +// made every successful call look like a failure. HRESULT is the real status. +func TestCallErrnoIsNeverReturnedAsError(t *testing.T) { + files := generateFromPinnedIDL(t) + + for fileName, content := range files { + if fileName == "com.go" { + // com.tmpl's hand-written IStream.Read does bind err, and correctly: it compares + // against windows.ERROR_SUCCESS, which IS Errno(0), rather than against nil. + continue + } + require.NotContains(t, content, ", _, err := i.Vtbl.", + "%s binds ComProc.Call's Errno, which is non-nil on success", fileName) + } +} + +// TestByValueArgumentsAreNotPassedByAddress is table-driven over synthetic IDL rather than a +// property over the real one, because the wrong and right forms are distinguishable only if you know +// the parameter's type -- which the generated text alone does not tell you. +// +// The Windows x64 rule being pinned: an aggregate of exactly 1, 2, 4 or 8 bytes is passed IN A +// REGISTER as an integer of that width, anything else by address. So POINT (8 bytes) and RECT (16) +// take opposite forms, which is how a single &address default came to look plausible. +func TestByValueArgumentsAreNotPassedByAddress(t *testing.T) { + cases := []struct { + name string + param string + want string + }{ + {"BOOL in-param", "[in] BOOL value", "boolToUintptr(value),"}, + {"UINT32 in-param", "[in] UINT32 value", "uintptr(value),"}, + {"HWND is a uintptr typedef", "[in] HWND value", "uintptr(value),"}, + {"8-byte token goes in a register", "[in] EventRegistrationToken value", + "uintptr(*(*uint64)(unsafe.Pointer(&value))),"}, + {"8-byte POINT goes in a register", "[in] POINT value", + "uintptr(*(*uint64)(unsafe.Pointer(&value))),"}, + {"4-byte COLOR goes in a register", "[in] COREWEBVIEW2_COLOR value", + "uintptr(*(*uint32)(unsafe.Pointer(&value))),"}, + {"16-byte RECT is too wide, so by address", "[in] RECT value", + "uintptr(unsafe.Pointer(&value)),"}, + {"in-param pointer is already the address", "[in] ICoreWebView2Settings* value", + "uintptr(unsafe.Pointer(value)),"}, + {"out-param needs the address of our storage", "[out, retval] UINT32* value", + "uintptr(unsafe.Pointer(&value)),"}, + {"out-param string needs the address of our pointer", "[out, retval] LPWSTR* value", + "uintptr(unsafe.Pointer(&_value)),"}, + {"in-param string is already a *uint16", "[in] LPCWSTR value", + "uintptr(unsafe.Pointer(_value)),"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + idl := fmt.Sprintf(` +[uuid(26d34152-879f-4065-bea2-3daa2cfadfb8), version(1.0)] +library WebView2 { +[uuid(A0D6DF20-3B92-416D-AA0C-437A9C727857), object, pointer_default(unique)] +interface ICoreWebView2Probe : IUnknown { + HRESULT Probe(%s); +} +}`, c.param) + + files, err := ParseIDL([]byte(idl)) + require.NoError(t, err) + + var content string + for _, f := range files { + if f.FileName == "ICoreWebView2Probe.go" { + content = f.Content.String() + } + } + require.NotEmpty(t, content, "probe interface was not generated") + require.Contains(t, content, c.want, + "wrong marshalling for %q.\ngenerated:\n%s", c.param, content) + }) + } +} + +// TestCommittedOutputMatchesGenerator is the invariant this whole generator-first arrangement +// exists to establish, and until now it was the one thing left to a human running diff -r. +// +// The committed pkg/webview2 was NOT the output of the committed generator: fixes had been applied +// to the 306 output files and never to the templates, so each regeneration silently reverted them. +// Nothing detected that, because nothing compared the two. This does. +// +// It replaces a test that asserted the output was gofmt-clean. That one could not fail for the +// reason it claimed: its input had already been through gofmtAll, so it was checking that +// formatting formatted content is a no-op. Deliberately mangling a template still left it green. +// gofmtAll's own error return is the real guard against a template emitting invalid Go. +func TestCommittedOutputMatchesGenerator(t *testing.T) { + const committed = "../../pkg/webview2" + if _, err := os.Stat(committed); err != nil { + t.Skipf("%s is absent; the scripts module stays independently testable", committed) + } + + generated := generateFromPinnedIDL(t) + + entries, err := os.ReadDir(committed) + require.NoError(t, err) + onDisk := map[string]bool{} + for _, e := range entries { + if e.IsDir() || !strings.HasSuffix(e.Name(), ".go") || strings.HasSuffix(e.Name(), "_test.go") { + continue + } + onDisk[e.Name()] = true + } + + for name, want := range generated { + require.True(t, onDisk[name], + "the generator produces %s but it is not committed; run the regeneration", name) + got, err := os.ReadFile(filepath.Join(committed, name)) + require.NoError(t, err) + require.Equal(t, want, string(got), + "committed %s differs from generator output -- it has been hand-edited, or the "+ + "regeneration was not run after a template change. Never fix generated output "+ + "directly: the next regeneration reverts it.", name) + } + for name := range onDisk { + require.Contains(t, generated, name, + "%s is committed but the generator does not produce it", name) + } +} + +// TestVtableDeclaresEveryDeclaredMethod is the other half of the slot-offset argument, and the half +// that was previously only asserted in a commit message. +// +// Embedding the base vtable is sufficient for correct offsets ONLY IF each interface also contributes +// exactly its own methods, in the IDL's order. COM guarantees declaration order is vtable order, so +// the remaining risk is a method going missing: if the parser ever dropped one -- a form it does not +// recognise, a grammar change -- every slot after the gap would shift, and the failure would look +// exactly like the bug this series fixed while every embedding assertion still passed. +// +// So count them. One embedded base, and one ComProc per declared method, for all 252 interfaces. +func TestVtableDeclaresEveryDeclaredMethod(t *testing.T) { + files := generateFromPinnedIDL(t) + + data, err := os.ReadFile(filepath.Join("..", pinnedIDL(t))) + require.NoError(t, err) + idl, err := Parser.ParseBytes("", data) + require.NoError(t, err) + require.NoError(t, idl.Process()) + + checked := 0 + for _, lib := range idl.Libraries { + for _, d := range lib.Declarations { + if d.Interface == nil { + continue + } + name := d.Interface.Name + content, ok := files[name+".go"] + require.True(t, ok, "%s is declared but generated no file", name) + + body := vtableBody(t, content, name) + procs, embeds := 0, 0 + for _, line := range strings.Split(body, "\n") { + switch line = strings.TrimSpace(line); { + case line == "": + case strings.HasSuffix(line, "ComProc"): + procs++ + case strings.HasSuffix(line, "Vtbl"): + embeds++ + } + } + require.Equal(t, len(d.Interface.Methods), procs, + "%s declares %d methods in the IDL but its vtable has %d slots; every slot after "+ + "the gap dispatches to the wrong function", + name, len(d.Interface.Methods), procs) + require.Equal(t, 1, embeds, "%s must embed exactly one base vtable", name) + checked++ + } + } + require.NotZero(t, checked) +} + +// vtableBody returns the field block of Vtbl. +func vtableBody(t *testing.T, content, name string) string { + t.Helper() + open := name + "Vtbl struct {" + i := strings.Index(content, open) + require.NotEqual(t, -1, i, "%s has no vtable struct", name) + rest := content[i+len(open):] + j := strings.Index(rest, "\n}") + require.NotEqual(t, -1, j, "%s's vtable struct is unterminated", name) + return rest[:j] +} diff --git a/scripts/generator/testfiles/COREWEBVIEW2_KEY_EVENT_KIND.go.txt b/scripts/generator/testfiles/COREWEBVIEW2_KEY_EVENT_KIND.go.txt index 2bd8bdd..838426b 100644 --- a/scripts/generator/testfiles/COREWEBVIEW2_KEY_EVENT_KIND.go.txt +++ b/scripts/generator/testfiles/COREWEBVIEW2_KEY_EVENT_KIND.go.txt @@ -5,8 +5,8 @@ package webview2 type COREWEBVIEW2_KEY_EVENT_KIND uint32 const ( - COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN = 0 - COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP = 1 + COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN = 0 + COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP = 1 COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN = 2 - COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_UP = 3 + COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_UP = 3 ) diff --git a/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME.go.txt b/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME.go.txt index d9c7d2d..7f602a6 100644 --- a/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME.go.txt +++ b/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME.go.txt @@ -5,7 +5,7 @@ package webview2 type COREWEBVIEW2_PREFERRED_COLOR_SCHEME uint32 const ( - COREWEBVIEW2_PREFERRED_COLOR_SCHEME_AUTO = 0 + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_AUTO = 0 COREWEBVIEW2_PREFERRED_COLOR_SCHEME_LIGHT = 1 - COREWEBVIEW2_PREFERRED_COLOR_SCHEME_DARK = 2 + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_DARK = 2 ) diff --git a/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME1.go.txt b/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME1.go.txt index c1fddae..9e84be4 100644 --- a/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME1.go.txt +++ b/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME1.go.txt @@ -5,7 +5,7 @@ package webview2 type COREWEBVIEW2_PREFERRED_COLOR_SCHEME1 uint32 const ( - COREWEBVIEW2_PREFERRED_COLOR_SCHEME_AUTO1 = 1 + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_AUTO1 = 1 COREWEBVIEW2_PREFERRED_COLOR_SCHEME_LIGHT1 = 2 - COREWEBVIEW2_PREFERRED_COLOR_SCHEME_DARK1 = 3 + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_DARK1 = 3 ) diff --git a/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME2.go.txt b/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME2.go.txt index 18475a6..0a1d1e2 100644 --- a/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME2.go.txt +++ b/scripts/generator/testfiles/COREWEBVIEW2_PREFERRED_COLOR_SCHEME2.go.txt @@ -5,7 +5,7 @@ package webview2 type COREWEBVIEW2_PREFERRED_COLOR_SCHEME2 uint32 const ( - COREWEBVIEW2_PREFERRED_COLOR_SCHEME_AUTO2 = 1 << 1 + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_AUTO2 = 1 << 1 COREWEBVIEW2_PREFERRED_COLOR_SCHEME_LIGHT2 = 1 << 2 - COREWEBVIEW2_PREFERRED_COLOR_SCHEME_DARK2 = 1 << 3 + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_DARK2 = 1 << 3 ) diff --git a/scripts/generator/testfiles/ICoreWebView2.go.txt b/scripts/generator/testfiles/ICoreWebView2.go.txt index da352fb..c3a5d90 100644 --- a/scripts/generator/testfiles/ICoreWebView2.go.txt +++ b/scripts/generator/testfiles/ICoreWebView2.go.txt @@ -1,16 +1,17 @@ //go:build windows package webview2 + import ( - "unsafe" - "syscall" "golang.org/x/sys/windows" + "syscall" + "unsafe" ) type ICoreWebView2Vtbl struct { IUnknownVtbl AddNavigationStarting ComProc - GetSettings ComProc + GetSettings ComProc } type ICoreWebView2 struct { @@ -22,12 +23,24 @@ func (i *ICoreWebView2) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} func (i *ICoreWebView2) AddNavigationStarting(eventHandler *ICoreWebView2NavigationStartingEventHandler) (EventRegistrationToken, error) { var token EventRegistrationToken - hr, _, err := i.Vtbl.AddNavigationStarting.Call( + hr, _, _ := i.Vtbl.AddNavigationStarting.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(eventHandler)), uintptr(unsafe.Pointer(&token)), @@ -35,19 +48,19 @@ func (i *ICoreWebView2) AddNavigationStarting(eventHandler *ICoreWebView2Navigat if windows.Handle(hr) != windows.S_OK { return EventRegistrationToken{}, syscall.Errno(hr) } - return token, err + return token, nil } func (i *ICoreWebView2) GetSettings() (*ICoreWebView2Settings, error) { var settings *ICoreWebView2Settings - hr, _, err := i.Vtbl.GetSettings.Call( + hr, _, _ := i.Vtbl.GetSettings.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&settings)), ) if windows.Handle(hr) != windows.S_OK { return nil, syscall.Errno(hr) } - return settings, err + return settings, nil } diff --git a/scripts/generator/testfiles/ICoreWebView2AcceleratorKeyPressedEventArgs.go.txt b/scripts/generator/testfiles/ICoreWebView2AcceleratorKeyPressedEventArgs.go.txt index 9e05d6f..d791e41 100644 --- a/scripts/generator/testfiles/ICoreWebView2AcceleratorKeyPressedEventArgs.go.txt +++ b/scripts/generator/testfiles/ICoreWebView2AcceleratorKeyPressedEventArgs.go.txt @@ -1,10 +1,11 @@ //go:build windows package webview2 + import ( - "unsafe" - "syscall" "golang.org/x/sys/windows" + "syscall" + "unsafe" ) type ICoreWebView2AcceleratorKeyPressedEventArgsVtbl struct { @@ -21,17 +22,29 @@ func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventKind() (COREWEBVIEW2_KEY_EVENT_KIND, error) { var keyEventKind COREWEBVIEW2_KEY_EVENT_KIND - hr, _, err := i.Vtbl.GetKeyEventKind.Call( + hr, _, _ := i.Vtbl.GetKeyEventKind.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&keyEventKind)), ) if windows.Handle(hr) != windows.S_OK { return 0, syscall.Errno(hr) } - return keyEventKind, err + return keyEventKind, nil } diff --git a/scripts/generator/testfiles/ICoreWebView2CustomSchemeRegistration.go.txt b/scripts/generator/testfiles/ICoreWebView2CustomSchemeRegistration.go.txt index 5f84641..7bd96b0 100644 --- a/scripts/generator/testfiles/ICoreWebView2CustomSchemeRegistration.go.txt +++ b/scripts/generator/testfiles/ICoreWebView2CustomSchemeRegistration.go.txt @@ -1,10 +1,11 @@ //go:build windows package webview2 + import ( - "unsafe" - "syscall" "golang.org/x/sys/windows" + "syscall" + "unsafe" ) type ICoreWebView2CustomSchemeRegistrationVtbl struct { @@ -21,6 +22,18 @@ func (i *ICoreWebView2CustomSchemeRegistration) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2CustomSchemeRegistration) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} func (i *ICoreWebView2CustomSchemeRegistration) SetAllowedOrigins(allowedOriginsCount uint32, allowedOrigins string) error { @@ -30,13 +43,13 @@ func (i *ICoreWebView2CustomSchemeRegistration) SetAllowedOrigins(allowedOrigins return err } - hr, _, err := i.Vtbl.SetAllowedOrigins.Call( + hr, _, _ := i.Vtbl.SetAllowedOrigins.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(&allowedOriginsCount)), + uintptr(allowedOriginsCount), uintptr(unsafe.Pointer(_allowedOrigins)), ) if windows.Handle(hr) != windows.S_OK { return syscall.Errno(hr) } - return err + return nil } diff --git a/scripts/generator/testfiles/ICoreWebView2FrameInfo.go.txt b/scripts/generator/testfiles/ICoreWebView2FrameInfo.go.txt index 1d81a14..e86c923 100644 --- a/scripts/generator/testfiles/ICoreWebView2FrameInfo.go.txt +++ b/scripts/generator/testfiles/ICoreWebView2FrameInfo.go.txt @@ -1,15 +1,16 @@ //go:build windows package webview2 + import ( - "unsafe" - "syscall" "golang.org/x/sys/windows" + "syscall" + "unsafe" ) type ICoreWebView2FrameInfoVtbl struct { IUnknownVtbl - GetName ComProc + GetName ComProc GetSource ComProc } @@ -22,15 +23,26 @@ func (i *ICoreWebView2FrameInfo) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2FrameInfo) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} func (i *ICoreWebView2FrameInfo) GetName() (string, error) { // Create *uint16 to hold result var _name *uint16 - - hr, _, err := i.Vtbl.GetName.Call( + hr, _, _ := i.Vtbl.GetName.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_name)), + uintptr(unsafe.Pointer(&_name)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -38,17 +50,16 @@ func (i *ICoreWebView2FrameInfo) GetName() (string, error) { // Get result and cleanup name := UTF16PtrToString(_name) CoTaskMemFree(unsafe.Pointer(_name)) - return name, err + return name, nil } func (i *ICoreWebView2FrameInfo) GetSource() (string, error) { // Create *uint16 to hold result var _source *uint16 - - hr, _, err := i.Vtbl.GetSource.Call( + hr, _, _ := i.Vtbl.GetSource.Call( uintptr(unsafe.Pointer(i)), - uintptr(unsafe.Pointer(_source)), + uintptr(unsafe.Pointer(&_source)), ) if windows.Handle(hr) != windows.S_OK { return "", syscall.Errno(hr) @@ -56,5 +67,5 @@ func (i *ICoreWebView2FrameInfo) GetSource() (string, error) { // Get result and cleanup source := UTF16PtrToString(_source) CoTaskMemFree(unsafe.Pointer(_source)) - return source, err + return source, nil } diff --git a/scripts/generator/testfiles/ICoreWebView2ProcessFailedEventArgs2.go.txt b/scripts/generator/testfiles/ICoreWebView2ProcessFailedEventArgs2.go.txt index c16dd90..9fd4dde 100644 --- a/scripts/generator/testfiles/ICoreWebView2ProcessFailedEventArgs2.go.txt +++ b/scripts/generator/testfiles/ICoreWebView2ProcessFailedEventArgs2.go.txt @@ -1,14 +1,15 @@ //go:build windows package webview2 + import ( - "unsafe" - "syscall" "golang.org/x/sys/windows" + "syscall" + "unsafe" ) type ICoreWebView2ProcessFailedEventArgs2Vtbl struct { - IUnknownVtbl + ICoreWebView2ProcessFailedEventArgsVtbl GetExitCode ComProc } @@ -21,11 +22,30 @@ func (i *ICoreWebView2ProcessFailedEventArgs2) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2ProcessFailedEventArgs2) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} -func (i *ICoreWebView2) GetICoreWebView2ProcessFailedEventArgs2() *ICoreWebView2ProcessFailedEventArgs2 { +func (i *ICoreWebView2ProcessFailedEventArgs) GetICoreWebView2ProcessFailedEventArgs2() *ICoreWebView2ProcessFailedEventArgs2 { var result *ICoreWebView2ProcessFailedEventArgs2 iidICoreWebView2ProcessFailedEventArgs2 := NewGUID("{4dab9422-46fa-4c3e-a5d2-41d2071d3680}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2ProcessFailedEventArgs2)), @@ -34,17 +54,16 @@ func (i *ICoreWebView2) GetICoreWebView2ProcessFailedEventArgs2() *ICoreWebView2 return result } +func (i *ICoreWebView2ProcessFailedEventArgs2) GetExitCode() (int32, error) { -func (i *ICoreWebView2ProcessFailedEventArgs2) GetExitCode() (int, error) { - - var exitCode int + var exitCode int32 - hr, _, err := i.Vtbl.GetExitCode.Call( + hr, _, _ := i.Vtbl.GetExitCode.Call( uintptr(unsafe.Pointer(i)), - uintptr(exitCode), + uintptr(unsafe.Pointer(&exitCode)), ) if windows.Handle(hr) != windows.S_OK { return 0, syscall.Errno(hr) } - return exitCode, err + return exitCode, nil } diff --git a/scripts/generator/testfiles/ICoreWebView2_3.go.txt b/scripts/generator/testfiles/ICoreWebView2_3.go.txt index e675790..3cec43a 100644 --- a/scripts/generator/testfiles/ICoreWebView2_3.go.txt +++ b/scripts/generator/testfiles/ICoreWebView2_3.go.txt @@ -1,14 +1,15 @@ //go:build windows package webview2 + import ( - "unsafe" - "syscall" "golang.org/x/sys/windows" + "syscall" + "unsafe" ) type ICoreWebView2_3Vtbl struct { - IUnknownVtbl + ICoreWebView2_2Vtbl GetIsSuspended ComProc } @@ -21,11 +22,30 @@ func (i *ICoreWebView2_3) AddRef() uintptr { return refCounter } +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *ICoreWebView2_3) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} -func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 { +func (i *ICoreWebView2_2) GetICoreWebView2_3() *ICoreWebView2_3 { var result *ICoreWebView2_3 iidICoreWebView2_3 := NewGUID("{A0D6DF20-3B92-416D-AA0C-437A9C727857}") + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iidICoreWebView2_3)), @@ -34,12 +54,11 @@ func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 { return result } - func (i *ICoreWebView2_3) GetIsSuspended() (bool, error) { // Create int32 to hold bool result var _isSuspended int32 - hr, _, err := i.Vtbl.GetIsSuspended.Call( + hr, _, _ := i.Vtbl.GetIsSuspended.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&_isSuspended)), ) @@ -47,6 +66,6 @@ func (i *ICoreWebView2_3) GetIsSuspended() (bool, error) { return false, syscall.Errno(hr) } // Get result and cleanup - isSuspended := _isSuspended != 0 - return isSuspended, err + isSuspended := _isSuspended != 0 + return isSuspended, nil } diff --git a/scripts/generator/types/enum.go b/scripts/generator/types/enum.go index 2797c98..21c970f 100644 --- a/scripts/generator/types/enum.go +++ b/scripts/generator/types/enum.go @@ -4,6 +4,7 @@ import ( "io" "log" "strconv" + "strings" "text/template" ) @@ -31,18 +32,53 @@ func (e *EnumValueDecl) Process() { } } +// asInt evaluates the initialiser forms the grammar accepts -- a decimal or hex literal, with an +// optional "<< N" -- so that the NEXT enumerator can continue counting from it. Reports false for +// anything it cannot evaluate, which is not an error: the caller has a correct fallback. +func (e *EnumValueDecl) asInt() (int64, bool) { + text := strings.TrimSpace(e.Value) + shift := uint64(0) + if base, sh, found := strings.Cut(text, "<<"); found { + n, err := strconv.ParseUint(strings.TrimSpace(sh), 0, 8) + if err != nil { + return 0, false + } + text, shift = strings.TrimSpace(base), n + } + // ParseInt with base 0 takes both "5" and "0x4". + n, err := strconv.ParseInt(text, 0, 64) + if err != nil { + return 0, false + } + return n << shift, true +} + func (d *EnumDeclaration) Process(decl *Declaration) error { d.decl = decl + // An enumerator with no initialiser is PREVIOUS + 1 in C, not its ordinal position. Using the + // index gave the right answer only for an enum that sets no values at all, or sets them to + // their own positions -- which every shipped WebView2 enum happens to do, which is why this + // never showed. "A = 5, B" produced B = 1 rather than 6: a wrong constant that compiles and + // goes straight to WebView2. + prev, prevKnown := int64(-1), true for index, value := range d.Values { - if value.Value == nil { - value.Value = &EnumValueDecl{ - Value: strconv.Itoa(index), - } - } else { + if value.Value != nil { value.Value.Process() + prev, prevKnown = value.Value.asInt() + continue + } + switch { + case prevKnown: + prev++ + value.Value = &EnumValueDecl{Value: strconv.FormatInt(prev, 10)} + default: + // The previous initialiser was an expression this cannot evaluate. Naming the previous + // enumerator is still exact, because Go constant declarations allow it. + value.Value = &EnumValueDecl{Value: d.Values[index-1].Key + " + 1"} } } - decl.library.enums.Add(d.Name) + // The name is registered in Library.Process's pre-pass, before any interface is processed -- + // see the comment there. Registering it again here would be too late to be useful. return nil } diff --git a/scripts/generator/types/idl.go b/scripts/generator/types/idl.go index e1609c2..8415851 100644 --- a/scripts/generator/types/idl.go +++ b/scripts/generator/types/idl.go @@ -3,7 +3,9 @@ package types import ( "bytes" "errors" + "fmt" "github.com/leaanthony/slicer" + "go/format" "log" "strings" "text/template" @@ -31,10 +33,37 @@ func (i *IDL) Process() error { } func (i *IDL) Generate() ([]*GeneratedFile, error) { + // Accumulate across libraries rather than returning inside the loop. Every WebView2 IDL + // declares exactly one, so the old early return was never wrong -- it just read as a loop while + // behaving like an index, which is the kind of thing that stops being harmless quietly. + var all []*GeneratedFile for _, library := range i.Libraries { - return library.Generate() + files, err := library.Generate() + if err != nil { + return nil, err + } + all = append(all, files...) + } + return gofmtAll(all) +} + +// gofmtAll formats every generated file, which the generator did not previously do although the +// committed tree is gofmt-clean -- so somebody was formatting the output by hand afterwards. That +// left ~180 files differing from a fresh generation by nothing but import order and blank lines, +// which is enough noise to hide a real change in a regeneration diff, and hiding real changes in +// regeneration diffs is how this package accumulated hand-patched output in the first place. +// +// The error path is a second, unlooked-for benefit: a template that emits invalid Go now fails the +// generator by name instead of writing a file that only fails later at `go build`. +func gofmtAll(files []*GeneratedFile) ([]*GeneratedFile, error) { + for _, f := range files { + formatted, err := format.Source(f.Content.Bytes()) + if err != nil { + return nil, fmt.Errorf("generated %s is not valid Go: %w", f.FileName, err) + } + f.Content = bytes.NewBuffer(formatted) } - return nil, nil + return files, nil } type Import struct { @@ -54,10 +83,29 @@ type Library struct { forewardInterfaceDeclarations slicer.StringSlicer enums slicer.StringSlicer packageName string + interfaces map[string]*InterfaceDeclaration } func (l *Library) Process() error { l.packageName = strings.ToLower(l.Name) + // Index the interfaces AND the enums before processing any of them: resolving an inheritance + // chain needs every declaration to be findable by name, and nothing guarantees a base -- or an + // enum -- is declared first. + // + // The enums were previously registered as each one was processed, while Param.IsEnum() is + // consulted while processing an INTERFACE. An enum declared after the interface that uses it + // therefore looked like an unknown type, which used to mean a silently wrong &address and now + // means the generator stops with advice that does not apply. Microsoft's IDLs happen to put + // every enum first, which is the only reason this never fired. + l.interfaces = map[string]*InterfaceDeclaration{} + for _, declaration := range l.Declarations { + if declaration.Interface != nil { + l.interfaces[declaration.Interface.Name] = declaration.Interface + } + if declaration.Enum != nil { + l.enums.Add(declaration.Enum.Name) + } + } for _, declaration := range l.Declarations { err := declaration.Process(l) if err != nil { diff --git a/scripts/generator/types/interface.go b/scripts/generator/types/interface.go index a0d19c3..88048d7 100644 --- a/scripts/generator/types/interface.go +++ b/scripts/generator/types/interface.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "fmt" "github.com/leaanthony/slicer" "io" "log" @@ -31,8 +32,11 @@ func (d *InterfaceDeclaration) Process(decl *Declaration) error { return err } if string(method.Name) == "Invoke" { + // No break: a method declared AFTER Invoke would never be processed, and would then be + // emitted with an empty parameter list and no call arguments. Every shipped handler has + // Invoke alone, so this only ever saved a few iterations -- and since the generator now + // gofmts its output, such a file fails generation rather than being written out broken. d.InvokeMethod = method - break } } d.includes.AddUnique(`"unsafe"`) @@ -64,6 +68,10 @@ func (d *InterfaceDeclaration) Generate(packageName string, w io.Writer) error { } func (d *InterfaceDeclaration) generateVtbl(packageName string, w io.Writer) error { + rootInterface, err := d.RootInterface() + if err != nil { + return err + } data := struct { PackageName string Name string @@ -71,10 +79,15 @@ func (d *InterfaceDeclaration) generateVtbl(packageName string, w io.Writer) err HasInvokeMethod bool Includes []string BaseClass string + RootInterface string Header *InterfaceHeader }{ - PackageName: packageName, - BaseClass: d.BaseClass, + PackageName: packageName, + BaseClass: d.BaseClass, + // The vtable embeds the IMMEDIATE base, because that is what the memory layout is; the + // QueryInterface accessor hangs off the chain ROOT, because that is which object can + // answer it. Two different questions, so two fields. + RootInterface: rootInterface, Header: d.Header, Name: d.Name, Methods: d.Methods, @@ -95,6 +108,55 @@ func (d *InterfaceDeclaration) GetBaseClass() string { return d.BaseClass } +// RootInterface walks the declared inheritance chain to its first member -- the ancestor whose own +// base is IUnknown -- and returns "" if this interface IS that ancestor. +// +// This, not the immediate base, is where a QueryInterface accessor belongs, and the distinction is +// the whole of what makes those accessors either useful or useless. QueryInterface asks an OBJECT +// for another of its interfaces, so any interface on the same object can answer for any other. A +// chain like ICoreWebView2 -> _2 -> ... -> _27 is all one object, so ICoreWebView2 can hand out +// ICoreWebView2_14 directly and a caller need not walk thirteen accessors to reach it. +// +// What the chain root identifies is WHICH object. ICoreWebView2Controller2's root is +// ICoreWebView2Controller, a different object from the webview -- so the accessor emitted on +// ICoreWebView2 asked the wrong object and could only ever fail, while the controller, which can +// answer, had no accessor at all. Rooting on the chain start fixes exactly those and leaves the +// ICoreWebView2_N family where it already is, which is both correct and not an API break. +// +// An interface whose base is IUnknown returns "" here and gets no accessor at all -- see +// interfacevtbl.tmpl, whose guard is BaseClass rather than RootInterface. +func (d *InterfaceDeclaration) RootInterface() (string, error) { + root := "" + seen := map[string]bool{d.Name: true} + for cur := d; cur != nil && cur.BaseClass != "IUnknown"; { + root = cur.BaseClass + next := cur.decl.library.interfaces[cur.BaseClass] + if next == nil { + // A base this library does not declare ends the chain, and is deliberately NOT an + // error. com.tmpl hand-writes IUnknown, IStream and IDataObject precisely so that + // interfaces can derive from types no IDL declares; the IDL also carries forward + // declarations; and this generator's own test fixtures are single-interface fragments + // whose base is absent by construction. Rejecting the case breaks all three. + // + // The cost is that a base which really is missing surfaces as `undefined: Vtbl` + // when the CONSUMING package is built, rather than here where the cause is known. + // Telling "hand-written elsewhere" from "absent" would need a registry of what com.tmpl + // defines, which is a worse coupling than the deferred error. + break + } + if seen[next.Name] { + // A cyclic "A : B, B : A" would otherwise spin forever. The generator runs on whatever + // IDL Microsoft publishes next, and a hang is a worse failure than a wrong answer + // because there is nothing to read. + return "", fmt.Errorf("inheritance cycle reached %s while resolving the chain root "+ + "of %s", next.Name, d.Name) + } + seen[next.Name] = true + cur = next + } + return root, nil +} + func (d *InterfaceDeclaration) generateInvoke(w io.Writer) error { if d.InvokeMethod == nil { return nil @@ -182,12 +244,10 @@ func (m *InterfaceMethod) Process(decl *InterfaceDeclaration) error { if m.Prop != nil { m.ProcessedName = string(*m.Prop) + m.ProcessedName } - m.processParams() - - return nil + return m.processParams() } -func (m *InterfaceMethod) processParams() { +func (m *InterfaceMethod) processParams() error { for _, param := range m.Params { param.Process(m) if param.IsOutputParam() { @@ -197,23 +257,28 @@ func (m *InterfaceMethod) processParams() { } } - m.processInputParams() - m.processOutputParams() + if err := m.processInputParams(); err != nil { + return err + } + return m.processOutputParams() } -func (m *InterfaceMethod) processInputParams() { +func (m *InterfaceMethod) processInputParams() error { var inputs slicer.StringSlicer var inputParamNames slicer.StringSlicer for _, param := range m.inputParams { inputs.Add(param.Name + " " + param.AsInputType()) inputParamNames.Add(param.Name) - param.processSetup() + if err := param.processSetup(); err != nil { + return err + } } m.GoInputs = inputs.Join(", ") m.InputParamNames = inputParamNames.Join(", ") + return nil } -func (m *InterfaceMethod) processOutputParams() { +func (m *InterfaceMethod) processOutputParams() error { var outputs slicer.StringSlicer var outputParamNames slicer.StringSlicer var outputParamTypes slicer.StringSlicer @@ -221,7 +286,9 @@ func (m *InterfaceMethod) processOutputParams() { outputs.Add(param.Name + " " + param.GoType) outputParamNames.Add(param.Name) outputParamTypes.Add(param.GoType) - param.processSetup() + if err := param.processSetup(); err != nil { + return err + } } // Add the mandatory error outputs.Add("err error") @@ -234,6 +301,18 @@ func (m *InterfaceMethod) processOutputParams() { if outputParamTypes.Length() > 1 { m.GoReturnTypes = "(" + m.GoReturnTypes + ")" } + return nil +} + +// CallbackInputs is GoInputs for a callback: the same parameters, declared in the shape the +// Windows callback ABI actually delivers them in. Only interfaceInvoke.tmpl uses it. See +// Param.AsCallbackType. +func (m *InterfaceMethod) CallbackInputs() string { + var inputs slicer.StringSlicer + for _, param := range m.inputParams { + inputs.Add(param.Name + " " + param.AsCallbackType()) + } + return inputs.Join(", ") } func (m *InterfaceMethod) SetupCode() string { @@ -264,6 +343,9 @@ func (m *InterfaceMethod) ReturnsHRESULT() bool { return m.ReturnType == "HRESULT" } +// ErrorValues is the early return taken when converting a string input fails. It keeps +// "err" -- unlike the paths below -- because there the error is UTF16PtrFromString's, which +// is a real Go error, and it is in scope (inputStringSetup.tmpl binds it). func (m *InterfaceMethod) ErrorValues() string { var errorValues slicer.StringSlicer for _, outputParam := range m.outputParams { @@ -280,7 +362,9 @@ func (m *InterfaceMethod) ErrorValuesHRESULT() string { if m.ReturnsHRESULT() { errorValues.Add("syscall.Errno(hr)") } else { - errorValues.Add("err") + // Not "err": the Call's Errno is not bound any more (see interfaceMethod.tmpl), and + // a method with no HRESULT has no status to report. + errorValues.Add("nil") } return errorValues.Join(", ") } @@ -292,12 +376,14 @@ func (m *InterfaceMethod) GetHResultVariable() string { return "_" } +// SuccessValues is reached only after the HRESULT check passed, so the error is nil by +// construction. It used to be "err" -- the Call's Errno -- which is non-nil on success. func (m *InterfaceMethod) SuccessValues() string { var successValues slicer.StringSlicer for _, outputParam := range m.outputParams { successValues.Add(outputParam.GetReturnVariableName()) } - successValues.Add("err") + successValues.Add("nil") return successValues.Join(", ") } diff --git a/scripts/generator/types/maps.go b/scripts/generator/types/maps.go index fdb3912..4a68cd5 100644 --- a/scripts/generator/types/maps.go +++ b/scripts/generator/types/maps.go @@ -8,8 +8,18 @@ var idlTypeToGoType = map[string]string{ "HRESULT": "uintptr", "UINT64": "uint64", "UINT32": "uint32", - "UINT": "uint", - "INT": "int", + // Sized, not Go's int/uint. These appear as out-parameters, where the generated method + // declares a local of the mapped type and hands the callee its address -- and a 64-bit local + // receiving a 32-bit write keeps its zeroed high half, so the sign never extends. GetExitCode + // returned 3221225477 for an exit code of -1073741819. Seven out-parameters were affected, of + // which GetKeyEventLParam (bit 31 set on every key-up) and GetExitCode (negative NTSTATUS) are + // wrong for ordinary inputs rather than only extreme ones. + // + // Lowercase "int" is the spelling the IDL actually uses for six of the seven and was absent + // from this map entirely, so it fell through to Go's int by passthrough. + "UINT": "uint32", + "INT": "int32", + "int": "int32", "INT32": "int32", "INT64": "int64", "BOOL": "bool", @@ -25,3 +35,60 @@ func IdlTypeToGoType(input string) string { } return result } + +// byValueArgument gives, per IDL type, the expression that passes a BY-VALUE in-parameter of that +// type to ComProc.Call. %s is the variable name. Only types that are neither a mapped scalar nor +// an enum reach here: the handle typedefs and the aggregates. +// +// The rule being encoded is the Windows x64 calling convention's, and it is not "aggregates go by +// reference". An aggregate of exactly 1, 2, 4 or 8 bytes is passed IN A REGISTER as an integer of +// that width; anything else is passed by reference. So POINT (8) and COREWEBVIEW2_COLOR (4) are +// register-passed while RECT (16) is not, and a single rule cannot cover both -- which is how +// every one of these ended up as &address, the answer that is only ever right for the large ones. +// +// Reinterpreting the struct through a same-width integer copies its layout rather than re-deriving +// the field order by hand, and it is a plain read, so unlike &address it also has no +// unsafe.Pointer lifetime question. +// +// The 8-byte entries assume a 64-bit uintptr. On windows/386 they would truncate, because an 8-byte +// by-value aggregate occupies two stack slots there and cannot be one Call argument at all -- the +// same shape of limit as the floats. That assumption is not new: PutPerformanceCount already passes +// a uint64 as one uintptr, so the generated binding has always been 64-bit-only in practice. +var byValueArgument = map[string]string{ + // Register-sized aggregates. + "EventRegistrationToken": "uintptr(*(*uint64)(unsafe.Pointer(&%s)))", // struct{ value int64 } + "POINT": "uintptr(*(*uint64)(unsafe.Pointer(&%s)))", // struct{ X, Y int32 } + "COREWEBVIEW2_COLOR": "uintptr(*(*uint32)(unsafe.Pointer(&%s)))", // struct{ A, R, G, B byte } +} + +// uintptrTypedef lists the IDL types the binding declares as `type X uintptr` in com.tmpl. They are +// integers, so both questions this file answers have one obvious answer: pass the value, and use 0 +// as the zero value. +// +// Only HWND currently appears as a by-value parameter and only HANDLE, HWND and HCURSOR as +// out-parameters; the rest are listed because for a uintptr typedef there is exactly one right +// answer, so pre-classifying them is not the guessing that byRefAggregate exists to prevent. +// +// VARIANT is deliberately ABSENT even though com.tmpl declares it `type VARIANT uintptr`. A real +// VARIANT is a 16-byte tagged union, com.tmpl says so itself ("NOTE: For sure, this is wrong!"), and +// the IDL only ever uses VARIANT* -- so a by-value VARIANT should hit the generator's error and make +// someone look, not quietly become an integer. +var uintptrTypedef = map[string]bool{ + "HANDLE": true, + "HBRUSH": true, + "HCURSOR": true, + "HICON": true, + "HINSTANCE": true, + "HMENU": true, + "HMODULE": true, + "HWND": true, +} + +// byRefAggregate are the by-value in-parameter types that really are passed by address, with the +// width that makes them so. They are listed rather than left to a default so that a type in +// NEITHER table is a generator error instead of a silent guess -- the failure mode this entire +// family is made of. Adding a struct to the IDL should cost one line here and a look at its size. +var byRefAggregate = map[string]int{ + "RECT": 16, // struct{ Left, Top, Right, Bottom int32 } + "COREWEBVIEW2_PHYSICAL_KEY_STATUS": 24, // 2x UINT32 + 4x BOOL +} diff --git a/scripts/generator/types/param.go b/scripts/generator/types/param.go index 8075c81..2a7532c 100644 --- a/scripts/generator/types/param.go +++ b/scripts/generator/types/param.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "io" "strings" ) @@ -71,10 +72,39 @@ func (p *Param) AsInputType() string { return p.GoType } -func (p *Param) processSetup() { +// AsCallbackType is the type an INBOUND parameter must be declared as, and is deliberately not +// AsInputType. An outbound call is free to take a Go string, because the generated method +// converts it with UTF16PtrFromString before it reaches the vtable. A callback has no such +// step: syscall.NewCallback hands the Go function the raw machine words WebView2 passed, so the +// declared type IS the ABI. LPCWSTR arrives as a pointer, hence *uint16. +// +// Declaring it "string" does not merely mis-marshal; it fails to load at all. Every handler +// vtable is built in a package-level var initialiser, so NewComProc -> syscall.NewCallback runs +// during package init, and NewCallback rejects any argument wider than a uintptr. A string +// header is 16 bytes on amd64, so importing pkg/webview2 panicked before main() -- whether or +// not the program ever used these three handlers: +// +// panic: compileCallback: argument size is larger than uintptr +// +// BOOL is left as Go's bool (ICoreWebView2PrintToPdf/TrySuspendCompletedHandler) although it is +// the same family. bool is 1 byte against a 4-byte BOOL, so the callee reads the low byte of the +// word -- correct for the 0/1 Win32 BOOL actually carries, and NewCallback accepts it because +// 1 <= sizeof(uintptr). Widening it to int32 would change those two Impl interfaces for every +// caller that implements them, to fix nothing observable. +func (p *Param) AsCallbackType() string { + if p.GoType == "string" { + // One star per level of IDL indirection, so LPCWSTR is *uint16 and LPCWSTR* is **uint16. + // Every string callback parameter in the pinned IDL is a plain LPCWSTR, but returning + // *uint16 regardless of depth would be its own silently-wrong answer if that changes. + return strings.Repeat("*", len(p.Pointer)) + "*uint16" + } + return p.AsInputType() +} + +func (p *Param) processSetup() error { p.processSetupInputs() p.processSetupOutputs() - p.processVtableCallInput() + return p.processVtableCallInput() } func (p *Param) SetupCode(w io.Writer) { @@ -101,20 +131,109 @@ func (p *Param) IsInputParam() bool { return !p.IsOutputParam() } -func (p *Param) processVtableCallInput() { +func (p *Param) processVtableCallInput() error { variableName := p.GetVariableName() - if strings.HasPrefix(p.Type, "int") || strings.HasPrefix(p.Type, "uint") || p.Type == "bool" || p.Type == "float32" || p.Type == "float64" { - p.VtableCallInput = "uintptr(" + variableName + ")" - return + + // This block used to test p.Type -- the IDL type, so "BOOL", "INT32", "double" -- against + // Go type names in lower case. It therefore never matched, and every by-value input + // parameter fell through to the &address catch-all at the bottom of this function, which + // makes the callee read a pointer as an integer. p.GoType is the mapped Go type and is + // what the comparisons meant. One wrong field name, and no scalar in-parameter in the + // whole binding was passed correctly. + if !p.isPointer() { + switch { + case p.GoType == "bool": + // A COM BOOL in-param is a 4-byte integer passed by value. uintptr(someBool) is + // not a legal Go conversion, hence the helper in com.tmpl. + p.VtableCallInput = "boolToUintptr(" + variableName + ")" + return nil + case strings.HasPrefix(p.GoType, "int"), strings.HasPrefix(p.GoType, "uint"): + p.VtableCallInput = "uintptr(" + variableName + ")" + return nil + } + // Handle typedefs and aggregates. See maps.go for the ABI rule and for why no single rule + // covers them: EventRegistrationToken alone is 61 call sites, and every remove_ method in + // the binding handed the callee the ADDRESS of the 8-byte token it was supposed to match, so + // no event handler could ever be removed -- and remove_ still returned S_OK. + if uintptrTypedef[p.Type] { + p.VtableCallInput = "uintptr(" + variableName + ")" + return nil + } + if expr, ok := byValueArgument[p.Type]; ok { + p.VtableCallInput = fmt.Sprintf(expr, variableName) + return nil + } + if _, ok := byRefAggregate[p.Type]; ok { + // Wider than a register, so here the address genuinely is the argument. + p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "))" + return nil + } + // A double goes in XMM0-XMM3 for the first four arguments, and Go's amd64 syscall + // assembly copies each of those four argument slots into the matching XMM register + // specifically so that floats work (runtime/sys_windows_amd64.s, "Load first 4 args into + // correspondent registers ... in case any of the arguments are floating point values"). + // So the bit pattern IS the argument, and Float64bits produces it. + // + // An earlier version of this comment claimed no marshalling answer existed. That was + // wrong, and it was wrong about the scope too: 12 methods take a double in-parameter -- + // PutZoomFactor, PutRasterizationScale, PutScaleFactor, PutExpires, PutPageWidth/Height, + // the four PutMargin*, SetBoundsAndZoomFactor and ClearBrowsingDataInTimeRange -- and all + // of them were handing the callee the ADDRESS of a Go float reinterpreted as a double. + // + // windows/arm64 remains unsolved: sys_windows_arm64.s loads only R0-R7 and never V0-V7, + // carrying a TODO to do what amd64 does. Passing the bits in an integer register is no + // worse there than passing a pointer was, so this is a strict improvement on both. + if p.GoType == "float64" { + p.VtableCallInput = "uintptr(math.Float64bits(" + variableName + "))" + p.decl.decl.includes.AddUnique(`"math"`) + return nil + } + // float32 is left unclassified on purpose: no IDL declares one, and it would need + // Float32bits in the low half of the register rather than Float64bits. + // Strings and enums are classified further down (the LPCWSTR case and IsEnum), so those two + // are exempt rather than unclassified. + if p.GoType != "string" && !p.IsEnum() { + // Refuse to guess. Every defect in this family was the &address default landing on a + // type nobody had classified, and each one returned S_OK while corrupting exactly one + // argument. A new IDL type should cost one line in maps.go, not a silent wire bug. + // + // An error rather than log.Fatalf: log.Fatalf calls os.Exit, and this runs inside the + // generator's own tests, so a reintroduced bug killed the test binary mid-run -- no + // attributable failure, and every test after it silently never ran. + return fmt.Errorf("by-value in-parameter %q of type %q (%s.%s) is in neither "+ + "byValueArgument nor byRefAggregate in maps.go. Classify it: an aggregate of "+ + "1, 2, 4 or 8 bytes is passed in a register as an integer of that width; "+ + "anything else is passed by address", + variableName, p.Type, p.decl.decl.Name, p.decl.ProcessedName) + } } switch p.Type { case "LPCWSTR", "LPWSTR": - p.VtableCallInput = "uintptr(unsafe.Pointer(" + variableName + "))" - return + // Direction matters here and was not being distinguished. An OUT parameter is + // declared LPWSTR* : the callee writes a string pointer into storage we own, so it + // needs the ADDRESS of our local *uint16. Passing the local's (nil) value instead + // gave the callee a null to write through, so every string getter returned empty -- + // silently, since the HRESULT was S_OK. An IN parameter is already the *uint16 that + // UTF16PtrFromString produced and is passed as-is. + if p.IsOutputParam() { + p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "))" + } else { + p.VtableCallInput = "uintptr(unsafe.Pointer(" + variableName + "))" + } + return nil } if p.Pointer == "**" { - p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "))" - return + // Direction matters here for the same reason it does for "*" below, and this branch was + // the one left without the check. An IN parameter is already the T** the caller built, so + // taking its address hands the callee a T*** -- it then reads our local's own value as the + // first element and calls through it. ICoreWebView2Environment14.CreateObjectCollection is + // the live example, and it is a wild call rather than a wrong value. + if p.IsOutputParam() { + p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "))" + } else { + p.VtableCallInput = "uintptr(unsafe.Pointer(" + variableName + "))" + } + return nil } if p.Pointer == "*" { if p.IsOutputParam() { @@ -122,13 +241,14 @@ func (p *Param) processVtableCallInput() { } else { p.VtableCallInput = "uintptr(unsafe.Pointer(" + variableName + "))" } - return + return nil } if p.IsEnum() { p.VtableCallInput = "uintptr(" + variableName + ")" - return + return nil } p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "))" + return nil } func (p *Param) ClearLocalName() string { @@ -192,8 +312,20 @@ func (p *Param) processSetupOutputs() { func (p *Param) defaultErrorValue() string { switch true { + // A pointer's zero value is nil, and this has to be tested FIRST: every case below asks what + // kind of thing p is, and for *T the answer that matters is only that it is a pointer. + case p.OutputGoType[0] == '*': + return "nil" + // uintptrTypedef rather than the three of the eight that happen to appear as out-parameters + // today (HANDLE, HWND, HCURSOR). The default branch below returns GoType{} as the zero value, + // which for a uintptr typedef does not compile -- so an HICON out-parameter in some later IDL + // would have broken the build with nothing to point at. Same knowledge, one place. + // + // The p.GoType guard matters because uintptrTypedef is keyed on the IDL type, which carries no + // indirection: without it [out] HANDLE** returned the integer 0 for a *HANDLE, which does not + // compile. That was a regression against the p.GoType == "HANDLE" test this replaced. case p.IsEnum(), strings.HasPrefix(p.GoType, "uint"), strings.HasPrefix(p.GoType, "int"), - p.GoType == "HANDLE", p.GoType == "HWND", p.GoType == "HCURSOR": + uintptrTypedef[p.Type] && p.GoType == p.Type: return "0" case strings.HasPrefix(p.GoType, "float"): return "0.0" @@ -201,8 +333,6 @@ func (p *Param) defaultErrorValue() string { return "false" case p.GoType == "string": return `""` - case p.OutputGoType[0] == '*': - return "nil" default: return p.GoType + "{}" } diff --git a/scripts/generator/types/struct.go b/scripts/generator/types/struct.go index 592b6da..8d28aff 100644 --- a/scripts/generator/types/struct.go +++ b/scripts/generator/types/struct.go @@ -51,6 +51,26 @@ type StructField struct { GoType string } +// idlStructFieldToGoType is deliberately separate from IdlTypeToGoType, which is written for +// PARAMETERS. A parameter's BOOL is converted at the boundary, so mapping it to Go's bool is a +// kindness to callers and costs nothing. A struct FIELD has no boundary: the struct is a memory +// layout that the callee writes into directly, so every field must be the width the C declaration +// says it is. +// +// BOOL is a 4-byte int. Mapping it to Go's 1-byte bool made COREWEBVIEW2_PHYSICAL_KEY_STATUS 12 +// bytes against a native 24, and its only use is +// ICoreWebView2AcceleratorKeyPressedEventArgs.GetPhysicalKeyStatus, which hands WebView2 the +// address of that 12-byte local. So every call wrote 12 bytes past the end of a heap object -- and +// even the bytes that landed inside were misread, because the last three flags sat at native +// offsets 12/16/20 while Go looked for them at 9/10/11, making them permanently false. +var idlStructFieldToGoType = map[string]string{ + "BOOL": "int32", +} + func (s *StructField) Process() { + if goType, ok := idlStructFieldToGoType[s.Type]; ok { + s.GoType = goType + return + } s.GoType = IdlTypeToGoType(s.Type) } diff --git a/scripts/generator/types/templates/com.tmpl b/scripts/generator/types/templates/com.tmpl index d74edfa..d1c2e36 100644 --- a/scripts/generator/types/templates/com.tmpl +++ b/scripts/generator/types/templates/com.tmpl @@ -32,14 +32,18 @@ type IUnknownVtbl struct { Release ComProc } -func (i *IUnknownVtbl) CallRelease(this unsafe.Pointer) error { - _, _, err := i.Release.Call( +// CallRelease returns the new reference count, which is what IUnknown::Release returns. +// +// This used to return error, built from the Errno that LazyProc.Call yields -- which is +// non-nil on success, so `err != windows.ERROR_SUCCESS` was true for every successful +// Release and the refcount was thrown away. pkg/edge/com.go and the committed +// pkg/webview2/com.go both already carry this corrected form; only the template did not. +func (i *IUnknownVtbl) CallRelease(this unsafe.Pointer) uint32 { + ret, _, _ := i.Release.Call( uintptr(this), ) - if err != windows.ERROR_SUCCESS { - return err - } - return nil + + return uint32(ret) } type IUnknownImpl interface { @@ -330,7 +334,7 @@ type IStream struct { Vtbl *IStreamVtbl } -func (i *IStream) Release() error { +func (i *IStream) Release() uint32 { return i.Vtbl.CallRelease(unsafe.Pointer(i)) } @@ -362,3 +366,16 @@ func (i *IStream) Read(p []byte) (int, error) { return 0, syscall.Errno(res) } } + +// boolToUintptr converts a Go bool to a Win32 BOOL passed by value. +// +// A COM in-parameter declared BOOL is a 4-byte integer passed BY VALUE. Handing over the +// address of a Go bool instead makes the callee read a pointer as an integer -- wrong, and +// wrong differently on each call. uintptr(b) is not a legal Go conversion, so the branch in +// Param.processVtableCallInput emits a call to this instead. +func boolToUintptr(b bool) uintptr { + if b { + return 1 + } + return 0 +} diff --git a/scripts/generator/types/templates/interfaceInvoke.tmpl b/scripts/generator/types/templates/interfaceInvoke.tmpl index 316f83a..fa1b30d 100644 --- a/scripts/generator/types/templates/interfaceInvoke.tmpl +++ b/scripts/generator/types/templates/interfaceInvoke.tmpl @@ -10,13 +10,18 @@ func {{.Declaration.Name}}IUnknownRelease(this *{{.Declaration.Name}}) uintptr { return this.impl.Release() } -func {{.Declaration.Name}}Invoke(this *{{.Declaration.Name}}, {{.InvokeMethod.GoInputs}}) uintptr { +{{/* CallbackInputs, not GoInputs: this function is the target of syscall.NewCallback, so its + parameters are whatever WebView2 left in the registers -- not the marshalled Go types an + outbound method is free to declare. GoInputs gave three handlers a "string" result parameter, + and because the vtable below is a package-level var, that made merely importing the package + panic during init on amd64. See Param.AsCallbackType. */ -}} +func {{.Declaration.Name}}Invoke(this *{{.Declaration.Name}}, {{.InvokeMethod.CallbackInputs}}) uintptr { return this.impl.{{.InvokeMethod.GoMethodName}}({{.InvokeMethod.InputParamNames}}) } type {{.Declaration.Name}}Impl interface { IUnknownImpl - {{.InvokeMethod.GoMethodName}}({{.InvokeMethod.GoInputs}}) uintptr + {{.InvokeMethod.GoMethodName}}({{.InvokeMethod.CallbackInputs}}) uintptr } var {{.Declaration.Name}}Fn = {{.Declaration.Name}}Vtbl{ diff --git a/scripts/generator/types/templates/interfaceMethod.tmpl b/scripts/generator/types/templates/interfaceMethod.tmpl index 23e36d8..aca6c2c 100644 --- a/scripts/generator/types/templates/interfaceMethod.tmpl +++ b/scripts/generator/types/templates/interfaceMethod.tmpl @@ -2,7 +2,12 @@ func (i *{{.Name}}) {{.Method.ProcessedName}}({{.Method.GoInputs}}) {{.Method.GoReturnTypes}} { {{ .Method.SetupCode}} - {{ .Method.GetHResultVariable }}, _, err := i.Vtbl.{{.Method.ProcessedName}}.Call( + {{/* The third return of syscall.LazyProc.Call is a syscall.Errno, which is NON-NIL even + on success ("The operation completed successfully"), so returning it made every + successful call look like a failure. HRESULT is the real status and is checked below. + Fixed across the generated tree by hand in "fix: com error handling" and "fix: + mischanged error values" but never here, so a regeneration reintroduced it. */}} + {{ .Method.GetHResultVariable }}, _, _ := i.Vtbl.{{.Method.ProcessedName}}.Call( uintptr(unsafe.Pointer(i)), {{ .Method.VtableCallInputs}} ) diff --git a/scripts/generator/types/templates/interfacevtbl.tmpl b/scripts/generator/types/templates/interfacevtbl.tmpl index 1926149..95b65f9 100644 --- a/scripts/generator/types/templates/interfacevtbl.tmpl +++ b/scripts/generator/types/templates/interfacevtbl.tmpl @@ -10,8 +10,24 @@ import ( ) {{- end}} +{{/* A COM vtable is FLAT: a derived interface's vtable begins with its entire base chain and + only then its own methods. Embedding IUnknownVtbl instead of the parent's vtable omitted + every intermediate interface's slots, so each method sat too early by however many + methods the chain above it declares, and a call landed on whichever unrelated method + occupies that offset. It cannot fail loudly -- the wrong slot holds a real function + pointer, so it runs and returns S_OK. + + The IDL always states a base ("interface ICoreWebView2_2 : ICoreWebView2") and the parser + already captures it as BaseClass; it was simply never used here. A first-generation + interface's base IS IUnknown, so one expression covers both cases. + + Concretely this moves ICoreWebView2_14's AddServerCertificateErrorDetected from slot 4 -- + ICoreWebView2::get_Settings, whose single out-parameter duly wrote the Settings pointer + over the caller's event-handler struct -- to its correct slot 107. 88 interfaces were + affected. Base-interface calls were always correct, which is why Navigate and + AddNavigationCompleted worked throughout and hid this for as long as they did. */}} type {{.Name}}Vtbl struct { - IUnknownVtbl + {{ if .BaseClass }}{{.BaseClass}}Vtbl{{ else }}IUnknownVtbl{{ end }} {{- range .Methods}} {{.ProcessedName}} ComProc {{- end}} @@ -28,12 +44,54 @@ func (i *{{.Name}}) AddRef() uintptr { refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i))) return refCounter } +{{ if not .HasInvokeMethod }} +// Release drops one reference and returns the new count. +// +// AddRef was generated for all 252 interfaces and Release for none, which left every caller of a +// Get() accessor leaking: QueryInterface AddRefs on success and there was no matching +// call to make, short of reaching through the embedded IUnknownVtbl for CallRelease. Additive, so +// no existing caller changes. +// +// Not generated for handler interfaces: those are objects WE implement and hand to WebView2, so +// their lifetime is the Go object's, and calling through the vtable would re-enter our own impl. +func (i *{{.Name}}) Release() uint32 { + return i.Vtbl.CallRelease(unsafe.Pointer(i)) +} +{{ end }} + +{{/* The QueryInterface accessor belongs on an interface of the OBJECT that can answer it, and + the declared chain's ROOT is what names that object -- not the immediate base. See + InterfaceDeclaration.RootInterface. + + The receiver was hardcoded to ICoreWebView2. For the ICoreWebView2_N chain that is right: + same object, so a webview can hand out ICoreWebView2_14 without walking thirteen + accessors. For every other chain it is wrong, and uselessly so -- + GetICoreWebView2Controller2 hung off ICoreWebView2, which is a different object and can + only fail, while ICoreWebView2Controller, which can answer, had no accessor at all. Rooting + on the chain start fixes those and leaves the ICoreWebView2_N family untouched, so no + existing caller breaks. + + An interface whose base is IUnknown gets NO accessor, here or before this change: the guard + below is BaseClass, which generateVtbl blanks for IUnknown. So the 169 such interfaces -- + ICoreWebView2EnvironmentOptions among them -- have never had one, and there is no sibling + interface to hang one on. Giving them one would be an API addition needing a decision about + where it belongs, not a fix. (An earlier version of this comment claimed they "keep the + ICoreWebView2 receiver they have today"; there was nothing to keep.) + RootInterface is non-empty exactly when BaseClass is not IUnknown, which is the same condition + as the guard -- so there is no second case to handle. */}} {{if .BaseClass }} -func (i *ICoreWebView2) Get{{.Name}}() *{{.Name}} { +func (i *{{.RootInterface}}) Get{{.Name}}() *{{.Name}} { var result *{{.Name}} iid{{.Name}} := NewGUID({{.Header.AsString}}) + // The HRESULT is deliberately not returned, because changing the signature of all 82 of these + // accessors is an API break. It is E_NOINTERFACE whenever the installed WebView2 Runtime is + // older than this interface, which is the normal case rather than an exotic one -- and then + // result stays nil and the CALLER's next method call dereferences it. Callers must nil-check. + // + // This also leaks a reference on success: QueryInterface AddRefs, and no Release is generated. + // Use Vtbl.CallRelease(unsafe.Pointer(x)) via the embedded IUnknownVtbl when finished. _, _, _ = i.Vtbl.QueryInterface.Call( uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(iid{{.Name}})), diff --git a/scripts/regen/main.go b/scripts/regen/main.go new file mode 100644 index 0000000..c996356 --- /dev/null +++ b/scripts/regen/main.go @@ -0,0 +1,66 @@ +// Command regen runs the generator against a local IDL and writes the result to a chosen +// directory. update_version_mapping.go can only regenerate as a side effect of checking +// Microsoft's release-notes page for a NEW version, which needs the network and rewrites the +// tree in place -- neither of which suits comparing generator output against the committed +// files. +// +// Usage: go run ./regen -idl WebView2.1.0.2903.40.idl -out /tmp/baseline +package main + +import ( + "flag" + "log" + "os" + "path/filepath" + "strings" + + "updater/generator" +) + +func main() { + idl := flag.String("idl", "WebView2.1.0.2903.40.idl", "IDL file to generate from") + out := flag.String("out", "", "directory to write the generated files to (required)") + flag.Parse() + if *out == "" { + log.Fatal("-out is required") + } + + data, err := os.ReadFile(*idl) + if err != nil { + log.Fatal(err) + } + files, err := generator.ParseIDL(data) + if err != nil { + log.Fatal(err) + } + if err := os.MkdirAll(*out, 0o755); err != nil { + log.Fatal(err) + } + // Clear the previously generated files, because reusing a directory across two IDL versions + // otherwise leaves behind the ones only the earlier version produced, and `diff -r` then reads + // as though they were still being generated -- which defeats the one thing this command is for. + // + // Only non-test .go files, NOT the whole directory: -out is usually pkg/webview2 itself, which + // also holds hand-written tests. Everything the generator emits is a non-test .go file, so that + // line is exactly the boundary between "derived, safe to delete" and "written by a person". + // RemoveAll here deleted marshal_windows_test.go, silently, and the package went back to + // reporting "no test files". + stale, err := filepath.Glob(filepath.Join(*out, "*.go")) + if err != nil { + log.Fatal(err) + } + for _, f := range stale { + if strings.HasSuffix(f, "_test.go") { + continue + } + if err := os.Remove(f); err != nil { + log.Fatal(err) + } + } + for _, f := range files { + if err := os.WriteFile(filepath.Join(*out, f.FileName), f.Content.Bytes(), 0o644); err != nil { + log.Fatal(err) + } + } + log.Printf("wrote %d files to %s", len(files), *out) +}