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 }