keycard-go/vendor/github.com/ebfe/scard/scard_windows.go

220 lines
6.7 KiB
Go
Raw Normal View History

2018-11-09 11:32:05 +00:00
package scard
import (
"fmt"
"syscall"
"unsafe"
)
var (
modwinscard = syscall.NewLazyDLL("winscard.dll")
procEstablishContext = modwinscard.NewProc("SCardEstablishContext")
procReleaseContext = modwinscard.NewProc("SCardReleaseContext")
procIsValidContext = modwinscard.NewProc("SCardIsValidContext")
procCancel = modwinscard.NewProc("SCardCancel")
procListReaders = modwinscard.NewProc("SCardListReadersW")
procListReaderGroups = modwinscard.NewProc("SCardListReaderGroupsW")
procGetStatusChange = modwinscard.NewProc("SCardGetStatusChangeW")
procConnect = modwinscard.NewProc("SCardConnectW")
procDisconnect = modwinscard.NewProc("SCardDisconnect")
procReconnect = modwinscard.NewProc("SCardReconnect")
procBeginTransaction = modwinscard.NewProc("SCardBeginTransaction")
procEndTransaction = modwinscard.NewProc("SCardEndTransaction")
procStatus = modwinscard.NewProc("SCardStatusW")
procTransmit = modwinscard.NewProc("SCardTransmit")
procControl = modwinscard.NewProc("SCardControl")
procGetAttrib = modwinscard.NewProc("SCardGetAttrib")
procSetAttrib = modwinscard.NewProc("SCardSetAttrib")
dataT0Pci = modwinscard.NewProc("g_rgSCardT0Pci")
dataT1Pci = modwinscard.NewProc("g_rgSCardT1Pci")
)
var scardIoReqT0 uintptr
var scardIoReqT1 uintptr
func init() {
if err := dataT0Pci.Find(); err != nil {
panic(err)
}
scardIoReqT0 = dataT0Pci.Addr()
if err := dataT1Pci.Find(); err != nil {
panic(err)
}
scardIoReqT1 = dataT1Pci.Addr()
}
func (e Error) Error() string {
err := syscall.Errno(e)
return fmt.Sprintf("scard: error(%x): %s", uintptr(e), err.Error())
}
func scardEstablishContext(scope Scope, reserved1, reserved2 uintptr) (uintptr, Error) {
var ctx uintptr
r, _, _ := procEstablishContext.Call(uintptr(scope), reserved1, reserved2, uintptr(unsafe.Pointer(&ctx)))
return ctx, Error(r)
}
func scardIsValidContext(ctx uintptr) Error {
r, _, _ := procIsValidContext.Call(ctx)
return Error(r)
}
func scardCancel(ctx uintptr) Error {
r, _, _ := procCancel.Call(ctx)
return Error(r)
}
func scardReleaseContext(ctx uintptr) Error {
r, _, _ := procReleaseContext.Call(ctx)
return Error(r)
}
func scardListReaders(ctx uintptr, groups, buf unsafe.Pointer, bufLen uint32) (uint32, Error) {
dwBufLen := uint32(bufLen)
r, _, _ := procListReaders.Call(ctx, uintptr(groups), uintptr(buf), uintptr(unsafe.Pointer(&dwBufLen)))
return dwBufLen, Error(r)
}
func scardListReaderGroups(ctx uintptr, buf unsafe.Pointer, bufLen uint32) (uint32, Error) {
dwBufLen := uint32(bufLen)
r, _, _ := procListReaderGroups.Call(ctx, uintptr(buf), uintptr(unsafe.Pointer(&dwBufLen)))
return dwBufLen, Error(r)
}
func scardGetStatusChange(ctx uintptr, timeout uint32, states []scardReaderState) Error {
r, _, _ := procGetStatusChange.Call(ctx, uintptr(timeout), uintptr(unsafe.Pointer(&states[0])), uintptr(len(states)))
return Error(r)
}
func scardConnect(ctx uintptr, reader unsafe.Pointer, shareMode ShareMode, proto Protocol) (uintptr, Protocol, Error) {
var handle uintptr
var activeProto uint32
r, _, _ := procConnect.Call(ctx, uintptr(reader), uintptr(shareMode), uintptr(proto), uintptr(unsafe.Pointer(&handle)), uintptr(unsafe.Pointer(&activeProto)))
return handle, Protocol(activeProto), Error(r)
}
func scardDisconnect(card uintptr, d Disposition) Error {
r, _, _ := procDisconnect.Call(card, uintptr(d))
return Error(r)
}
func scardReconnect(card uintptr, mode ShareMode, proto Protocol, disp Disposition) (Protocol, Error) {
var activeProtocol uint32
r, _, _ := procReconnect.Call(card, uintptr(mode), uintptr(proto), uintptr(disp), uintptr(unsafe.Pointer(&activeProtocol)))
return Protocol(activeProtocol), Error(r)
}
func scardBeginTransaction(card uintptr) Error {
r, _, _ := procBeginTransaction.Call(card)
return Error(r)
}
func scardEndTransaction(card uintptr, disp Disposition) Error {
r, _, _ := procEndTransaction.Call(card, uintptr(disp))
return Error(r)
}
func scardCardStatus(card uintptr, readerBuf strbuf, atrBuf []byte) (uint32, State, Protocol, uint32, Error) {
var state, proto uint32
var atrLen = uint32(len(atrBuf))
readerLen := uint32(len(readerBuf))
r, _, _ := procStatus.Call(card, uintptr(readerBuf.ptr()), uintptr(unsafe.Pointer(&readerLen)), uintptr(unsafe.Pointer(&state)), uintptr(unsafe.Pointer(&proto)), uintptr(unsafe.Pointer(&atrBuf[0])), uintptr(unsafe.Pointer(&atrLen)))
return readerLen, State(state), Protocol(proto), atrLen, Error(r)
}
func scardTransmit(card uintptr, proto Protocol, cmd []byte, rsp []byte) (uint32, Error) {
var sendpci uintptr
var rspLen = uint32(len(rsp))
switch proto {
case ProtocolT0:
sendpci = scardIoReqT0
case ProtocolT1:
sendpci = scardIoReqT1
default:
panic("unknown protocol")
}
r, _, _ := procTransmit.Call(card, sendpci, uintptr(unsafe.Pointer(&cmd[0])), uintptr(len(cmd)), uintptr(0), uintptr(unsafe.Pointer(&rsp[0])), uintptr(unsafe.Pointer(&rspLen)))
return rspLen, Error(r)
}
func scardControl(card uintptr, ioctl uint32, in, out []byte) (uint32, Error) {
var ptrIn uintptr
var outLen = uint32(len(out))
if len(in) != 0 {
ptrIn = uintptr(unsafe.Pointer(&in[0]))
}
r, _, _ := procControl.Call(card, uintptr(ioctl), ptrIn, uintptr(len(in)), uintptr(unsafe.Pointer(&out[0])), uintptr(len(out)), uintptr(unsafe.Pointer(&outLen)))
return outLen, Error(r)
}
func scardGetAttrib(card uintptr, id Attrib, buf []byte) (uint32, Error) {
var ptr uintptr
if len(buf) != 0 {
ptr = uintptr(unsafe.Pointer(&buf[0]))
}
bufLen := uint32(len(buf))
r, _, _ := procGetAttrib.Call(card, uintptr(id), ptr, uintptr(unsafe.Pointer(&bufLen)))
return bufLen, Error(r)
}
func scardSetAttrib(card uintptr, id Attrib, buf []byte) Error {
r, _, _ := procSetAttrib.Call(card, uintptr(id), uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)))
return Error(r)
}
type scardReaderState struct {
szReader uintptr
pvUserData uintptr
dwCurrentState uint32
dwEventState uint32
cbAtr uint32
rgbAtr [36]byte
}
func (rs *ReaderState) toSys() (scardReaderState, error) {
var sys scardReaderState
creader, err := encodestr(rs.Reader)
if err != nil {
return scardReaderState{}, err
}
sys.szReader = uintptr(creader.ptr())
sys.dwCurrentState = uint32(rs.CurrentState)
sys.cbAtr = uint32(len(rs.Atr))
copy(sys.rgbAtr[:], rs.Atr)
return sys, nil
}
func (rs *ReaderState) update(sys *scardReaderState) {
rs.EventState = StateFlag(sys.dwEventState)
if sys.cbAtr > 0 {
rs.Atr = make([]byte, int(sys.cbAtr))
copy(rs.Atr, sys.rgbAtr[:])
}
}
type strbuf []uint16
func encodestr(s string) (strbuf, error) {
utf16, err := syscall.UTF16FromString(s)
return strbuf(utf16), err
}
func decodestr(buf strbuf) string {
return syscall.UTF16ToString(buf)
}