Initialize COM around file dialogs.

This commit is contained in:
Nuno Cruces 2024-02-05 10:20:14 +00:00
parent 341ccb89d4
commit 3f5b602117
2 changed files with 43 additions and 8 deletions

View File

@ -1,8 +1,10 @@
package zenity
import (
"context"
"fmt"
"path/filepath"
"runtime"
"syscall"
"unicode/utf16"
"unsafe"
@ -36,6 +38,12 @@ func selectFile(opts options) (string, error) {
args.MaxFile = uint32(len(res))
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
uninit, err := coInitialize()
if err != nil {
return "", err
}
defer uninit()
defer setup(args.Owner)()
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
if err != nil {
@ -79,6 +87,12 @@ func selectFileMultiple(opts options) ([]string, error) {
args.MaxFile = uint32(len(res))
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
uninit, err := coInitialize()
if err != nil {
return nil, err
}
defer uninit()
defer setup(args.Owner)()
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
if err != nil {
@ -153,6 +167,12 @@ func selectFileSave(opts options) (string, error) {
args.MaxFile = uint32(len(res))
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
uninit, err := coInitialize()
if err != nil {
return "", err
}
defer uninit()
defer setup(args.Owner)()
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
if err != nil {
@ -171,17 +191,15 @@ func selectFileSave(opts options) (string, error) {
}
func pickFolders(opts options, multi bool) (string, []string, error) {
uninit, err := coInitialize()
if err != nil {
return "", nil, err
}
defer uninit()
owner, _ := opts.attach.(win.HWND)
defer setup(owner)()
err := win.CoInitializeEx(0, win.COINIT_APARTMENTTHREADED|win.COINIT_DISABLE_OLE1DDE)
if err != win.RPC_E_CHANGED_MODE {
if err != nil {
return "", nil, err
}
defer win.CoUninitialize()
}
var dialog *win.IFileOpenDialog
err = win.CoCreateInstance(
win.CLSID_FileOpenDialog, nil, win.CLSCTX_ALL,
@ -320,6 +338,22 @@ func browseForFolderCallback(wnd win.HWND, msg uint32, lparam, data uintptr) uin
return 0
}
func coInitialize() (context.CancelFunc, error) {
runtime.LockOSThread()
err := win.CoInitializeEx(0, win.COINIT_APARTMENTTHREADED|win.COINIT_DISABLE_OLE1DDE)
if err == nil || err == win.S_FALSE {
return func() {
win.CoUninitialize()
runtime.UnlockOSThread()
}, nil
}
if err == win.RPC_E_CHANGED_MODE {
return runtime.UnlockOSThread, nil
}
runtime.UnlockOSThread()
return nil, err
}
func initDirNameExt(filename string, name []uint16) (dir *uint16, ext *uint16) {
d, n, _ := splitDirAndName(filename)
e := filepath.Ext(n)

View File

@ -24,6 +24,7 @@ const (
E_CANCELED = windows.ERROR_CANCELLED | windows.FACILITY_WIN32<<16 | 0x80000000
RPC_E_CHANGED_MODE = syscall.Errno(windows.RPC_E_CHANGED_MODE)
S_FALSE = syscall.Errno(windows.S_FALSE)
)
func CoInitializeEx(reserved uintptr, coInit uint32) error {