-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shell: Add SHFileOperationW #62
base: master
Are you sure you want to change the base?
Conversation
Is there a corresponding lxn/walk commit for this? IIRC, this is a somewhat tricky interface to use because it requires creating double-null-terminated strings. |
lxn/walk doesn't use this. However, I have implemented an example of this in the "use syscall mechanism on windows" linked above: func getShortPathName(path string) (string, error) {
p, err := syscall.UTF16FromString(path)
if err != nil {
return "", err
}
b := p // GetShortPathName says we can reuse buffer
n := uint32(len(b))
for {
n, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
if err != nil {
return "", err
}
if n <= uint32(len(b)) {
return syscall.UTF16ToString(b[:n]), nil
}
b = make([]uint16, n)
}
}
...
filePath, err := getShortPathName(filePath)
if err != nil {
return "", err
}
fileop := win.SHFILEOPSTRUCT{
Hwnd: win.HWND(0),
WFunc: win.FO_DELETE,
PFrom: syscall.StringToUTF16Ptr(filePath),
PTo: nil,
FFlags: win.FOF_ALLOWUNDO | win.FOF_NOCONFIRMATION | win.FOF_NOERRORUI | win.FOF_SILENT,
FAnyOperationsAborted: win.BOOL(0),
HNameMappings: 0,
LpszProgressTitle: syscall.StringToUTF16Ptr(""),
}
result := win.SHFileOperation(&fileop)
if result != 0 {
return "", errors.New("File operation returned code " + strconv.Itoa(int(result)))
} |
Why are you passing the short filename? Also, you're not doing the double null termination like msdn says you must. Perhaps you're just relying on the same-buffer-usage of your getShortFilePathName call? And then hoping the remaining bytes after the first null aren't real paths and somewhere in memory is two nulls? |
You're correct that my initial implementation was less than optimal, but it passed the tests for random paths on my computer, so I assumed that it was good enough. You can see my revised implementation below. But regardless, the interface here is the same. Are you suggesting that changes be made to the lxn/win interface, or that an example is included in the comments? The reason that I proposed this here is that I try to share code across the entire ecosystem, and lxn/win seems to be the place to put windows apis. func DoubleNullTerminatedUTF16PtrFromString(s string) *uint16 {
return &(utf16.Encode([]rune(s + "\x00\x00"))[0])
}
func MoveToTrash(filePath string) (string, error) {
if result := win.SHFileOperation(&win.SHFILEOPSTRUCT{
Hwnd: win.HWND(0),
WFunc: win.FO_DELETE,
PFrom: DoubleNullTerminatedUTF16PtrFromString(filePath),
PTo: nil,
FFlags: win.FOF_ALLOWUNDO | win.FOF_NOCONFIRMATION | win.FOF_NOERRORUI | win.FOF_SILENT,
FAnyOperationsAborted: win.BOOL(0),
HNameMappings: 0,
LpszProgressTitle: DoubleNullTerminatedUTF16PtrFromString(""), // Note: double-null termination not required
}); result != 0 {
return "", errors.New("File operation returned code " + strconv.Itoa(int(result)))
}
return "", nil
} |
@lxn is there a way that I could get this merged? |
Please add yourself to the AUTHORS file. |
@lxn Done. |
@lxn Is there further action that you require? |
Adds SHFileOperationW, which allows programs to use the windows recycle bin.