/[winpt]/trunk/Src/wptCardPCSC.c
ViewVC logotype

Diff of /trunk/Src/wptCardPCSC.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 26 by twoaday, Mon Oct 17 08:49:30 2005 UTC revision 48 by werner, Mon Oct 31 21:14:11 2005 UTC
# Line 1  Line 1 
1  /* wptCardPCSC.cpp - PC/SC card API interface  /* wptCardPCSC.cpp - PC/SC card API interface
2   *      Copyright (C) 2003 Timo Schulz   *      Copyright (C) 2003 Timo Schulz
3   *   *      Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4   * This file is part of WinPT.   *
5   *   * This file is part of WinPT.
6   * WinPT is free software; you can redistribute it and/or modify   *
7   * it under the terms of the GNU General Public License as published by   * WinPT is free software; you can redistribute it and/or modify
8   * the Free Software Foundation; either version 2 of the License, or   * it under the terms of the GNU General Public License as published by
9   * (at your option) any later version.   * the Free Software Foundation; either version 2 of the License, or
10   *   * (at your option) any later version.
11   * WinPT is distributed in the hope that it will be useful,   *
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * WinPT is distributed in the hope that it will be useful,
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * GNU General Public License for more details.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15   *   * GNU General Public License for more details.
16   * You should have received a copy of the GNU General Public License   *
17   * along with WinPT; if not, write to the Free Software Foundation,   * You should have received a copy of the GNU General Public License
18   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   * along with WinPT; if not, write to the Free Software Foundation,
19   */   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20     */
21  #include <stdio.h>  
22  #include <windows.h>  #ifdef HAVE_CONFIG_H
23  #include <winscard.h>  #include <config.h>
24    #endif
25  #include "gpgme.h"  
26  #include "wptTypes.h"  #include <stdio.h>
27  #include "wptCard.h"  #include <stdio.h>
28    #include <windows.h>
29  /* Possible card states. */  
30  enum {  #include "gpgme.h"
31      CARD_STATE_NONE=0,  #include "wptTypes.h"
32      CARD_STATE_UNAWARE,  #include "wptCard.h"
33      CARD_STATE_UNAVAIL,  
34      CARD_STATE_PRESENT,  
35      CARD_STATE_EXCLUSI,  /* Definitions usually found in winscard.h but not used here becuase
36      CARD_STATE_EMPTY,     mingw does not come with winscard and we dlopen the stuff
37      CARD_STATE_INUSE,     anyway. */
38      CARD_STATE_MUTE  typedef unsigned long pcsc_context_t;
39  };  
40    struct pcsc_readerstate_s
41  #define MAX_READERS 8  {
42      const char *reader;
43  struct pcsc_reader_s {    void *user_data;
44      SCARD_READERSTATE_A reader_states[MAX_READERS];    unsigned long current_state;
45      int nreaders;    unsigned long event_state;
46      char * readers[MAX_READERS];    unsigned long atrlen;
47  };    unsigned char atr[33];
48  typedef struct pcsc_reader_s *pcsc_reader_t;  };
49    
50    typedef struct pcsc_readerstate_s *pcsc_readerstate_t;
51  static LONG (WINAPI *pcsc_establish_context) (unsigned long scope,  
52                                  const void *reserved1,  /* PC/SC constants and function pointer. */
53                                  const void *reserved2,  #define PCSC_SCOPE_USER      0
54                                  unsigned long *r_context);  #define PCSC_SCOPE_TERMINAL  1
55  static LONG (WINAPI *pcsc_release_context) (unsigned long context);  #define PCSC_SCOPE_SYSTEM    2
56  static LONG (WINAPI *pcsc_list_readers) (unsigned long context,  #define PCSC_SCOPE_GLOBAL    3
57                                           const char *groups,  
58                                           char *readers,  #define PCSC_PROTOCOL_T0     1
59                                           unsigned long *readerslen);  #define PCSC_PROTOCOL_T1     2
60  static LONG (WINAPI *pcsc_connect) (unsigned long context,  #define PCSC_PROTOCOL_RAW    4
61                        const char *reader,  
62                        unsigned long share_mode,  #define PCSC_SHARE_EXCLUSIVE 1
63                        unsigned long preferred_protocols,  #define PCSC_SHARE_SHARED    2
64                        unsigned long *r_card,  #define PCSC_SHARE_DIRECT    3
65                        unsigned long *r_active_protocol);  
66  static LONG (WINAPI *pcsc_disconnect) (unsigned long card,  #define PCSC_LEAVE_CARD      0
67                                         unsigned long disposition);  #define PCSC_RESET_CARD      1
68  static LONG (WINAPI *pcsc_status) (unsigned long card,  #define PCSC_UNPOWER_CARD    2
69                       char *reader, unsigned long *readerlen,  #define PCSC_EJECT_CARD      3
70                       unsigned long *r_state, unsigned long *r_protocol,  
71                       unsigned char *atr, unsigned long *atrlen);  #define PCSC_UNKNOWN    0x0001
72  static LONG (WINAPI *pcsc_get_status_change)(unsigned long ctx,  #define PCSC_ABSENT     0x0002  /* Card is absent.  */
73                                               unsigned long timeout,  #define PCSC_PRESENT    0x0004  /* Card is present.  */
74                                               SCARD_READERSTATE * readerstate,  #define PCSC_SWALLOWED  0x0008  /* Card is present and electrical connected. */
75                                               unsigned long creaders);  #define PCSC_POWERED    0x0010  /* Card is powered.  */
76    #define PCSC_NEGOTIABLE 0x0020  /* Card is awaiting PTS.  */
77  static int pcsc_init = 0;  #define PCSC_SPECIFIC   0x0040  /* Card is ready for use.  */
78    
79    #define PCSC_STATE_UNAWARE     0x0000  /* Want status.  */
80  #define load_one_fnc(ptr, hlib, name) do {                          \  #define PCSC_STATE_IGNORE      0x0001  /* Ignore this reader.  */
81      a = ptr = (void *)GetProcAddress (hlib, name);                  \  #define PCSC_STATE_CHANGED     0x0002  /* State has changed.  */
82      if (!a) {                                                       \  #define PCSC_STATE_UNKNOWN     0x0004  /* Reader unknown.  */
83          char msg[256];                                              \  #define PCSC_STATE_UNAVAILABLE 0x0008  /* Status unavailable.  */
84          _snprintf (msg, sizeof msg-1, "Could not load '%s'", name); \  #define PCSC_STATE_EMPTY       0x0010  /* Card removed.  */
85          MessageBox (NULL, msg, "PC/SC Driver", MB_ICONERROR|MB_OK); \  #define PCSC_STATE_PRESENT     0x0020  /* Card inserted.  */
86          goto fail;                                                  \  #define PCSC_STATE_ATRMATCH    0x0040  /* ATR matches card. */
87      } \  #define PCSC_STATE_EXCLUSIVE   0x0080  /* Exclusive Mode.  */
88  } while (0)  #define PCSC_STATE_INUSE       0x0100  /* Shared mode.  */
89    #define PCSC_STATE_MUTE        0x0200  /* Unresponsive card.  */
90    
91  int  /* Some PC/SC error codes.  */
92  pcsc_loadlib (int scard_support)  #define PCSC_E_CANCELLED               0x80100002
93  {  #define PCSC_E_CANT_DISPOSE            0x8010000E
94      HMODULE hlib;  #define PCSC_E_INSUFFICIENT_BUFFER     0x80100008
95      FARPROC a;      #define PCSC_E_INVALID_ATR             0x80100015
96    #define PCSC_E_INVALID_HANDLE          0x80100003
97      if (!scard_support || pcsc_init)  #define PCSC_E_INVALID_PARAMETER       0x80100004
98          return 0;  #define PCSC_E_INVALID_TARGET          0x80100005
99      hlib = LoadLibrary ("WINSCARD");  #define PCSC_E_INVALID_VALUE           0x80100011
100      if (!hlib)  #define PCSC_E_NO_MEMORY               0x80100006
101          goto fail;  #define PCSC_E_UNKNOWN_READER          0x80100009
102      load_one_fnc (pcsc_establish_context, hlib, "SCardEstablishContext");  #define PCSC_E_TIMEOUT                 0x8010000A
103      load_one_fnc (pcsc_release_context, hlib, "SCardReleaseContext");  #define PCSC_E_SHARING_VIOLATION       0x8010000B
104      load_one_fnc (pcsc_list_readers, hlib, "SCardListReadersA");  #define PCSC_E_NO_SMARTCARD            0x8010000C
105      load_one_fnc (pcsc_connect, hlib, "SCardConnectA");  #define PCSC_E_UNKNOWN_CARD            0x8010000D
106      load_one_fnc (pcsc_disconnect, hlib, "SCardDisconnect");  #define PCSC_E_PROTO_MISMATCH          0x8010000F
107      load_one_fnc (pcsc_status, hlib, "SCardStatusA");  #define PCSC_E_NOT_READY               0x80100010
108      load_one_fnc (pcsc_get_status_change, hlib, "SCardGetStatusChangeA");  #define PCSC_E_SYSTEM_CANCELLED        0x80100012
109      goto success;  #define PCSC_E_NOT_TRANSACTED          0x80100016
110    #define PCSC_E_READER_UNAVAILABLE      0x80100017
111  fail:  #define PCSC_W_REMOVED_CARD            0x80100069
112      FreeLibrary (hlib);  
113      return -1;  /* Possible card states. */
114  success:  enum card_state_t {
115      pcsc_init = 1;      CARD_STATE_NONE=0,
116      FreeLibrary (hlib);      CARD_STATE_UNAWARE,
117      return 0;      CARD_STATE_UNAVAIL,
118  }      CARD_STATE_PRESENT,
119        CARD_STATE_EXCLUSI,
120        CARD_STATE_EMPTY,
121  void      CARD_STATE_INUSE,
122  pcsc_free_readers (pcsc_reader_t rd)      CARD_STATE_MUTE
123  {  };
124      int i;  
125    #define MAX_READERS 8
126      if (!rd)  
127          return;  struct pcsc_reader_s {
128        struct pcsc_readerstate_s reader_states[MAX_READERS];
129      for (i=0; i < rd->nreaders; i++)      int nreaders;
130          safe_free (rd->readers[i]);      char * readers[MAX_READERS];
131      safe_free (rd);  };
132  }  typedef struct pcsc_reader_s *pcsc_reader_t;
133    
134    
135  const char *  static LONG (WINAPI *pcsc_establish_context) (unsigned long scope,
136  pcsc_get_reader (pcsc_reader_t rd, int idx, int * ret_nrd)                                  const void *reserved1,
137  {                                  const void *reserved2,
138      if (!rd)                                  unsigned long *r_context);
139          return NULL;  static LONG (WINAPI *pcsc_release_context) (unsigned long context);
140      if (idx == -1 && ret_nrd) {  static LONG (WINAPI *pcsc_list_readers) (unsigned long context,
141          *ret_nrd = rd->nreaders;                                           const char *groups,
142          return NULL;                                           char *readers,
143      }                                           unsigned long *readerslen);
144      if (idx >= rd->nreaders)  static LONG (WINAPI *pcsc_connect) (unsigned long context,
145          idx=0;                        const char *reader,
146      return rd->readers[idx];                        unsigned long share_mode,
147  }                        unsigned long preferred_protocols,
148                          unsigned long *r_card,
149                          unsigned long *r_active_protocol);
150  int  static LONG (WINAPI *pcsc_disconnect) (unsigned long card,
151  pcsc_scan_readers (pcsc_reader_t * ret_rd)                                         unsigned long disposition);
152  {  static LONG (WINAPI *pcsc_status) (unsigned long card,
153      pcsc_reader_t rd;                       char *reader, unsigned long *readerlen,
154      SCARDCONTEXT hctx;                       unsigned long *r_state, unsigned long *r_protocol,
155      SCARD_READERSTATE_A rdstat;                       unsigned char *atr, unsigned long *atrlen);
156      DWORD readers;  static LONG (WINAPI *pcsc_get_status_change)(unsigned long ctx,
157      LPSTR rdrstr;                                               unsigned long timeout,
158      char * p;                                               pcsc_readerstate_t readerstate,
159      int i;                                               unsigned long creaders);
160      int rc, curr_rd=0;  
161    static int pcsc_init = 0;
162      *ret_rd = NULL;  
163      if (!pcsc_init)  
164          return -1;  #define load_one_fnc(ptr, hlib, name) do {                          \
165        a = ptr = (void *)GetProcAddress (hlib, name);                  \
166      rc = pcsc_establish_context (SCARD_SCOPE_SYSTEM, NULL, NULL, &hctx);      if (!a) {                                                       \
167      if (rc != SCARD_S_SUCCESS)          char msg[256];                                              \
168          return -1;          _snprintf (msg, sizeof msg-1, "Could not load '%s'", name); \
169            MessageBox (NULL, msg, "PC/SC Driver", MB_ICONERROR|MB_OK); \
170      rc = pcsc_list_readers (hctx, NULL, NULL, &readers);          goto fail;                                                  \
171      if (rc != SCARD_S_SUCCESS)      } \
172          return -1;  } while (0)
173    
174      rdrstr = malloc (sizeof(char)*readers);  
175      if (!rdrstr)  int
176          BUG (0);  pcsc_loadlib (int scard_support)
177    {
178      rc = pcsc_list_readers (hctx, NULL, rdrstr, &readers);      HMODULE hlib;
179      if (rc != SCARD_S_SUCCESS) {      FARPROC a;    
180          safe_free (rdrstr);  
181          return -1;      if (!scard_support || pcsc_init)
182      }          return 0;
183        hlib = LoadLibrary ("WINSCARD");
184      rd = calloc (1, sizeof *rd);      if (!hlib)
185      if (!rd)          goto fail;
186          BUG (0);      load_one_fnc (pcsc_establish_context, hlib, "SCardEstablishContext");
187                load_one_fnc (pcsc_release_context, hlib, "SCardReleaseContext");
188      p = rdrstr;      load_one_fnc (pcsc_list_readers, hlib, "SCardListReadersA");
189      while ((*p != '\0') && (rd->nreaders < MAX_READERS)) {            load_one_fnc (pcsc_connect, hlib, "SCardConnectA");
190          rd->readers[rd->nreaders] = strdup (p);      load_one_fnc (pcsc_disconnect, hlib, "SCardDisconnect");
191          p += strlen (p)+1;      load_one_fnc (pcsc_status, hlib, "SCardStatusA");
192          rd->nreaders++;      load_one_fnc (pcsc_get_status_change, hlib, "SCardGetStatusChangeA");
193      }      goto success;
194    
195      if (!rd->nreaders) {  fail:
196          safe_free (rdrstr);      FreeLibrary (hlib);
197          safe_free (rd);      return -1;
198          return 0;  success:
199      }      pcsc_init = 1;
200        FreeLibrary (hlib);
201      /* set the initial states */      return 0;
202      for (i=0; i<rd->nreaders; i++) {  }
203          rd->reader_states[i].szReader = rd->readers[i];  
204          rd->reader_states[i].dwCurrentState = SCARD_STATE_EMPTY;  
205      }  void
206    pcsc_free_readers (pcsc_reader_t rd)
207      while (1) {  {
208          rdstat = rd->reader_states[curr_rd];                  int i;
209          rc = pcsc_get_status_change (hctx, 0, &rdstat, 1);  
210          if (rc == SCARD_E_TIMEOUT)      if (!rd)
211              continue;          return;
212          if (rc != SCARD_S_SUCCESS)  
213              ;      for (i=0; i < rd->nreaders; i++)
214            safe_free (rd->readers[i]);
215          /* next reader */      safe_free (rd);
216          curr_rd++;  }
217          if (curr_rd >= rd->nreaders)  
218              curr_rd = 0;  
219      }  const char *
220        pcsc_get_reader (pcsc_reader_t rd, int idx, int * ret_nrd)
221      safe_free (rdrstr);  {
222      *ret_rd = rd;      if (!rd)
223      rc = pcsc_release_context (hctx);          return NULL;
224      if (rc != SCARD_S_SUCCESS)      if (idx == -1 && ret_nrd) {
225          return -1;          *ret_nrd = rd->nreaders;
226      return 0;          return NULL;
227  }      }
228        if (idx >= rd->nreaders)
229            idx=0;
230  int      return rd->readers[idx];
231  pcsc_get_card_status (void)  }
232  {  
233      pcsc_reader_t rd;  
234      SCARD_READERSTATE_A rdstat;  int
235      int rc, stat=0;  pcsc_scan_readers (pcsc_reader_t * ret_rd)
236    {
237      rc = pcsc_scan_readers (&rd);      pcsc_reader_t rd;
238      if (rc)      pcsc_context_t hctx;
239          return -1;      struct pcsc_readerstate_s rdstat;
240      rdstat = rd->reader_states[0];      DWORD readers;
241      if (rdstat.dwCurrentState & SCARD_STATE_UNAVAILABLE)      LPSTR rdrstr;
242          stat |= CARD_STATE_UNAVAIL;      char * p;
243      if (rdstat.dwCurrentState & SCARD_STATE_EMPTY)      int i;
244          stat |= CARD_STATE_EMPTY;      int rc, curr_rd=0;
245      if (rdstat.dwCurrentState & SCARD_STATE_INUSE)  
246          stat |= CARD_STATE_INUSE;      *ret_rd = NULL;
247      if (rdstat.dwCurrentState & SCARD_STATE_EXCLUSIVE)      if (!pcsc_init)
248          stat |= CARD_STATE_EXCLUSI;          return -1;
249      return stat;  
250  }      rc = pcsc_establish_context (PCSC_SCOPE_SYSTEM, NULL, NULL, &hctx);
251        if (rc)
252            return -1;
253    
254        rc = pcsc_list_readers (hctx, NULL, NULL, &readers);
255        if (rc)
256            return -1;
257    
258        rdrstr = malloc (sizeof(char)*readers);
259        if (!rdrstr)
260            BUG (0);
261    
262        rc = pcsc_list_readers (hctx, NULL, rdrstr, &readers);
263        if (rc) {
264            safe_free (rdrstr);
265            return -1;
266        }
267    
268        rd = calloc (1, sizeof *rd);
269        if (!rd)
270            BUG (0);
271            
272        p = rdrstr;
273        while ((*p != '\0') && (rd->nreaders < MAX_READERS)) {      
274            rd->readers[rd->nreaders] = strdup (p);
275            p += strlen (p)+1;
276            rd->nreaders++;
277        }
278    
279        if (!rd->nreaders) {
280            safe_free (rdrstr);
281            safe_free (rd);
282            return 0;
283        }
284    
285        /* set the initial states */
286        for (i=0; i<rd->nreaders; i++) {
287            rd->reader_states[i].reader = rd->readers[i];
288            rd->reader_states[i].current_state = PCSC_STATE_EMPTY;
289        }
290    
291        while (1) {
292            rdstat = rd->reader_states[curr_rd];            
293            rc = pcsc_get_status_change (hctx, 0, &rdstat, 1);
294            if (rc == PCSC_E_TIMEOUT)
295                continue;
296            if (rc)
297              ; /* FIXME:  What is this?? */
298    
299            /* next reader */
300            curr_rd++;
301            if (curr_rd >= rd->nreaders)
302                curr_rd = 0;
303        }
304        
305        safe_free (rdrstr);
306        *ret_rd = rd;
307        rc = pcsc_release_context (hctx);
308        if (rc)
309            return -1;
310        return 0;
311    }
312    
313    
314    int
315    pcsc_get_card_status (void)
316    {
317        pcsc_reader_t rd;
318        struct pcsc_readerstate_s rdstat;
319        int rc, stat=0;
320    
321        rc = pcsc_scan_readers (&rd);
322        if (rc)
323            return -1;
324        rdstat = rd->reader_states[0];
325        if (rdstat.current_state & PCSC_STATE_UNAVAILABLE)
326            stat |= CARD_STATE_UNAVAIL;
327        if (rdstat.current_state & PCSC_STATE_EMPTY)
328            stat |= CARD_STATE_EMPTY;
329        if (rdstat.current_state & PCSC_STATE_INUSE)
330            stat |= CARD_STATE_INUSE;
331        if (rdstat.current_state & PCSC_STATE_EXCLUSIVE)
332            stat |= CARD_STATE_EXCLUSI;
333        return stat;
334    }

Legend:
Removed from v.26  
changed lines
  Added in v.48

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26