github.com/AlpineAIO/wails/v2@v2.0.0-beta.32.0.20240505041856-1047a8fa5fef/internal/go-common-file-dialog/cfd/iShellItem.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package cfd
     5  
     6  import (
     7  	"github.com/go-ole/go-ole"
     8  	"syscall"
     9  	"unsafe"
    10  )
    11  
    12  var (
    13  	procSHCreateItemFromParsingName = syscall.NewLazyDLL("Shell32.dll").NewProc("SHCreateItemFromParsingName")
    14  	iidShellItem                    = ole.NewGUID("43826d1e-e718-42ee-bc55-a1e261c37bfe")
    15  )
    16  
    17  type iShellItem struct {
    18  	vtbl *iShellItemVtbl
    19  }
    20  
    21  type iShellItemVtbl struct {
    22  	iUnknownVtbl
    23  	BindToHandler  uintptr
    24  	GetParent      uintptr
    25  	GetDisplayName uintptr // func (sigdnName SIGDN, ppszName *LPWSTR) HRESULT
    26  	GetAttributes  uintptr
    27  	Compare        uintptr
    28  }
    29  
    30  func newIShellItem(path string) (*iShellItem, error) {
    31  	var shellItem *iShellItem
    32  	pathPtr := ole.SysAllocString(path)
    33  	ret, _, _ := procSHCreateItemFromParsingName.Call(
    34  		uintptr(unsafe.Pointer(pathPtr)),
    35  		0,
    36  		uintptr(unsafe.Pointer(iidShellItem)),
    37  		uintptr(unsafe.Pointer(&shellItem)))
    38  	return shellItem, hresultToError(ret)
    39  }
    40  
    41  func (vtbl *iShellItemVtbl) getDisplayName(objPtr unsafe.Pointer) (string, error) {
    42  	var ptr *uint16
    43  	ret, _, _ := syscall.Syscall(vtbl.GetDisplayName,
    44  		2,
    45  		uintptr(objPtr),
    46  		0x80058000, // SIGDN_FILESYSPATH
    47  		uintptr(unsafe.Pointer(&ptr)))
    48  	if err := hresultToError(ret); err != nil {
    49  		return "", err
    50  	}
    51  	defer ole.CoTaskMemFree(uintptr(unsafe.Pointer(ptr)))
    52  	return ole.LpOleStrToString(ptr), nil
    53  }