github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/windows/winc/w32/shell32.go (about)

     1  //go:build windows
     2  
     3  /*
     4   * Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
     5   * Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
     6   */
     7  package w32
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"syscall"
    13  	"unsafe"
    14  )
    15  
    16  type CSIDL uint32
    17  
    18  const (
    19  	CSIDL_DESKTOP                 = 0x00
    20  	CSIDL_INTERNET                = 0x01
    21  	CSIDL_PROGRAMS                = 0x02
    22  	CSIDL_CONTROLS                = 0x03
    23  	CSIDL_PRINTERS                = 0x04
    24  	CSIDL_PERSONAL                = 0x05
    25  	CSIDL_FAVORITES               = 0x06
    26  	CSIDL_STARTUP                 = 0x07
    27  	CSIDL_RECENT                  = 0x08
    28  	CSIDL_SENDTO                  = 0x09
    29  	CSIDL_BITBUCKET               = 0x0A
    30  	CSIDL_STARTMENU               = 0x0B
    31  	CSIDL_MYDOCUMENTS             = 0x0C
    32  	CSIDL_MYMUSIC                 = 0x0D
    33  	CSIDL_MYVIDEO                 = 0x0E
    34  	CSIDL_DESKTOPDIRECTORY        = 0x10
    35  	CSIDL_DRIVES                  = 0x11
    36  	CSIDL_NETWORK                 = 0x12
    37  	CSIDL_NETHOOD                 = 0x13
    38  	CSIDL_FONTS                   = 0x14
    39  	CSIDL_TEMPLATES               = 0x15
    40  	CSIDL_COMMON_STARTMENU        = 0x16
    41  	CSIDL_COMMON_PROGRAMS         = 0x17
    42  	CSIDL_COMMON_STARTUP          = 0x18
    43  	CSIDL_COMMON_DESKTOPDIRECTORY = 0x19
    44  	CSIDL_APPDATA                 = 0x1A
    45  	CSIDL_PRINTHOOD               = 0x1B
    46  	CSIDL_LOCAL_APPDATA           = 0x1C
    47  	CSIDL_ALTSTARTUP              = 0x1D
    48  	CSIDL_COMMON_ALTSTARTUP       = 0x1E
    49  	CSIDL_COMMON_FAVORITES        = 0x1F
    50  	CSIDL_INTERNET_CACHE          = 0x20
    51  	CSIDL_COOKIES                 = 0x21
    52  	CSIDL_HISTORY                 = 0x22
    53  	CSIDL_COMMON_APPDATA          = 0x23
    54  	CSIDL_WINDOWS                 = 0x24
    55  	CSIDL_SYSTEM                  = 0x25
    56  	CSIDL_PROGRAM_FILES           = 0x26
    57  	CSIDL_MYPICTURES              = 0x27
    58  	CSIDL_PROFILE                 = 0x28
    59  	CSIDL_SYSTEMX86               = 0x29
    60  	CSIDL_PROGRAM_FILESX86        = 0x2A
    61  	CSIDL_PROGRAM_FILES_COMMON    = 0x2B
    62  	CSIDL_PROGRAM_FILES_COMMONX86 = 0x2C
    63  	CSIDL_COMMON_TEMPLATES        = 0x2D
    64  	CSIDL_COMMON_DOCUMENTS        = 0x2E
    65  	CSIDL_COMMON_ADMINTOOLS       = 0x2F
    66  	CSIDL_ADMINTOOLS              = 0x30
    67  	CSIDL_CONNECTIONS             = 0x31
    68  	CSIDL_COMMON_MUSIC            = 0x35
    69  	CSIDL_COMMON_PICTURES         = 0x36
    70  	CSIDL_COMMON_VIDEO            = 0x37
    71  	CSIDL_RESOURCES               = 0x38
    72  	CSIDL_RESOURCES_LOCALIZED     = 0x39
    73  	CSIDL_COMMON_OEM_LINKS        = 0x3A
    74  	CSIDL_CDBURN_AREA             = 0x3B
    75  	CSIDL_COMPUTERSNEARME         = 0x3D
    76  	CSIDL_FLAG_CREATE             = 0x8000
    77  	CSIDL_FLAG_DONT_VERIFY        = 0x4000
    78  	CSIDL_FLAG_NO_ALIAS           = 0x1000
    79  	CSIDL_FLAG_PER_USER_INIT      = 0x8000
    80  	CSIDL_FLAG_MASK               = 0xFF00
    81  )
    82  
    83  var (
    84  	modshell32 = syscall.NewLazyDLL("shell32.dll")
    85  
    86  	procSHBrowseForFolder    = modshell32.NewProc("SHBrowseForFolderW")
    87  	procSHGetPathFromIDList  = modshell32.NewProc("SHGetPathFromIDListW")
    88  	procDragAcceptFiles      = modshell32.NewProc("DragAcceptFiles")
    89  	procDragQueryFile        = modshell32.NewProc("DragQueryFileW")
    90  	procDragQueryPoint       = modshell32.NewProc("DragQueryPoint")
    91  	procDragFinish           = modshell32.NewProc("DragFinish")
    92  	procShellExecute         = modshell32.NewProc("ShellExecuteW")
    93  	procExtractIcon          = modshell32.NewProc("ExtractIconW")
    94  	procGetSpecialFolderPath = modshell32.NewProc("SHGetSpecialFolderPathW")
    95  )
    96  
    97  func SHBrowseForFolder(bi *BROWSEINFO) uintptr {
    98  	ret, _, _ := procSHBrowseForFolder.Call(uintptr(unsafe.Pointer(bi)))
    99  
   100  	return ret
   101  }
   102  
   103  func SHGetPathFromIDList(idl uintptr) string {
   104  	buf := make([]uint16, 1024)
   105  	procSHGetPathFromIDList.Call(
   106  		idl,
   107  		uintptr(unsafe.Pointer(&buf[0])))
   108  
   109  	return syscall.UTF16ToString(buf)
   110  }
   111  
   112  func DragAcceptFiles(hwnd HWND, accept bool) {
   113  	procDragAcceptFiles.Call(
   114  		uintptr(hwnd),
   115  		uintptr(BoolToBOOL(accept)))
   116  }
   117  
   118  func DragQueryFile(hDrop HDROP, iFile uint) (fileName string, fileCount uint) {
   119  	ret, _, _ := procDragQueryFile.Call(
   120  		uintptr(hDrop),
   121  		uintptr(iFile),
   122  		0,
   123  		0)
   124  
   125  	fileCount = uint(ret)
   126  
   127  	if iFile != 0xFFFFFFFF {
   128  		buf := make([]uint16, fileCount+1)
   129  
   130  		ret, _, _ := procDragQueryFile.Call(
   131  			uintptr(hDrop),
   132  			uintptr(iFile),
   133  			uintptr(unsafe.Pointer(&buf[0])),
   134  			uintptr(fileCount+1))
   135  
   136  		if ret == 0 {
   137  			panic("Invoke DragQueryFile error.")
   138  		}
   139  
   140  		fileName = syscall.UTF16ToString(buf)
   141  	}
   142  
   143  	return
   144  }
   145  
   146  func DragQueryPoint(hDrop HDROP) (x, y int, isClientArea bool) {
   147  	var pt POINT
   148  	ret, _, _ := procDragQueryPoint.Call(
   149  		uintptr(hDrop),
   150  		uintptr(unsafe.Pointer(&pt)))
   151  
   152  	return int(pt.X), int(pt.Y), (ret == 1)
   153  }
   154  
   155  func DragFinish(hDrop HDROP) {
   156  	procDragFinish.Call(uintptr(hDrop))
   157  }
   158  
   159  func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
   160  	var op, param, directory uintptr
   161  	if len(lpOperation) != 0 {
   162  		op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
   163  	}
   164  	if len(lpParameters) != 0 {
   165  		param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
   166  	}
   167  	if len(lpDirectory) != 0 {
   168  		directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
   169  	}
   170  
   171  	ret, _, _ := procShellExecute.Call(
   172  		uintptr(hwnd),
   173  		op,
   174  		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
   175  		param,
   176  		directory,
   177  		uintptr(nShowCmd))
   178  
   179  	errorMsg := ""
   180  	if ret != 0 && ret <= 32 {
   181  		switch int(ret) {
   182  		case ERROR_FILE_NOT_FOUND:
   183  			errorMsg = "The specified file was not found."
   184  		case ERROR_PATH_NOT_FOUND:
   185  			errorMsg = "The specified path was not found."
   186  		case ERROR_BAD_FORMAT:
   187  			errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)."
   188  		case SE_ERR_ACCESSDENIED:
   189  			errorMsg = "The operating system denied access to the specified file."
   190  		case SE_ERR_ASSOCINCOMPLETE:
   191  			errorMsg = "The file name association is incomplete or invalid."
   192  		case SE_ERR_DDEBUSY:
   193  			errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed."
   194  		case SE_ERR_DDEFAIL:
   195  			errorMsg = "The DDE transaction failed."
   196  		case SE_ERR_DDETIMEOUT:
   197  			errorMsg = "The DDE transaction could not be completed because the request timed out."
   198  		case SE_ERR_DLLNOTFOUND:
   199  			errorMsg = "The specified DLL was not found."
   200  		case SE_ERR_NOASSOC:
   201  			errorMsg = "There is no application associated with the given file name extension. This error will also be returned if you attempt to print a file that is not printable."
   202  		case SE_ERR_OOM:
   203  			errorMsg = "There was not enough memory to complete the operation."
   204  		case SE_ERR_SHARE:
   205  			errorMsg = "A sharing violation occurred."
   206  		default:
   207  			errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", ret)
   208  		}
   209  	} else {
   210  		return nil
   211  	}
   212  
   213  	return errors.New(errorMsg)
   214  }
   215  
   216  func ExtractIcon(lpszExeFileName string, nIconIndex int) HICON {
   217  	ret, _, _ := procExtractIcon.Call(
   218  		0,
   219  		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpszExeFileName))),
   220  		uintptr(nIconIndex))
   221  
   222  	return HICON(ret)
   223  }
   224  
   225  func SHGetSpecialFolderPath(hwndOwner HWND, lpszPath *uint16, csidl CSIDL, fCreate bool) bool {
   226  	ret, _, _ := procGetSpecialFolderPath.Call(
   227  		uintptr(hwndOwner),
   228  		uintptr(unsafe.Pointer(lpszPath)),
   229  		uintptr(csidl),
   230  		uintptr(BoolToBOOL(fCreate)),
   231  		0,
   232  		0)
   233  
   234  	return ret != 0
   235  }