Initialize COM around file dialogs.
This commit is contained in:
parent
341ccb89d4
commit
3f5b602117
2 changed files with 43 additions and 8 deletions
|
@ -1,8 +1,10 @@
|
||||||
package zenity
|
package zenity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
@ -36,6 +38,12 @@ func selectFile(opts options) (string, error) {
|
||||||
args.MaxFile = uint32(len(res))
|
args.MaxFile = uint32(len(res))
|
||||||
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
||||||
|
|
||||||
|
uninit, err := coInitialize()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer uninit()
|
||||||
|
|
||||||
defer setup(args.Owner)()
|
defer setup(args.Owner)()
|
||||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -79,6 +87,12 @@ func selectFileMultiple(opts options) ([]string, error) {
|
||||||
args.MaxFile = uint32(len(res))
|
args.MaxFile = uint32(len(res))
|
||||||
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
||||||
|
|
||||||
|
uninit, err := coInitialize()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer uninit()
|
||||||
|
|
||||||
defer setup(args.Owner)()
|
defer setup(args.Owner)()
|
||||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -153,6 +167,12 @@ func selectFileSave(opts options) (string, error) {
|
||||||
args.MaxFile = uint32(len(res))
|
args.MaxFile = uint32(len(res))
|
||||||
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
||||||
|
|
||||||
|
uninit, err := coInitialize()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer uninit()
|
||||||
|
|
||||||
defer setup(args.Owner)()
|
defer setup(args.Owner)()
|
||||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -171,17 +191,15 @@ func selectFileSave(opts options) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickFolders(opts options, multi bool) (string, []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)
|
owner, _ := opts.attach.(win.HWND)
|
||||||
defer setup(owner)()
|
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
|
var dialog *win.IFileOpenDialog
|
||||||
err = win.CoCreateInstance(
|
err = win.CoCreateInstance(
|
||||||
win.CLSID_FileOpenDialog, nil, win.CLSCTX_ALL,
|
win.CLSID_FileOpenDialog, nil, win.CLSCTX_ALL,
|
||||||
|
@ -320,6 +338,22 @@ func browseForFolderCallback(wnd win.HWND, msg uint32, lparam, data uintptr) uin
|
||||||
return 0
|
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) {
|
func initDirNameExt(filename string, name []uint16) (dir *uint16, ext *uint16) {
|
||||||
d, n, _ := splitDirAndName(filename)
|
d, n, _ := splitDirAndName(filename)
|
||||||
e := filepath.Ext(n)
|
e := filepath.Ext(n)
|
||||||
|
|
|
@ -24,6 +24,7 @@ const (
|
||||||
|
|
||||||
E_CANCELED = windows.ERROR_CANCELLED | windows.FACILITY_WIN32<<16 | 0x80000000
|
E_CANCELED = windows.ERROR_CANCELLED | windows.FACILITY_WIN32<<16 | 0x80000000
|
||||||
RPC_E_CHANGED_MODE = syscall.Errno(windows.RPC_E_CHANGED_MODE)
|
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 {
|
func CoInitializeEx(reserved uintptr, coInit uint32) error {
|
||||||
|
|
Loading…
Reference in a new issue