我在win7-64位系统中调用dll时遇到了一些关于golang syscall的问题。

huangapple go评论137阅读模式
英文:

I have some trouble with golang syscall when calling dll in win7-64

问题

这是我的代码:

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

var (
    WinSCard, _                  = syscall.LoadLibrary("C:\\windows\\system32\\WinSCard.dll")
    procSCardListReaders, _      = syscall.GetProcAddress(WinSCard, "SCardListReaders")
    procSCardEstablishContext, _ = syscall.GetProcAddress(WinSCard, "SCardEstablishContext")
)

func abort(funcname string, err error) {
    panic(fmt.Sprintf("%s failed: %v", funcname, err))
}

func SCardEstablishContext(dwScope uint32, pvReserved1 *uint32, pvReserved2 *uint32, phContext uintptr) int32 {
    ret, _, callErr := syscall.Syscall6(uintptr(procSCardEstablishContext),
        4,
        uintptr(unsafe.Pointer(&dwScope)),
        uintptr(unsafe.Pointer(pvReserved1)),
        uintptr(unsafe.Pointer(pvReserved2)),
        phContext,
        0,
        0)
    if callErr != 0 {
        abort("Err:", callErr)
    }
    return int32(ret)
}

func main() {
    var Hwd uintptr
    defer syscall.FreeLibrary(WinSCard)
    rt := SCardEstablishContext(0, nil, nil, Hwd)
    fmt.Println(rt)
}

返回-2146435068表示0x80100004表示SCARD_E_INVALID_PARAMETER。一个或多个提供的参数无法正确解释。

函数SCardEstablishContext:

LONG WINAPI SCardEstablishContext(
    _In_   DWORD dwScope,
    _In_   LPCVOID pvReserved1,
    _In_   LPCVOID pvReserved2,
    _Out_  LPSCARDCONTEXT phContext
)

我的参数有什么问题?非常感谢!!

如何使用:

func SCardListReaders(hContext *syscall.Handle, mszGroups string, mszReaders *byte, pcchReaders *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(
	uintptr(procSCardListReaders),
	4,
	uintptr(unsafe.Pointer(hContext)),
	uintptr(unsafe.Pointer(syscall.StringBytePtr(mszGroups))),
	uintptr(unsafe.Pointer(mszReaders)),
	uintptr(unsafe.Pointer(pcchReaders)),
	0,
	0,
)
if r1 != 0 {
	if e1 != 0 {
		err = error(e1)
	} else {
		err = syscall.EINVAL
	}
}
return
}

var Groups string
var Readers byte
var pcchReaders uint32
er1 := SCardListReaders(&context, Groups, &Readers, &pcchReaders)
if er1 != nil {
	fmt.Println("SCardListReaders:", er1)
	return
}

返回:无效的参数

英文:

Here my code:

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

var (
    WinSCard, _                  = syscall.LoadLibrary("C:\\windows\\system32\\WinSCard.dll")
    procSCardListReaders, _      = syscall.GetProcAddress(WinSCard, "SCardListReaders")
    procSCardEstablishContext, _ = syscall.GetProcAddress(WinSCard, "SCardEstablishContext")
)

func abort(funcname string, err error) {
    panic(fmt.Sprintf("%s failed: %v", funcname, err))
}

func SCardEstablishContext(dwScope uint32, pvReserved1 *uint32, pvReserved2 *uint32, phContext uintptr) int32 {
    ret, _, callErr := syscall.Syscall6(uintptr(procSCardEstablishContext),
        4,
        uintptr(unsafe.Pointer(&dwScope)),
        uintptr(unsafe.Pointer(pvReserved1)),
        uintptr(unsafe.Pointer(pvReserved2)),
        phContext,
        0,
        0)
    if callErr != 0 {
        abort("Err:", callErr)
    }
    return int32(ret)
}

func main() {
    var Hwd uintptr
    defer syscall.FreeLibrary(WinSCard)
    rt := SCardEstablishContext(0, nil, nil, Hwd)
    fmt.Println(rt)
}

Return -2146435068 means 0x80100004 means SCARD_E_INVALID_PARAMETER. One or more of the supplied parameters could not be properly interpreted.

The func SCardEstablishContext:

LONG WINAPI SCardEstablishContext(
    _In_   DWORD dwScope,
    _In_   LPCVOID pvReserved1,
    _In_   LPCVOID pvReserved2,
    _Out_  LPSCARDCONTEXT phContext
)

What's wrong with my parameters? Thx a lot!!

How about

func SCardListReaders(hContext *syscall.Handle, mszGroups string, mszReaders *byte, pcchReaders *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(
	uintptr(procSCardListReaders),
	4,
	uintptr(unsafe.Pointer(hContext)),
	uintptr(unsafe.Pointer(syscall.StringBytePtr(mszGroups))),
	uintptr(unsafe.Pointer(mszReaders)),
	uintptr(unsafe.Pointer(pcchReaders)),
	0,
	0,
)
if r1 != 0 {
	if e1 != 0 {
		err = error(e1)
	} else {
		err = syscall.EINVAL
	}
}
return
}

var Groups string
var Readers byte
var pcchReaders uint32
er1 := SCardListReaders(&context, Groups, &Readers, &pcchReaders)
if er1 != nil {
	fmt.Println("SCardListReaders:", er1)
	return
}

return: invalid argument

答案1

得分: 4

例如,

package main

import (
	"fmt"
	"syscall"
	"unicode/utf16"
	"unsafe"
)

var (
	WinSCard, _                  = syscall.LoadLibrary(`C:\windows\system32\WinSCard.dll`)
	procSCardEstablishContext, _ = syscall.GetProcAddress(WinSCard, "SCardEstablishContext")
	procSCardReleaseContext, _   = syscall.GetProcAddress(WinSCard, "SCardReleaseContext")
	procSCardListReaders, _      = syscall.GetProcAddress(WinSCard, "SCardListReadersW")
)

const (
	SCARD_SCOPE_USER   = 0
	SCARD_SCOPE_SYSTEM = 2

	SCARD_ALL_READERS     = "SCard$AllReaders"
	SCARD_DEFAULT_READERS = "SCard$DefaultReaders"
)

func SCardListReaders(hContext syscall.Handle, mszGroups *uint16, mszReaders *uint16, pcchReaders *uint32) (retval error) {
	r0, _, _ := syscall.Syscall6(
		uintptr(procSCardListReaders),
		4,
		uintptr(hContext),
		uintptr(unsafe.Pointer(mszGroups)),
		uintptr(unsafe.Pointer(mszReaders)),
		uintptr(unsafe.Pointer(pcchReaders)),
		0,
		0,
	)
	if r0 != 0 {
		retval = syscall.Errno(r0)
	}
	return
}

func SCardReleaseContext(hContext syscall.Handle) (retval error) {
	r0, _, _ := syscall.Syscall(
		uintptr(procSCardReleaseContext),
		1,
		uintptr(hContext),
		0,
		0,
	)
	if r0 != 0 {
		retval = syscall.Errno(r0)
	}
	return
}

func SCardEstablishContext(dwScope uint32, pvReserved1 uintptr, pvReserved2 uintptr, phContext *syscall.Handle) (retval error) {
	r0, _, _ := syscall.Syscall6(
		uintptr(procSCardEstablishContext),
		4,
		uintptr(dwScope),
		uintptr(pvReserved1),
		uintptr(pvReserved2),
		uintptr(unsafe.Pointer(phContext)),
		0,
		0,
	)
	if r0 != 0 {
		retval = syscall.Errno(r0)
	}
	return
}

func ReturnValue(err error) uint32 {
	rv, ok := err.(syscall.Errno)
	if !ok {
		rv = 0
	}
	return uint32(rv)
}

func UTF16ToStrings(ls []uint16) []string {
	var ss []string
	if len(ls) == 0 {
		return ss
	}
	if ls[len(ls)-1] != 0 {
		ls = append(ls, 0)
	}
	i := 0
	for j, cu := range ls {
		if cu == 0 {
			if j >= 1 && ls[j-1] == 0 {
				break
			}
			if j-i > 0 {
				ss = append(ss, string(utf16.Decode(ls[i:j])))
			}
			i = j + 1
			continue
		}
	}
	return ss
}

func main() {
	var (
		context  syscall.Handle
		scope    uint32
		groups   *uint16
		cReaders uint32
	)

	context = 0
	groups, err := syscall.UTF16PtrFromString(SCARD_ALL_READERS)
	if err != nil {
		fmt.Println("Reader Group: ", err)
		return
	}
	err = SCardListReaders(context, groups, nil, &cReaders)
	if err != nil {
		fmt.Printf("SCardListReaders: 0x%X %s\n", ReturnValue(err), err)
		return
	}
	r := make([]uint16, cReaders)
	err = SCardListReaders(context, groups, &r[0], &cReaders)
	if err != nil {
		fmt.Printf("SCardListReaders: 0x%X %s\n", ReturnValue(err), err)
		return
	}
	readers := UTF16ToStrings(r[:cReaders])
	fmt.Println("Readers:", len(readers), readers)

	scope = SCARD_SCOPE_SYSTEM
	err = SCardEstablishContext(scope, 0, 0, &context)
	if err != nil {
		fmt.Printf("SCardEstablishContext: 0x%X %s\n", ReturnValue(err), err)
		return
	}
	defer SCardReleaseContext(context)
	fmt.Printf("Context: %X\n", context)
}

输出:

计算机1:

Readers: 1 [O2 O2Micro CCID SC Reader 0]
Context: CD00000100000000

计算机2:

Readers: 0 []
SCardEstablishContext: 0x8010001D The Smart card resource manager is not running.

另外,注意修复了procSCardListReadersProcName

procSCardListReaders, _ = syscall.GetProcAddress(WinSCard, "SCardListReadersW")
英文:

For example,

package main

import (
	"fmt"
	"syscall"
	"unicode/utf16"
	"unsafe"
)

var (
	WinSCard, _                  = syscall.LoadLibrary(`C:\windows\system32\WinSCard.dll`)
	procSCardEstablishContext, _ = syscall.GetProcAddress(WinSCard, "SCardEstablishContext")
	procSCardReleaseContext, _   = syscall.GetProcAddress(WinSCard, "SCardReleaseContext")
	procSCardListReaders, _      = syscall.GetProcAddress(WinSCard, "SCardListReadersW")
)

const (
	SCARD_SCOPE_USER   = 0
	SCARD_SCOPE_SYSTEM = 2

	SCARD_ALL_READERS     = "SCard$AllReaders"
	SCARD_DEFAULT_READERS = "SCard$DefaultReaders"
)

func SCardListReaders(hContext syscall.Handle, mszGroups *uint16, mszReaders *uint16, pcchReaders *uint32) (retval error) {
	r0, _, _ := syscall.Syscall6(
		uintptr(procSCardListReaders),
		4,
		uintptr(hContext),
		uintptr(unsafe.Pointer(mszGroups)),
		uintptr(unsafe.Pointer(mszReaders)),
		uintptr(unsafe.Pointer(pcchReaders)),
		0,
		0,
	)
	if r0 != 0 {
		retval = syscall.Errno(r0)
	}
	return
}

func SCardReleaseContext(hContext syscall.Handle) (retval error) {
	r0, _, _ := syscall.Syscall(
		uintptr(procSCardReleaseContext),
		1,
		uintptr(hContext),
		0,
		0,
	)
	if r0 != 0 {
		retval = syscall.Errno(r0)
	}
	return
}

func SCardEstablishContext(dwScope uint32, pvReserved1 uintptr, pvReserved2 uintptr, phContext *syscall.Handle) (retval error) {
	r0, _, _ := syscall.Syscall6(
		uintptr(procSCardEstablishContext),
		4,
		uintptr(dwScope),
		uintptr(pvReserved1),
		uintptr(pvReserved2),
		uintptr(unsafe.Pointer(phContext)),
		0,
		0,
	)
	if r0 != 0 {
		retval = syscall.Errno(r0)
	}
	return
}

func ReturnValue(err error) uint32 {
	rv, ok := err.(syscall.Errno)
	if !ok {
		rv = 0
	}
	return uint32(rv)
}

func UTF16ToStrings(ls []uint16) []string {
	var ss []string
	if len(ls) == 0 {
		return ss
	}
	if ls[len(ls)-1] != 0 {
		ls = append(ls, 0)
	}
	i := 0
	for j, cu := range ls {
		if cu == 0 {
			if j >= 1 && ls[j-1] == 0 {
				break
			}
			if j-i > 0 {
				ss = append(ss, string(utf16.Decode(ls[i:j])))
			}
			i = j + 1
			continue
		}
	}
	return ss
}

func main() {
	var (
		context  syscall.Handle
		scope    uint32
		groups   *uint16
		cReaders uint32
	)

	context = 0
	groups, err := syscall.UTF16PtrFromString(SCARD_ALL_READERS)
	if err != nil {
		fmt.Println("Reader Group: ", err)
		return
	}
	err = SCardListReaders(context, groups, nil, &cReaders)
	if err != nil {
		fmt.Printf("SCardListReaders: 0x%X %s\n", ReturnValue(err), err)
		return
	}
	r := make([]uint16, cReaders)
	err = SCardListReaders(context, groups, &r[0], &cReaders)
	if err != nil {
		fmt.Printf("SCardListReaders: 0x%X %s\n", ReturnValue(err), err)
		return
	}
	readers := UTF16ToStrings(r[:cReaders])
	fmt.Println("Readers:", len(readers), readers)

	scope = SCARD_SCOPE_SYSTEM
	err = SCardEstablishContext(scope, 0, 0, &context)
	if err != nil {
		fmt.Printf("SCardEstablishContext: 0x%X %s\n", ReturnValue(err), err)
		return
	}
	defer SCardReleaseContext(context)
	fmt.Printf("Context: %X\n", context)
}

Output:

Computer 1:

Readers: 1 [O2 O2Micro CCID SC Reader 0]
Context: CD00000100000000

Computer 2:

Readers: 0 []
SCardEstablishContext: 0x8010001D The Smart card resource manager is not running.

Also, note the fix for the procSCardListReaders ProcName:

procSCardListReaders, _ = syscall.GetProcAddress(WinSCard, "SCardListReadersW")

huangapple
  • 本文由 发表于 2013年6月9日 12:40:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/17006483.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定