mirror of
https://github.com/golang/go
synced 2024-11-25 06:57:58 -07:00
os: use GetFileAttributesEx to implement Stat on windows
Fixes #2129. R=rsc CC=golang-dev https://golang.org/cl/4934049
This commit is contained in:
parent
919cb2ec7c
commit
37f390aa20
@ -21,39 +21,6 @@ func epipecheck(file *File, e int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns a FileInfo structure describing the named file and an error, if any.
|
|
||||||
// If name names a valid symbolic link, the returned FileInfo describes
|
|
||||||
// the file pointed at by the link and has fi.FollowedSymlink set to true.
|
|
||||||
// If name names an invalid symbolic link, the returned FileInfo describes
|
|
||||||
// the link itself and has fi.FollowedSymlink set to false.
|
|
||||||
func Stat(name string) (fi *FileInfo, err Error) {
|
|
||||||
var lstat, stat syscall.Stat_t
|
|
||||||
e := syscall.Lstat(name, &lstat)
|
|
||||||
if iserror(e) {
|
|
||||||
return nil, &PathError{"stat", name, Errno(e)}
|
|
||||||
}
|
|
||||||
statp := &lstat
|
|
||||||
if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
|
|
||||||
e := syscall.Stat(name, &stat)
|
|
||||||
if !iserror(e) {
|
|
||||||
statp = &stat
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lstat returns the FileInfo structure describing the named file and an
|
|
||||||
// error, if any. If the file is a symbolic link, the returned FileInfo
|
|
||||||
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
|
||||||
func Lstat(name string) (fi *FileInfo, err Error) {
|
|
||||||
var stat syscall.Stat_t
|
|
||||||
e := syscall.Lstat(name, &stat)
|
|
||||||
if iserror(e) {
|
|
||||||
return nil, &PathError{"lstat", name, Errno(e)}
|
|
||||||
}
|
|
||||||
return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the named file or directory.
|
// Remove removes the named file or directory.
|
||||||
func Remove(name string) Error {
|
func Remove(name string) Error {
|
||||||
// System call interface forces us to know
|
// System call interface forces us to know
|
||||||
|
@ -94,6 +94,39 @@ func (file *File) Stat() (fi *FileInfo, err Error) {
|
|||||||
return fileInfoFromStat(file.name, new(FileInfo), &stat, &stat), nil
|
return fileInfoFromStat(file.name, new(FileInfo), &stat, &stat), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stat returns a FileInfo structure describing the named file and an error, if any.
|
||||||
|
// If name names a valid symbolic link, the returned FileInfo describes
|
||||||
|
// the file pointed at by the link and has fi.FollowedSymlink set to true.
|
||||||
|
// If name names an invalid symbolic link, the returned FileInfo describes
|
||||||
|
// the link itself and has fi.FollowedSymlink set to false.
|
||||||
|
func Stat(name string) (fi *FileInfo, err Error) {
|
||||||
|
var lstat, stat syscall.Stat_t
|
||||||
|
e := syscall.Lstat(name, &lstat)
|
||||||
|
if iserror(e) {
|
||||||
|
return nil, &PathError{"stat", name, Errno(e)}
|
||||||
|
}
|
||||||
|
statp := &lstat
|
||||||
|
if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
|
||||||
|
e := syscall.Stat(name, &stat)
|
||||||
|
if !iserror(e) {
|
||||||
|
statp = &stat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lstat returns the FileInfo structure describing the named file and an
|
||||||
|
// error, if any. If the file is a symbolic link, the returned FileInfo
|
||||||
|
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
||||||
|
func Lstat(name string) (fi *FileInfo, err Error) {
|
||||||
|
var stat syscall.Stat_t
|
||||||
|
e := syscall.Lstat(name, &stat)
|
||||||
|
if iserror(e) {
|
||||||
|
return nil, &PathError{"lstat", name, Errno(e)}
|
||||||
|
}
|
||||||
|
return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Readdir reads the contents of the directory associated with file and
|
// Readdir reads the contents of the directory associated with file and
|
||||||
// returns an array of up to n FileInfo structures, as would be returned
|
// returns an array of up to n FileInfo structures, as would be returned
|
||||||
// by Lstat, in directory order. Subsequent calls on the same file will yield
|
// by Lstat, in directory order. Subsequent calls on the same file will yield
|
||||||
|
@ -39,8 +39,8 @@ func NewFile(fd syscall.Handle, name string) *File {
|
|||||||
|
|
||||||
// Auxiliary information if the File describes a directory
|
// Auxiliary information if the File describes a directory
|
||||||
type dirInfo struct {
|
type dirInfo struct {
|
||||||
stat syscall.Stat_t
|
data syscall.Win32finddata
|
||||||
usefirststat bool
|
needdata bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const DevNull = "NUL"
|
const DevNull = "NUL"
|
||||||
@ -64,12 +64,11 @@ func openFile(name string, flag int, perm uint32) (file *File, err Error) {
|
|||||||
|
|
||||||
func openDir(name string) (file *File, err Error) {
|
func openDir(name string) (file *File, err Error) {
|
||||||
d := new(dirInfo)
|
d := new(dirInfo)
|
||||||
r, e := syscall.FindFirstFile(syscall.StringToUTF16Ptr(name+"\\*"), &d.stat.Windata)
|
r, e := syscall.FindFirstFile(syscall.StringToUTF16Ptr(name+`\*`), &d.data)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, &PathError{"open", name, Errno(e)}
|
return nil, &PathError{"open", name, Errno(e)}
|
||||||
}
|
}
|
||||||
f := NewFile(r, name)
|
f := NewFile(r, name)
|
||||||
d.usefirststat = true
|
|
||||||
f.dirinfo = d
|
f.dirinfo = d
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
@ -128,28 +127,6 @@ func (file *File) Close() Error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (file *File) statFile(name string) (fi *FileInfo, err Error) {
|
|
||||||
var stat syscall.ByHandleFileInformation
|
|
||||||
e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &stat)
|
|
||||||
if e != 0 {
|
|
||||||
return nil, &PathError{"stat", file.name, Errno(e)}
|
|
||||||
}
|
|
||||||
return fileInfoFromByHandleInfo(new(FileInfo), file.name, &stat), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stat returns the FileInfo structure describing file.
|
|
||||||
// It returns the FileInfo and an error, if any.
|
|
||||||
func (file *File) Stat() (fi *FileInfo, err Error) {
|
|
||||||
if file == nil || file.fd < 0 {
|
|
||||||
return nil, EINVAL
|
|
||||||
}
|
|
||||||
if file.isdir() {
|
|
||||||
// I don't know any better way to do that for directory
|
|
||||||
return Stat(file.name)
|
|
||||||
}
|
|
||||||
return file.statFile(file.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Readdir reads the contents of the directory associated with file and
|
// Readdir reads the contents of the directory associated with file and
|
||||||
// returns an array of up to n FileInfo structures, as would be returned
|
// returns an array of up to n FileInfo structures, as would be returned
|
||||||
// by Lstat, in directory order. Subsequent calls on the same file will yield
|
// by Lstat, in directory order. Subsequent calls on the same file will yield
|
||||||
@ -172,7 +149,6 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
|
|||||||
if !file.isdir() {
|
if !file.isdir() {
|
||||||
return nil, &PathError{"Readdir", file.name, ENOTDIR}
|
return nil, &PathError{"Readdir", file.name, ENOTDIR}
|
||||||
}
|
}
|
||||||
di := file.dirinfo
|
|
||||||
wantAll := n <= 0
|
wantAll := n <= 0
|
||||||
size := n
|
size := n
|
||||||
if wantAll {
|
if wantAll {
|
||||||
@ -180,11 +156,10 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
|
|||||||
size = 100
|
size = 100
|
||||||
}
|
}
|
||||||
fi = make([]FileInfo, 0, size) // Empty with room to grow.
|
fi = make([]FileInfo, 0, size) // Empty with room to grow.
|
||||||
|
d := &file.dirinfo.data
|
||||||
for n != 0 {
|
for n != 0 {
|
||||||
if di.usefirststat {
|
if file.dirinfo.needdata {
|
||||||
di.usefirststat = false
|
e := syscall.FindNextFile(syscall.Handle(file.fd), d)
|
||||||
} else {
|
|
||||||
e := syscall.FindNextFile(syscall.Handle(file.fd), &di.stat.Windata)
|
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
if e == syscall.ERROR_NO_MORE_FILES {
|
if e == syscall.ERROR_NO_MORE_FILES {
|
||||||
break
|
break
|
||||||
@ -198,7 +173,8 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var f FileInfo
|
var f FileInfo
|
||||||
fileInfoFromWin32finddata(&f, &di.stat.Windata)
|
setFileInfo(&f, string(syscall.UTF16ToString(d.FileName[0:])), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime)
|
||||||
|
file.dirinfo.needdata = true
|
||||||
if f.Name == "." || f.Name == ".." { // Useless names
|
if f.Name == "." || f.Name == ".." { // Useless names
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,76 @@
|
|||||||
|
|
||||||
package os
|
package os
|
||||||
|
|
||||||
import "syscall"
|
import (
|
||||||
|
"unsafe"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
func fileInfoFromStat(name string, fi *FileInfo, lstat, stat *syscall.Stat_t) *FileInfo {
|
// Stat returns the FileInfo structure describing file.
|
||||||
return fileInfoFromWin32finddata(fi, &stat.Windata)
|
// It returns the FileInfo and an error, if any.
|
||||||
|
func (file *File) Stat() (fi *FileInfo, err Error) {
|
||||||
|
if file == nil || file.fd < 0 {
|
||||||
|
return nil, EINVAL
|
||||||
|
}
|
||||||
|
if file.isdir() {
|
||||||
|
// I don't know any better way to do that for directory
|
||||||
|
return Stat(file.name)
|
||||||
|
}
|
||||||
|
var d syscall.ByHandleFileInformation
|
||||||
|
e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &d)
|
||||||
|
if e != 0 {
|
||||||
|
return nil, &PathError{"GetFileInformationByHandle", file.name, Errno(e)}
|
||||||
|
}
|
||||||
|
return setFileInfo(new(FileInfo), basename(file.name), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileInfoFromWin32finddata(fi *FileInfo, d *syscall.Win32finddata) *FileInfo {
|
// Stat returns a FileInfo structure describing the named file and an error, if any.
|
||||||
return setFileInfo(fi, string(syscall.UTF16ToString(d.FileName[0:])), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime)
|
// If name names a valid symbolic link, the returned FileInfo describes
|
||||||
|
// the file pointed at by the link and has fi.FollowedSymlink set to true.
|
||||||
|
// If name names an invalid symbolic link, the returned FileInfo describes
|
||||||
|
// the link itself and has fi.FollowedSymlink set to false.
|
||||||
|
func Stat(name string) (fi *FileInfo, err Error) {
|
||||||
|
if len(name) == 0 {
|
||||||
|
return nil, &PathError{"Stat", name, Errno(syscall.ERROR_PATH_NOT_FOUND)}
|
||||||
|
}
|
||||||
|
var d syscall.Win32FileAttributeData
|
||||||
|
e := syscall.GetFileAttributesEx(syscall.StringToUTF16Ptr(name), syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&d)))
|
||||||
|
if e != 0 {
|
||||||
|
return nil, &PathError{"GetFileAttributesEx", name, Errno(e)}
|
||||||
|
}
|
||||||
|
return setFileInfo(new(FileInfo), basename(name), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileInfoFromByHandleInfo(fi *FileInfo, name string, d *syscall.ByHandleFileInformation) *FileInfo {
|
// Lstat returns the FileInfo structure describing the named file and an
|
||||||
for i := len(name) - 1; i >= 0; i-- {
|
// error, if any. If the file is a symbolic link, the returned FileInfo
|
||||||
|
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
||||||
|
func Lstat(name string) (fi *FileInfo, err Error) {
|
||||||
|
// No links on Windows
|
||||||
|
return Stat(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// basename removes trailing slashes and the leading
|
||||||
|
// directory name and drive letter from path name.
|
||||||
|
func basename(name string) string {
|
||||||
|
// Remove drive letter
|
||||||
|
if len(name) == 2 && name[1] == ':' {
|
||||||
|
name = "."
|
||||||
|
} else if len(name) > 2 && name[1] == ':' {
|
||||||
|
name = name[2:]
|
||||||
|
}
|
||||||
|
i := len(name) - 1
|
||||||
|
// Remove trailing slashes
|
||||||
|
for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i-- {
|
||||||
|
name = name[:i]
|
||||||
|
}
|
||||||
|
// Remove leading directory name
|
||||||
|
for i--; i >= 0; i-- {
|
||||||
if name[i] == '/' || name[i] == '\\' {
|
if name[i] == '/' || name[i] == '\\' {
|
||||||
name = name[i+1:]
|
name = name[i+1:]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return setFileInfo(fi, name, d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime)
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFileInfo(fi *FileInfo, name string, fa, sizehi, sizelo uint32, ctime, atime, wtime syscall.Filetime) *FileInfo {
|
func setFileInfo(fi *FileInfo, name string, fa, sizehi, sizelo uint32, ctime, atime, wtime syscall.Filetime) *FileInfo {
|
||||||
|
@ -207,6 +207,7 @@ func NewCallback(fn interface{}) uintptr
|
|||||||
//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (errno int)
|
//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (errno int)
|
||||||
//sys GetFileAttributes(name *uint16) (attrs uint32, errno int) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
|
//sys GetFileAttributes(name *uint16) (attrs uint32, errno int) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
|
||||||
//sys SetFileAttributes(name *uint16, attrs uint32) (errno int) = kernel32.SetFileAttributesW
|
//sys SetFileAttributes(name *uint16, attrs uint32) (errno int) = kernel32.SetFileAttributesW
|
||||||
|
//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (errno int) = kernel32.GetFileAttributesExW
|
||||||
//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
|
//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
|
||||||
//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, errno int) [failretval==nil] = shell32.CommandLineToArgvW
|
//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, errno int) [failretval==nil] = shell32.CommandLineToArgvW
|
||||||
//sys LocalFree(hmem Handle) (handle Handle, errno int) [failretval!=0]
|
//sys LocalFree(hmem Handle) (handle Handle, errno int) [failretval!=0]
|
||||||
@ -354,39 +355,6 @@ func getStdHandle(h int) (fd Handle) {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func Stat(path string, stat *Stat_t) (errno int) {
|
|
||||||
if len(path) == 0 {
|
|
||||||
return ERROR_PATH_NOT_FOUND
|
|
||||||
}
|
|
||||||
// Remove trailing slash.
|
|
||||||
if path[len(path)-1] == '/' || path[len(path)-1] == '\\' {
|
|
||||||
// Check if we're given root directory ("\" or "c:\").
|
|
||||||
if len(path) == 1 || (len(path) == 3 && path[1] == ':') {
|
|
||||||
// TODO(brainman): Perhaps should fetch other fields, not just FileAttributes.
|
|
||||||
stat.Windata = Win32finddata{}
|
|
||||||
a, e := GetFileAttributes(StringToUTF16Ptr(path))
|
|
||||||
if e != 0 {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
stat.Windata.FileAttributes = a
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
path = path[:len(path)-1]
|
|
||||||
}
|
|
||||||
h, e := FindFirstFile(StringToUTF16Ptr(path), &stat.Windata)
|
|
||||||
if e != 0 {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
defer FindClose(h)
|
|
||||||
stat.Mode = 0
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func Lstat(path string, stat *Stat_t) (errno int) {
|
|
||||||
// no links on windows, just call Stat
|
|
||||||
return Stat(path, stat)
|
|
||||||
}
|
|
||||||
|
|
||||||
const ImplementsGetwd = true
|
const ImplementsGetwd = true
|
||||||
|
|
||||||
func Getwd() (wd string, errno int) {
|
func Getwd() (wd string, errno int) {
|
||||||
|
@ -66,6 +66,7 @@ var (
|
|||||||
procSetFileTime = modkernel32.NewProc("SetFileTime")
|
procSetFileTime = modkernel32.NewProc("SetFileTime")
|
||||||
procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW")
|
procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW")
|
||||||
procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW")
|
procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW")
|
||||||
|
procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW")
|
||||||
procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
|
procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
|
||||||
procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW")
|
procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW")
|
||||||
procLocalFree = modkernel32.NewProc("LocalFree")
|
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||||
@ -142,7 +143,8 @@ func FreeLibrary(handle Handle) (errno int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetProcAddress(module Handle, procname string) (proc uintptr, errno int) {
|
func GetProcAddress(module Handle, procname string) (proc uintptr, errno int) {
|
||||||
proc, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
|
r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
|
||||||
|
proc = uintptr(r0)
|
||||||
if proc == 0 {
|
if proc == 0 {
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
errno = int(e1)
|
errno = int(e1)
|
||||||
@ -847,6 +849,20 @@ func SetFileAttributes(name *uint16, attrs uint32) (errno int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetFileAttributesEx(name *uint16, level uint32, info *byte) (errno int) {
|
||||||
|
r1, _, e1 := Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info)))
|
||||||
|
if int(r1) == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
errno = int(e1)
|
||||||
|
} else {
|
||||||
|
errno = EINVAL
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errno = 0
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func GetCommandLine() (cmd *uint16) {
|
func GetCommandLine() (cmd *uint16) {
|
||||||
r0, _, _ := Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0)
|
r0, _, _ := Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0)
|
||||||
cmd = (*uint16)(unsafe.Pointer(r0))
|
cmd = (*uint16)(unsafe.Pointer(r0))
|
||||||
|
@ -66,6 +66,7 @@ var (
|
|||||||
procSetFileTime = modkernel32.NewProc("SetFileTime")
|
procSetFileTime = modkernel32.NewProc("SetFileTime")
|
||||||
procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW")
|
procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW")
|
||||||
procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW")
|
procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW")
|
||||||
|
procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW")
|
||||||
procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
|
procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
|
||||||
procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW")
|
procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW")
|
||||||
procLocalFree = modkernel32.NewProc("LocalFree")
|
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||||
@ -142,7 +143,8 @@ func FreeLibrary(handle Handle) (errno int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetProcAddress(module Handle, procname string) (proc uintptr, errno int) {
|
func GetProcAddress(module Handle, procname string) (proc uintptr, errno int) {
|
||||||
proc, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
|
r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
|
||||||
|
proc = uintptr(r0)
|
||||||
if proc == 0 {
|
if proc == 0 {
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
errno = int(e1)
|
errno = int(e1)
|
||||||
@ -847,6 +849,20 @@ func SetFileAttributes(name *uint16, attrs uint32) (errno int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetFileAttributesEx(name *uint16, level uint32, info *byte) (errno int) {
|
||||||
|
r1, _, e1 := Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info)))
|
||||||
|
if int(r1) == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
errno = int(e1)
|
||||||
|
} else {
|
||||||
|
errno = EINVAL
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errno = 0
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func GetCommandLine() (cmd *uint16) {
|
func GetCommandLine() (cmd *uint16) {
|
||||||
r0, _, _ := Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0)
|
r0, _, _ := Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0)
|
||||||
cmd = (*uint16)(unsafe.Pointer(r0))
|
cmd = (*uint16)(unsafe.Pointer(r0))
|
||||||
|
@ -244,6 +244,20 @@ type ByHandleFileInformation struct {
|
|||||||
FileIndexLow uint32
|
FileIndexLow uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
GetFileExInfoStandard = 0
|
||||||
|
GetFileExMaxInfoLevel = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
type Win32FileAttributeData struct {
|
||||||
|
FileAttributes uint32
|
||||||
|
CreationTime Filetime
|
||||||
|
LastAccessTime Filetime
|
||||||
|
LastWriteTime Filetime
|
||||||
|
FileSizeHigh uint32
|
||||||
|
FileSizeLow uint32
|
||||||
|
}
|
||||||
|
|
||||||
// ShowWindow constants
|
// ShowWindow constants
|
||||||
const (
|
const (
|
||||||
// winuser.h
|
// winuser.h
|
||||||
@ -291,12 +305,6 @@ type ProcessInformation struct {
|
|||||||
ThreadId uint32
|
ThreadId uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invented values to support what package os expects.
|
|
||||||
type Stat_t struct {
|
|
||||||
Windata Win32finddata
|
|
||||||
Mode uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type Systemtime struct {
|
type Systemtime struct {
|
||||||
Year uint16
|
Year uint16
|
||||||
Month uint16
|
Month uint16
|
||||||
|
Loading…
Reference in New Issue
Block a user