1// Copyright 2016 Keybase Inc. All rights reserved. 2// Use of this source code is governed by a BSD 3// license that can be found in the LICENSE file. 4 5// +build windows 6 7package libdokan 8 9import ( 10 "reflect" 11 "strings" 12 "syscall" 13 "unicode/utf16" 14 "unicode/utf8" 15 "unsafe" 16 17 "golang.org/x/sys/windows" 18) 19 20func isNewFolderName(name string) bool { 21 return name == newFolderName || name == newFolderAltName 22} 23 24var newFolderName, newFolderNameErr = getNewFolderName() 25var newFolderAltName = altCase(newFolderName) 26 27func altCase(s string) string { 28 _, idx := utf8.DecodeRuneInString(s) 29 return s[:idx] + strings.ToLower(s[idx:]) 30} 31 32// The resourse IDs are not considered stable by Microsoft. 33// Luckily for us this happens to be the same for our 34// targeted Windows versions where kbfsdokan works. 35// Tested for Windows 7, 8, 8.1 and 10. 36// TODO test this for new Windows versions! 37const newFolderWindws7to10ResourceID = 16888 38 39func getNewFolderName() (string, error) { 40 var u16ptr *uint16 41 // The following id is valid for at least Windows 7, 8.1 and 10. 42 res, _, err := syscall.Syscall6(procLoadStringW.Addr(), 4, shell32DLL.Handle(), 43 newFolderWindws7to10ResourceID, uintptr(unsafe.Pointer(&u16ptr)), 0, 0, 0) 44 if res == 0 { 45 return "New Folder", err 46 } 47 return lpcwstrToString(u16ptr), nil 48} 49 50var ( 51 shell32DLL = windows.NewLazySystemDLL("shell32.dll") 52 user32DLL = windows.NewLazySystemDLL("user32.dll") 53 procLoadStringW = user32DLL.NewProc("LoadStringW") 54) 55 56// lpcwstrToString converts a nul-terminated Windows wide string to a Go string, 57func lpcwstrToString(ptr *uint16) string { 58 if ptr == nil { 59 return "" 60 } 61 var len = 0 62 for tmp := ptr; *tmp != 0; tmp = (*uint16)(unsafe.Pointer((uintptr(unsafe.Pointer(tmp)) + 2))) { 63 len++ 64 } 65 raw := ptrUcs2Slice(ptr, len) 66 return string(utf16.Decode(raw)) 67} 68 69// ptrUcs2Slice takes a C Windows wide string and length in UCS2 70// and returns it aliased as a uint16 slice. 71func ptrUcs2Slice(ptr *uint16, lenUcs2 int) []uint16 { 72 return *(*[]uint16)(unsafe.Pointer(&reflect.SliceHeader{ 73 Data: uintptr(unsafe.Pointer(ptr)), 74 Len: lenUcs2, 75 Cap: lenUcs2})) 76} 77