zenity/file_windows.go

530 lines
13 KiB
Go
Raw Normal View History

2019-12-29 20:00:50 -05:00
package zenity
2019-12-13 08:45:23 -05:00
import (
2022-05-03 09:20:22 -04:00
"fmt"
2019-12-13 08:45:23 -05:00
"path/filepath"
2019-12-28 10:34:38 -05:00
"reflect"
2019-12-13 08:45:23 -05:00
"syscall"
"unicode/utf16"
"unsafe"
)
2019-12-13 20:07:25 -05:00
var (
2019-12-28 10:34:38 -05:00
getOpenFileName = comdlg32.NewProc("GetOpenFileNameW")
getSaveFileName = comdlg32.NewProc("GetSaveFileNameW")
shBrowseForFolder = shell32.NewProc("SHBrowseForFolderW")
shCreateItemFromParsingName = shell32.NewProc("SHCreateItemFromParsingName")
2022-05-19 18:39:21 -04:00
shGetPathFromIDListEx = shell32.NewProc("SHGetPathFromIDListEx")
)
const (
_OFN_OVERWRITEPROMPT = 0x00000002
_OFN_NOCHANGEDIR = 0x00000008
_OFN_ALLOWMULTISELECT = 0x00000200
_OFN_PATHMUSTEXIST = 0x00000800
_OFN_FILEMUSTEXIST = 0x00001000
_OFN_CREATEPROMPT = 0x00002000
_OFN_NOREADONLYRETURN = 0x00008000
_OFN_EXPLORER = 0x00080000
_OFN_FORCESHOWHIDDEN = 0x10000000
_FOS_NOCHANGEDIR = 0x00000008
_FOS_PICKFOLDERS = 0x00000020
_FOS_FORCEFILESYSTEM = 0x00000040
_FOS_ALLOWMULTISELECT = 0x00000200
_FOS_FORCESHOWHIDDEN = 0x10000000
2019-12-13 20:07:25 -05:00
)
2019-12-13 08:45:23 -05:00
2021-03-04 07:42:30 -05:00
func selectFile(opts options) (string, error) {
2020-01-09 20:46:53 -05:00
if opts.directory {
res, _, err := pickFolders(opts, false)
return res, err
}
2019-12-13 08:45:23 -05:00
var args _OPENFILENAME
args.StructSize = uint32(unsafe.Sizeof(args))
2022-06-08 15:33:10 -04:00
args.Owner, _ = opts.attach.(uintptr)
2022-05-19 18:39:21 -04:00
args.Flags = _OFN_NOCHANGEDIR | _OFN_FILEMUSTEXIST | _OFN_EXPLORER
2019-12-13 08:45:23 -05:00
2021-03-03 22:25:45 -05:00
if opts.title != nil {
args.Title = syscall.StringToUTF16Ptr(*opts.title)
2019-12-13 08:45:23 -05:00
}
2020-01-24 07:52:45 -05:00
if opts.showHidden {
2022-05-19 18:39:21 -04:00
args.Flags |= _OFN_FORCESHOWHIDDEN
}
2020-01-24 07:52:45 -05:00
if opts.fileFilters != nil {
args.Filter = &initFilters(opts.fileFilters)[0]
2020-01-08 19:54:34 -05:00
}
2019-12-13 08:45:23 -05:00
2021-04-27 20:27:28 -04:00
var res [32768]uint16
2019-12-13 08:45:23 -05:00
args.File = &res[0]
args.MaxFile = uint32(len(res))
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
2019-12-13 08:45:23 -05:00
2021-03-26 08:40:24 -04:00
defer setup()()
2020-01-02 20:44:23 -05:00
2020-01-30 09:14:42 -05:00
if opts.ctx != nil {
2022-05-19 18:39:21 -04:00
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
2020-01-30 09:14:42 -05:00
if err != nil {
return "", err
}
defer unhook()
}
2020-01-29 09:15:21 -05:00
s, _, _ := getOpenFileName.Call(uintptr(unsafe.Pointer(&args)))
2020-01-30 09:14:42 -05:00
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", opts.ctx.Err()
}
2020-01-29 09:15:21 -05:00
if s == 0 {
2020-01-02 20:44:23 -05:00
return "", commDlgError()
2019-12-28 10:34:38 -05:00
}
2019-12-13 08:45:23 -05:00
return syscall.UTF16ToString(res[:]), nil
}
2022-05-19 09:09:21 -04:00
func selectFileMultiple(opts options) ([]string, error) {
2020-01-09 20:46:53 -05:00
if opts.directory {
_, res, err := pickFolders(opts, true)
return res, err
}
2019-12-13 08:45:23 -05:00
var args _OPENFILENAME
args.StructSize = uint32(unsafe.Sizeof(args))
2022-06-08 15:33:10 -04:00
args.Owner, _ = opts.attach.(uintptr)
2022-05-19 18:39:21 -04:00
args.Flags = _OFN_NOCHANGEDIR | _OFN_ALLOWMULTISELECT | _OFN_FILEMUSTEXIST | _OFN_EXPLORER
2019-12-13 08:45:23 -05:00
2021-03-03 22:25:45 -05:00
if opts.title != nil {
args.Title = syscall.StringToUTF16Ptr(*opts.title)
2019-12-13 08:45:23 -05:00
}
2020-01-24 07:52:45 -05:00
if opts.showHidden {
2022-05-19 18:39:21 -04:00
args.Flags |= _OFN_FORCESHOWHIDDEN
}
2020-01-24 07:52:45 -05:00
if opts.fileFilters != nil {
args.Filter = &initFilters(opts.fileFilters)[0]
2020-01-08 19:54:34 -05:00
}
2019-12-13 08:45:23 -05:00
2021-04-27 20:27:28 -04:00
var res [32768 + 1024*256]uint16
2019-12-13 08:45:23 -05:00
args.File = &res[0]
args.MaxFile = uint32(len(res))
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
2019-12-13 08:45:23 -05:00
2021-03-26 08:40:24 -04:00
defer setup()()
2020-01-02 20:44:23 -05:00
2020-01-30 09:14:42 -05:00
if opts.ctx != nil {
2022-05-19 18:39:21 -04:00
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
2020-01-30 09:14:42 -05:00
if err != nil {
return nil, err
}
defer unhook()
}
2020-01-29 09:15:21 -05:00
s, _, _ := getOpenFileName.Call(uintptr(unsafe.Pointer(&args)))
2020-01-30 09:14:42 -05:00
if opts.ctx != nil && opts.ctx.Err() != nil {
return nil, opts.ctx.Err()
}
2020-01-29 09:15:21 -05:00
if s == 0 {
2020-01-02 20:44:23 -05:00
return nil, commDlgError()
2019-12-28 10:34:38 -05:00
}
2019-12-13 08:45:23 -05:00
var i int
var nul bool
var split []string
for j, p := range res {
if p == 0 {
if nul {
break
}
if i < j {
split = append(split, string(utf16.Decode(res[i:j])))
}
i = j + 1
nul = true
} else {
nul = false
}
}
if len := len(split) - 1; len > 0 {
base := split[0]
for i := 0; i < len; i++ {
split[i] = filepath.Join(base, string(split[i+1]))
}
split = split[:len]
}
return split, nil
}
2021-03-04 07:42:30 -05:00
func selectFileSave(opts options) (string, error) {
if opts.directory {
res, _, err := pickFolders(opts, false)
return res, err
}
2020-01-09 20:46:53 -05:00
2019-12-13 08:45:23 -05:00
var args _OPENFILENAME
args.StructSize = uint32(unsafe.Sizeof(args))
2022-06-08 15:33:10 -04:00
args.Owner, _ = opts.attach.(uintptr)
2022-05-19 18:39:21 -04:00
args.Flags = _OFN_NOCHANGEDIR | _OFN_PATHMUSTEXIST | _OFN_NOREADONLYRETURN | _OFN_EXPLORER
2019-12-13 08:45:23 -05:00
2021-03-03 22:25:45 -05:00
if opts.title != nil {
args.Title = syscall.StringToUTF16Ptr(*opts.title)
2019-12-13 08:45:23 -05:00
}
2020-01-24 07:52:45 -05:00
if opts.confirmOverwrite {
2022-05-19 18:39:21 -04:00
args.Flags |= _OFN_OVERWRITEPROMPT
2019-12-13 08:45:23 -05:00
}
2020-01-24 07:52:45 -05:00
if opts.confirmCreate {
2022-05-19 18:39:21 -04:00
args.Flags |= _OFN_CREATEPROMPT
}
2020-01-24 07:52:45 -05:00
if opts.showHidden {
2022-05-19 18:39:21 -04:00
args.Flags |= _OFN_FORCESHOWHIDDEN
}
2020-01-24 07:52:45 -05:00
if opts.fileFilters != nil {
args.Filter = &initFilters(opts.fileFilters)[0]
2020-01-08 19:54:34 -05:00
}
2019-12-13 08:45:23 -05:00
2021-04-27 20:27:28 -04:00
var res [32768]uint16
2019-12-13 08:45:23 -05:00
args.File = &res[0]
args.MaxFile = uint32(len(res))
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
2019-12-13 08:45:23 -05:00
2021-03-26 08:40:24 -04:00
defer setup()()
2020-01-02 20:44:23 -05:00
2020-01-30 09:14:42 -05:00
if opts.ctx != nil {
2022-05-19 18:39:21 -04:00
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
2020-01-30 09:14:42 -05:00
if err != nil {
return "", err
}
defer unhook()
}
2020-01-29 09:15:21 -05:00
s, _, _ := getSaveFileName.Call(uintptr(unsafe.Pointer(&args)))
2020-01-30 09:14:42 -05:00
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", opts.ctx.Err()
}
2020-01-29 09:15:21 -05:00
if s == 0 {
2020-01-02 20:44:23 -05:00
return "", commDlgError()
2019-12-28 10:34:38 -05:00
}
2019-12-13 08:45:23 -05:00
return syscall.UTF16ToString(res[:]), nil
}
2020-01-09 20:46:53 -05:00
func pickFolders(opts options, multi bool) (str string, lst []string, err error) {
2021-03-26 08:40:24 -04:00
defer setup()()
2020-01-02 20:44:23 -05:00
2019-12-28 10:34:38 -05:00
hr, _, _ := coInitializeEx.Call(0, 0x6) // COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE
2020-01-02 20:44:23 -05:00
if hr != 0x80010106 { // RPC_E_CHANGED_MODE
if int32(hr) < 0 {
2020-01-09 20:46:53 -05:00
return "", nil, syscall.Errno(hr)
2020-01-02 20:44:23 -05:00
}
defer coUninitialize.Call()
2019-12-28 10:34:38 -05:00
}
2020-01-02 20:44:23 -05:00
2019-12-28 10:34:38 -05:00
var dialog *_IFileOpenDialog
hr, _, _ = coCreateInstance.Call(
_CLSID_FileOpenDialog, 0, 0x17, // CLSCTX_ALL
_IID_IFileOpenDialog, uintptr(unsafe.Pointer(&dialog)))
2020-01-02 20:44:23 -05:00
if int32(hr) < 0 {
2021-07-12 20:43:52 -04:00
if multi {
2022-05-03 09:20:22 -04:00
return "", nil, fmt.Errorf("%w: multiple directory", ErrUnsupported)
2021-07-12 20:43:52 -04:00
}
return browseForFolder(opts)
2019-12-28 10:34:38 -05:00
}
2021-03-10 09:49:09 -05:00
defer dialog.Call(dialog.Release)
2019-12-28 10:34:38 -05:00
2020-01-02 20:44:23 -05:00
var flgs int
2021-03-10 09:49:09 -05:00
hr, _, _ = dialog.Call(dialog.GetOptions, uintptr(unsafe.Pointer(&flgs)))
2020-01-02 20:44:23 -05:00
if int32(hr) < 0 {
2020-01-09 20:46:53 -05:00
return "", nil, syscall.Errno(hr)
}
2022-05-19 18:39:21 -04:00
flgs |= _FOS_NOCHANGEDIR | _FOS_PICKFOLDERS | _FOS_FORCEFILESYSTEM
2020-01-09 20:46:53 -05:00
if multi {
2022-05-19 18:39:21 -04:00
flgs |= _FOS_ALLOWMULTISELECT
2019-12-28 10:34:38 -05:00
}
2020-01-24 07:52:45 -05:00
if opts.showHidden {
2022-05-19 18:39:21 -04:00
flgs |= _FOS_FORCESHOWHIDDEN
}
2022-05-19 18:39:21 -04:00
hr, _, _ = dialog.Call(dialog.SetOptions, uintptr(flgs))
2020-01-02 20:44:23 -05:00
if int32(hr) < 0 {
2020-01-09 20:46:53 -05:00
return "", nil, syscall.Errno(hr)
2019-12-28 10:34:38 -05:00
}
2021-03-03 22:25:45 -05:00
if opts.title != nil {
ptr := syscall.StringToUTF16Ptr(*opts.title)
2021-03-10 09:49:09 -05:00
dialog.Call(dialog.SetTitle, uintptr(unsafe.Pointer(ptr)))
2019-12-28 10:34:38 -05:00
}
2020-01-02 20:44:23 -05:00
if opts.filename != "" {
2019-12-28 10:34:38 -05:00
var item *_IShellItem
2020-01-02 20:44:23 -05:00
ptr := syscall.StringToUTF16Ptr(opts.filename)
2019-12-28 10:34:38 -05:00
hr, _, _ = shCreateItemFromParsingName.Call(
uintptr(unsafe.Pointer(ptr)), 0,
_IID_IShellItem,
uintptr(unsafe.Pointer(&item)))
2021-03-07 20:12:32 -05:00
if int32(hr) >= 0 && item != nil {
2021-03-10 09:49:09 -05:00
dialog.Call(dialog.SetFolder, uintptr(unsafe.Pointer(item)))
item.Call(item.Release)
2019-12-28 10:34:38 -05:00
}
}
2020-01-30 20:31:54 -05:00
if opts.ctx != nil {
2022-05-19 18:39:21 -04:00
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
2020-01-30 20:31:54 -05:00
if err != nil {
return "", nil, err
}
defer unhook()
}
2022-06-08 15:33:10 -04:00
owner, _ := opts.attach.(uintptr)
hr, _, _ = dialog.Call(dialog.Show, owner)
2020-01-30 20:31:54 -05:00
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", nil, opts.ctx.Err()
}
2020-01-02 20:44:23 -05:00
if hr == 0x800704c7 { // ERROR_CANCELLED
2021-04-29 11:05:28 -04:00
return "", nil, ErrCanceled
2020-01-02 20:44:23 -05:00
}
if int32(hr) < 0 {
2020-01-09 20:46:53 -05:00
return "", nil, syscall.Errno(hr)
2019-12-28 10:34:38 -05:00
}
2020-01-09 20:46:53 -05:00
shellItemPath := func(obj *_COMObject, trap uintptr, a ...uintptr) error {
var item *_IShellItem
hr, _, _ := obj.Call(trap, append(a, uintptr(unsafe.Pointer(&item)))...)
if int32(hr) < 0 {
return syscall.Errno(hr)
}
2021-03-10 09:49:09 -05:00
defer item.Call(item.Release)
2019-12-28 10:34:38 -05:00
2020-01-09 20:46:53 -05:00
var ptr uintptr
2021-03-10 09:49:09 -05:00
hr, _, _ = item.Call(item.GetDisplayName,
2020-01-09 20:46:53 -05:00
0x80058000, // SIGDN_FILESYSPATH
uintptr(unsafe.Pointer(&ptr)))
if int32(hr) < 0 {
return syscall.Errno(hr)
}
defer coTaskMemFree.Call(ptr)
2021-01-05 10:21:18 -05:00
var res []uint16
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&res))
hdr.Data, hdr.Len, hdr.Cap = ptr, 32768, 32768
str = syscall.UTF16ToString(res)
2020-01-09 20:46:53 -05:00
lst = append(lst, str)
return nil
2019-12-28 10:34:38 -05:00
}
2020-01-09 20:46:53 -05:00
if multi {
var items *_IShellItemArray
2021-03-10 09:49:09 -05:00
hr, _, _ = dialog.Call(dialog.GetResults, uintptr(unsafe.Pointer(&items)))
2020-01-09 20:46:53 -05:00
if int32(hr) < 0 {
return "", nil, syscall.Errno(hr)
}
2021-03-10 09:49:09 -05:00
defer items.Call(items.Release)
2020-01-09 20:46:53 -05:00
var count uint32
2021-03-10 09:49:09 -05:00
hr, _, _ = items.Call(items.GetCount, uintptr(unsafe.Pointer(&count)))
2020-01-09 20:46:53 -05:00
if int32(hr) < 0 {
return "", nil, syscall.Errno(hr)
}
for i := uintptr(0); i < uintptr(count) && err == nil; i++ {
2021-03-10 09:49:09 -05:00
err = shellItemPath(&items._COMObject, items.GetItemAt, i)
2020-01-09 20:46:53 -05:00
}
} else {
2021-03-10 09:49:09 -05:00
err = shellItemPath(&dialog._COMObject, dialog.GetResult)
2020-01-09 20:46:53 -05:00
}
return
2019-12-28 10:34:38 -05:00
}
func browseForFolder(opts options) (string, []string, error) {
2019-12-13 20:07:25 -05:00
var args _BROWSEINFO
2022-06-08 15:33:10 -04:00
args.Owner, _ = opts.attach.(uintptr)
2019-12-28 10:34:38 -05:00
args.Flags = 0x1 // BIF_RETURNONLYFSDIRS
2019-12-13 20:07:25 -05:00
2021-03-03 22:25:45 -05:00
if opts.title != nil {
args.Title = syscall.StringToUTF16Ptr(*opts.title)
}
if opts.filename != "" {
2021-09-15 08:54:35 -04:00
args.LParam = syscall.StringToUTF16Ptr(opts.filename)
args.CallbackFunc = syscall.NewCallback(browseForFolderCallback)
2019-12-13 20:07:25 -05:00
}
2020-01-30 20:31:54 -05:00
if opts.ctx != nil {
2022-05-19 18:39:21 -04:00
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
2020-01-30 20:31:54 -05:00
if err != nil {
return "", nil, err
}
defer unhook()
}
2019-12-28 10:34:38 -05:00
ptr, _, _ := shBrowseForFolder.Call(uintptr(unsafe.Pointer(&args)))
2020-01-30 20:31:54 -05:00
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", nil, opts.ctx.Err()
}
2019-12-13 20:07:25 -05:00
if ptr == 0 {
2021-04-29 11:05:28 -04:00
return "", nil, ErrCanceled
2019-12-13 20:07:25 -05:00
}
2019-12-28 10:34:38 -05:00
defer coTaskMemFree.Call(ptr)
2019-12-13 20:07:25 -05:00
2021-04-27 20:27:28 -04:00
var res [32768]uint16
2019-12-28 10:34:38 -05:00
shGetPathFromIDListEx.Call(ptr, uintptr(unsafe.Pointer(&res[0])), uintptr(len(res)), 0)
2019-12-13 20:07:25 -05:00
2020-01-09 20:46:53 -05:00
str := syscall.UTF16ToString(res[:])
return str, []string{str}, nil
2019-12-13 08:45:23 -05:00
}
func browseForFolderCallback(wnd uintptr, msg uint32, lparam, data uintptr) uintptr {
if msg == 1 { // BFFM_INITIALIZED
sendMessage.Call(wnd, 1024+103 /* BFFM_SETSELECTIONW */, 1 /* TRUE */, data)
}
return 0
}
func initDirNameExt(filename string, name []uint16) (dir *uint16, ext *uint16) {
2021-02-18 08:24:02 -05:00
d, n := splitDirAndName(filename)
e := filepath.Ext(n)
if n != "" {
2021-05-07 09:02:44 -04:00
copy(name, syscall.StringToUTF16(n))
2021-02-18 08:24:02 -05:00
}
if d != "" {
dir = syscall.StringToUTF16Ptr(d)
}
2021-02-22 14:04:55 -05:00
if len(e) > 1 {
2021-02-18 08:24:02 -05:00
ext = syscall.StringToUTF16Ptr(e[1:])
2020-01-09 12:05:43 -05:00
}
return
2020-01-09 12:05:43 -05:00
}
2021-04-13 08:28:26 -04:00
func initFilters(filters FileFilters) []uint16 {
filters.simplify()
2021-04-13 09:37:10 -04:00
filters.name()
2019-12-13 08:45:23 -05:00
var res []uint16
for _, f := range filters {
res = append(res, utf16.Encode([]rune(f.Name))...)
res = append(res, 0)
2020-01-08 19:54:34 -05:00
for _, p := range f.Patterns {
res = append(res, utf16.Encode([]rune(p))...)
2019-12-13 08:45:23 -05:00
res = append(res, uint16(';'))
}
res = append(res, 0)
}
if res != nil {
res = append(res, 0)
}
return res
}
2021-03-10 09:49:09 -05:00
// https://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamew
2019-12-13 08:45:23 -05:00
type _OPENFILENAME struct {
StructSize uint32
Owner uintptr
Instance uintptr
Filter *uint16
CustomFilter *uint16
MaxCustomFilter uint32
FilterIndex uint32
File *uint16
MaxFile uint32
FileTitle *uint16
MaxFileTitle uint32
InitialDir *uint16
Title *uint16
Flags uint32
FileOffset uint16
FileExtension uint16
DefExt *uint16
CustData uintptr
FnHook uintptr
TemplateName *uint16
2019-12-13 20:07:25 -05:00
PvReserved uintptr
2019-12-13 08:45:23 -05:00
DwReserved uint32
FlagsEx uint32
}
2019-12-13 20:07:25 -05:00
2021-03-10 09:49:09 -05:00
// https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfow
2019-12-13 20:07:25 -05:00
type _BROWSEINFO struct {
Owner uintptr
2019-12-28 10:34:38 -05:00
Root uintptr
2019-12-13 20:07:25 -05:00
DisplayName *uint16
Title *uint16
Flags uint32
CallbackFunc uintptr
2021-09-15 08:54:35 -04:00
LParam *uint16
2019-12-13 20:07:25 -05:00
Image int32
}
2019-12-28 10:34:38 -05:00
2021-03-10 09:49:09 -05:00
// https://github.com/wine-mirror/wine/blob/master/include/shobjidl.idl
2019-12-28 10:34:38 -05:00
var (
_IID_IShellItem = uuid("\x1e\x6d\x82\x43\x18\xe7\xee\x42\xbc\x55\xa1\xe2\x61\xc3\x7b\xfe")
_IID_IFileOpenDialog = uuid("\x88\x72\x7c\xd5\xad\xd4\x68\x47\xbe\x02\x9d\x96\x95\x32\xd9\x60")
_CLSID_FileOpenDialog = uuid("\x9c\x5a\x1c\xdc\x8a\xe8\xde\x4d\xa5\xa1\x60\xf8\x2a\x20\xae\xf7")
)
type _IFileOpenDialog struct {
_COMObject
2021-03-10 09:49:09 -05:00
*_IFileOpenDialogVtbl
2019-12-28 10:34:38 -05:00
}
type _IShellItem struct {
_COMObject
2021-03-10 09:49:09 -05:00
*_IShellItemVtbl
2019-12-28 10:34:38 -05:00
}
2020-01-09 20:46:53 -05:00
type _IShellItemArray struct {
_COMObject
2021-03-10 09:49:09 -05:00
*_IShellItemArrayVtbl
2020-01-09 20:46:53 -05:00
}
2019-12-28 10:34:38 -05:00
type _IFileOpenDialogVtbl struct {
_IFileDialogVtbl
GetResults uintptr
GetSelectedItems uintptr
}
type _IFileDialogVtbl struct {
_IModalWindowVtbl
SetFileTypes uintptr
SetFileTypeIndex uintptr
GetFileTypeIndex uintptr
Advise uintptr
Unadvise uintptr
SetOptions uintptr
GetOptions uintptr
SetDefaultFolder uintptr
SetFolder uintptr
GetFolder uintptr
GetCurrentSelection uintptr
SetFileName uintptr
GetFileName uintptr
SetTitle uintptr
SetOkButtonLabel uintptr
SetFileNameLabel uintptr
GetResult uintptr
AddPlace uintptr
SetDefaultExtension uintptr
Close uintptr
SetClientGuid uintptr
ClearClientData uintptr
SetFilter uintptr
}
type _IModalWindowVtbl struct {
_IUnknownVtbl
Show uintptr
}
type _IShellItemVtbl struct {
_IUnknownVtbl
BindToHandler uintptr
GetParent uintptr
GetDisplayName uintptr
GetAttributes uintptr
Compare uintptr
}
2020-01-09 20:46:53 -05:00
type _IShellItemArrayVtbl struct {
_IUnknownVtbl
BindToHandler uintptr
GetPropertyStore uintptr
GetPropertyDescriptionList uintptr
GetAttributes uintptr
GetCount uintptr
GetItemAt uintptr
EnumItems uintptr
}