| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- package wastebasket
- import (
- "fmt"
- "os"
- "unsafe"
- "golang.org/x/sys/windows"
- )
- var (
- shell32DLL = windows.NewLazyDLL("shell32.dll")
- shFileOperationW = shell32DLL.NewProc("SHFileOperationW")
- shEmptyRecycleBinW = shell32DLL.NewProc("SHEmptyRecycleBinW")
- )
- /*
- #define FO_DELETE 0x0003
- #define FOF_SILENT 0x0004
- #define FOF_NOCONFIRMATION 0x0010
- #define FOF_ALLOWUNDO 0x0040
- #define FOF_NOCONFIRMMKDIR 0x0200
- #define FOF_NOERRORUI 0x0400
- #define FOF_NO_UI (FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR)
- typedef struct _SHFILEOPSTRUCTW {
- HWND hwnd;
- UINT wFunc;
- PCZZWSTR pFrom;
- PCZZWSTR pTo;
- FILEOP_FLAGS fFlags;
- BOOL fAnyOperationsAborted;
- LPVOID hNameMappings;
- PCWSTR lpszProgressTitle;
- } SHFILEOPSTRUCTW, *LPSHFILEOPSTRUCTW;
- */
- const (
- FO_DELETE = 0x0003
- FOF_SILENT = 0x0004
- FOF_NOCONFIRMATION = 0x0010
- FOF_ALLOWUNDO = 0x0040
- FOF_NOCONFIRMMKDIR = 0x0200
- FOF_NOERRORUI = 0x0400
- FOF_NO_UI = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR
- )
- type SHFileOpStructW struct {
- // Irrelevant, as its for UI related things
- hwnd windows.HWND
- wFunc uint32
- pFrom *uint16
- // This isn't necessary as it is only needed for copy / move actions.
- pTo *uint16
- fFlags uint16
- // FIXME Why isn't this relevant?
- fAnyOperationsAborted int32
- // Irrelevant, as its for move operations
- hNameMappings uintptr
- // Irrelevant, as its for UI related things
- lpszProgressTitle *uint16
- }
- // Trash moves a file or folder including its content into the systems trashbin.
- func Trash(paths ...string) error {
- existingPaths := make([]string, 0, len(paths))
- for _, path := range paths {
- // The API will return error code "2 - Operation completed successfully"
- // when attempting to delete a non-existent file.
- if _, err := os.Stat(path); os.IsNotExist(err) {
- continue
- } else if err != nil {
- return err
- }
- existingPaths = append(existingPaths, path)
- }
- filesParameter, err := makeDoubleNullTerminatedLpstr(existingPaths...)
- if err != nil {
- return fmt.Errorf("error creating utf16ptr for passed path: %w", err)
- }
- ret, _, err := shFileOperationW.Call(uintptr(unsafe.Pointer(&SHFileOpStructW{
- hwnd: windows.HWND(0),
- wFunc: FO_DELETE,
- pFrom: filesParameter,
- pTo: nil,
- fFlags: FOF_NO_UI | FOF_ALLOWUNDO,
- fAnyOperationsAborted: 0,
- hNameMappings: 0,
- lpszProgressTitle: nil,
- })))
- if ret != 0 {
- return fmt.Errorf("windows error: %w", err)
- }
- return nil
- }
- func makeDoubleNullTerminatedLpstr(items ...string) (*uint16, error) {
- chars := []uint16{}
- for _, s := range items {
- converted, err := windows.UTF16FromString(s)
- if err != nil {
- return nil, err
- }
- chars = append(chars, converted...)
- }
- chars = append(chars, 0)
- return &chars[0], nil
- }
- const (
- SHERB_NOCONFIRMATION = 1
- SHERB_NOPROGRESSUI = 2
- SHERB_NOSOUND = 4
- )
- // Empty clears the platforms trashbin.
- func Empty() error {
- flags := SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND
- ret, _, err := shEmptyRecycleBinW.Call(uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(nil)), uintptr(flags))
- if ret != 0 {
- // Weird edge case, where windows reports that it couldnt load the DLL
- // if the trash bin is empty.
- if err.(windows.Errno) == 126 {
- return nil
- }
- return fmt.Errorf("windows error: %w", err)
- }
- return nil
- }
|