/[openpgpmdrv]/trunk/OpenPGPminidriver/CardPinOperation.c
ViewVC logotype

Annotation of /trunk/OpenPGPminidriver/CardPinOperation.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Tue Feb 23 19:18:59 2010 UTC (15 years, 2 months ago) by vletoux
File MIME type: text/plain
File size: 18100 byte(s)


1 vletoux 1 /* OpenPGP Smart Card Mini Driver
2     Copyright (C) 2009 Vincent Le Toux
3    
4     This library is Free software; you can redistribute it and/or
5     modify it under the terms of the GNU Lesser General Public
6     License version 2.1 as published by the Free Software Foundation.
7    
8     This library is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11     Lesser General Public License for more details.
12    
13     You should have received a copy of the GNU Lesser General Public
14     License along with this library; if not, write to the Free Software
15     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16     */
17    
18     #include <windows.h>
19     #include <cardmod.h>
20     #include "Tracing.h"
21     #include "Context.h"
22     #include "SmartCard.h"
23     #include "PinOperations.h"
24    
25    
26     // 4.2 Card PIN Operations
27    
28     /** The CardAuthenticatePin function submits a PIN value as a string
29     to the card to establish the user’s identity and to satisfy access
30     conditions for an operation to be undertaken on the user’s behalf.
31     Submission of a PIN to the card may involve some processing by the card
32     minidriver to render the PIN information to a card-specific form. */
33    
34     DWORD WINAPI CardAuthenticatePin(
35     __in PCARD_DATA pCardData,
36     __in LPWSTR pwszUserId,
37     __in_bcount(cbPin) PBYTE pbPin,
38     __in DWORD cbPin,
39     __out_opt PDWORD pcAttemptsRemaining
40     )
41     {
42     DWORD dwReturn = 0;
43     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter authenticate %s", pwszUserId);
44     __try
45     {
46     if ( pCardData == NULL )
47     {
48     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
49     dwReturn = SCARD_E_INVALID_PARAMETER;
50     __leave;
51     }
52     if ( pwszUserId == NULL )
53     {
54     Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId == NULL");
55     dwReturn = SCARD_E_INVALID_PARAMETER;
56     __leave;
57     }
58     if ( pbPin == NULL )
59     {
60     Trace(WINEVENT_LEVEL_ERROR, L"pbPin == NULL");
61     dwReturn = SCARD_E_INVALID_PARAMETER;
62     __leave;
63     }
64     dwReturn = CheckContext(pCardData);
65     if ( dwReturn )
66     {
67     Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
68     dwReturn = SCARD_E_INVALID_PARAMETER;
69     __leave;
70     }
71     if ( wcscmp(pwszUserId, wszCARD_USER_USER) == 0 )
72     {
73     dwReturn = CheckPinLength(pCardData, ROLE_USER, cbPin);
74     if (dwReturn)
75     {
76     __leave;
77     }
78     dwReturn = VerifyPIN(pCardData, ROLE_USER, pbPin, cbPin);
79     if (pcAttemptsRemaining)
80     {
81     GetRemainingPin(pCardData, ROLE_USER, pcAttemptsRemaining);
82     }
83     }
84     else if ( wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0)
85     {
86     dwReturn = CheckPinLength(pCardData, ROLE_ADMIN, cbPin);
87     if (dwReturn)
88     {
89     __leave;
90     }
91     dwReturn = VerifyPIN(pCardData, ROLE_ADMIN, pbPin, cbPin);
92     if (pcAttemptsRemaining)
93     {
94     GetRemainingPin(pCardData, ROLE_ADMIN, pcAttemptsRemaining);
95     }
96     }
97     else
98     {
99     Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId unknown : %s", pwszUserId);
100     dwReturn = SCARD_E_INVALID_PARAMETER;
101     __leave;
102     }
103    
104     }
105     __finally
106     {
107     }
108     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
109     return dwReturn;
110     }
111    
112     /** A card principal can be authenticated by using either a PIN
113     or a challenge/response protocol in which the card generates a block
114     of challenge data by using its administrative key. The authenticating
115     caller must compute the response to the challenge by using shared
116     knowledge of that key and submit the response back to the card.
117     If the response is correct, the principal is authenticated to the card. */
118    
119     DWORD WINAPI CardGetChallenge(
120     __in PCARD_DATA pCardData,
121     __deref_out_bcount(*pcbChallengeData) PBYTE *ppbChallengeData,
122     __out PDWORD pcbChallengeData
123     )
124     {
125     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
126     return SCARD_E_UNSUPPORTED_FEATURE;
127     }
128    
129     /** The CardAuthenticateChallenge function performs authentication of
130     a card principal by using a challenge/response protocol. The caller of
131     this function must have previously called CardGetChallenge to retrieve
132     the challenge data from the card and computed the correct response data
133     to submit with this call. */
134    
135     DWORD WINAPI CardAuthenticateChallenge(
136     __in PCARD_DATA pCardData,
137     __in_bcount(cbResponseData) PBYTE pbResponseData,
138     __in DWORD cbResponseData,
139     __out_opt PDWORD pcAttemptsRemaining
140     )
141     {
142     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
143     return SCARD_E_UNSUPPORTED_FEATURE;
144     }
145    
146     /** The CardDeauthenticate function is an optional export that should be
147     provided if it is possible within the card minidriver to efficiently reverse
148     the effect of authenticating a user or administrator without resetting
149     the card. If this function is not implemented, the card minidriver should
150     put NULL in the CARD_DATA structure pointer for this function.
151     The Base CSP/KSP tests this pointer for NULL value before calling it. If it
152     is found NULL, the Base CSP/KSP deauthenticates a user by resetting the
153     card. Because a card reset is a time-consuming operation, the card minidriver
154     should implement this function if it can be done.
155     */
156    
157     DWORD WINAPI CardDeauthenticate(
158     __in PCARD_DATA pCardData,
159     __in LPWSTR pwszUserId,
160     __in DWORD dwFlags
161     )
162     {
163     DWORD dwReturn = 0;
164     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
165     __try
166     {
167     if ( pCardData == NULL )
168     {
169     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
170     dwReturn = SCARD_E_INVALID_PARAMETER;
171     __leave;
172     }
173     if ( pwszUserId == NULL )
174     {
175     Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId == NULL");
176     dwReturn = SCARD_E_INVALID_PARAMETER;
177     __leave;
178     }
179     if ( dwFlags != 0 )
180     {
181     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags != 0 : %d", dwFlags);
182     dwReturn = SCARD_E_INVALID_PARAMETER;
183     __leave;
184     }
185     dwReturn = CheckContext(pCardData);
186     if ( dwReturn )
187     {
188     Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
189     dwReturn = SCARD_E_INVALID_PARAMETER;
190     __leave;
191     }
192     dwReturn = Deauthenticate(pCardData);
193     }
194     __finally
195     {
196     }
197     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
198     return dwReturn;
199     }
200    
201     /** The CardAuthenticateEx function handles PIN authentication operations to the card.
202     This function replaces the CardAuthenticate function of earlier versions of these
203     specifications and adds support for the following PIN types:
204     • External PINs, which are PINs that are accessed from a device that is connected to the computer.
205     • Challenge/response PINs.
206     • Secure PIN channels.
207     • Session PINs.
208     */
209     DWORD WINAPI CardAuthenticateEx(
210     __in PCARD_DATA pCardData,
211     __in PIN_ID PinId,
212     __in DWORD dwFlags,
213     __in_bcount(cbPinData) PBYTE pbPinData,
214     __in DWORD cbPinData,
215     __deref_opt_out_bcount(*pcbSessionPin) PBYTE *ppbSessionPin,
216     __out_opt PDWORD pcbSessionPin,
217     __out_opt PDWORD pcAttemptsRemaining
218     )
219     {
220     DWORD dwReturn = 0;
221     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter authenticate %d", PinId);
222     __try
223     {
224     if ( pCardData == NULL )
225     {
226     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
227     dwReturn = SCARD_E_INVALID_PARAMETER;
228     __leave;
229     }
230     if ( pbPinData == NULL )
231     {
232     Trace(WINEVENT_LEVEL_ERROR, L"pbPinData == NULL");
233     dwReturn = SCARD_E_INVALID_PARAMETER;
234     __leave;
235     }
236     if ((dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN)
237     || (dwFlags & CARD_AUTHENTICATE_SESSION_PIN))
238     {
239     if ( ( ppbSessionPin == NULL ) ||
240     ( pcbSessionPin == NULL ) )
241     {
242     Trace(WINEVENT_LEVEL_ERROR, L"ppbSessionPin == NULL");
243     dwReturn = SCARD_E_INVALID_PARAMETER;
244     __leave;
245     }
246     else
247     {
248     Trace(WINEVENT_LEVEL_ERROR, L"SESSION_PIN SCARD_E_UNSUPPORTED_FEATURE");
249     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
250     __leave;
251     }
252     }
253     dwReturn = CheckContext(pCardData);
254     if ( dwReturn )
255     {
256     Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
257     dwReturn = SCARD_E_INVALID_PARAMETER;
258     __leave;
259     }
260     dwReturn = CheckPinLength(pCardData, PinId, cbPinData);
261     if (dwReturn)
262     {
263     __leave;
264     }
265     dwReturn = VerifyPIN(pCardData, PinId, pbPinData, cbPinData);
266     if (pcAttemptsRemaining)
267     {
268     GetRemainingPin(pCardData, PinId, pcAttemptsRemaining);
269     }
270     }
271     __finally
272     {
273     }
274     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
275     return dwReturn;
276     }
277    
278     /** Besides authentication by using a PIN, a card principal can be authenticated
279     by using a challenge/response protocol in which the card generates a block of challenge data.
280     The authenticating caller must compute the response to the challenge by using
281     shared knowledge of a key and submit the response back to the card by calling
282     CardGetChallengeEx. If the response is correct, the principal is authenticated to the card.
283     */
284    
285     DWORD WINAPI CardGetChallengeEx(
286     __in PCARD_DATA pCardData,
287     __in PIN_ID PinId,
288     __deref_out_bcount(*pcbChallengeData) PBYTE *ppbChallengeData,
289     __out PDWORD pcbChallengeData,
290     __in DWORD dwFlags
291     )
292     {
293     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
294     return SCARD_E_UNSUPPORTED_FEATURE;
295     }
296    
297     /** The CardDeauthenticateEx function must always be provided. If it is not
298     possible within the card minidriver to efficiently reverse the effect of an
299     authentication operation without resetting the card, the call must return
300     SCARD_E_UNSUPPORTED_FEATURE. In this situation, the Base CSP/KSP performs
301     deauthentication by resetting the card. Because a card reset is a time-consuming
302     operation, the card minidriver must implement this function if it can be done.*/
303    
304     DWORD WINAPI CardDeauthenticateEx(
305     __in PCARD_DATA pCardData,
306     __in PIN_SET PinId,
307     __in DWORD dwFlags
308     )
309     {
310     DWORD dwReturn = 0;
311     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
312     __try
313     {
314     if ( pCardData == NULL )
315     {
316     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
317     dwReturn = SCARD_E_INVALID_PARAMETER;
318     __leave;
319     }
320     if ( dwFlags != 0 )
321     {
322     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags != 0 : %d", dwFlags);
323     dwReturn = SCARD_E_INVALID_PARAMETER;
324     __leave;
325     }
326     dwReturn = CheckContext(pCardData);
327     if ( dwReturn )
328     {
329     Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
330     dwReturn = SCARD_E_INVALID_PARAMETER;
331     __leave;
332     }
333     dwReturn = Deauthenticate(pCardData);
334     }
335     __finally
336     {
337     }
338     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
339     return dwReturn;
340     }
341    
342     /** The CardUnblockPin function is used to unblock a card that has become
343     blocked by too many incorrect PIN entry attempts. The unblock function is
344     atomic in that authentication and unblocking the card must occur as a single
345     operation. Therefore, authentication information and the new user PIN must
346     be presented when the call is made.*/
347    
348     DWORD WINAPI CardUnblockPin(
349     __in PCARD_DATA pCardData,
350     __in LPWSTR pwszUserId,
351     __in_bcount(cbAuthenticationData) PBYTE pbAuthenticationData,
352     __in DWORD cbAuthenticationData,
353     __in_bcount(cbNewPinData) PBYTE pbNewPinData,
354     __in DWORD cbNewPinData,
355     __in DWORD cRetryCount,
356     __in DWORD dwFlags
357     )
358     {
359     DWORD dwReturn = 0;
360    
361     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
362     __try
363     {
364     if ( pCardData == NULL )
365     {
366     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
367     dwReturn = SCARD_E_INVALID_PARAMETER;
368     __leave;
369     }
370     if ( pwszUserId == NULL )
371     {
372     Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId == NULL");
373     dwReturn = SCARD_E_INVALID_PARAMETER;
374     __leave;
375     }
376     if ( pbAuthenticationData == NULL )
377     {
378     Trace(WINEVENT_LEVEL_ERROR, L"pbAuthenticationData == NULL");
379     dwReturn = SCARD_E_INVALID_PARAMETER;
380     __leave;
381     }
382     if ( pbNewPinData == NULL )
383     {
384     Trace(WINEVENT_LEVEL_ERROR, L"pbNewPinData == NULL");
385     dwReturn = SCARD_E_INVALID_PARAMETER;
386     __leave;
387     }
388     if (!(dwFlags & CARD_AUTHENTICATE_PIN_PIN))
389     {
390     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
391     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags = 0x%08X", dwFlags);
392     __leave;
393     }
394     dwReturn = CheckContext(pCardData);
395     if ( !dwReturn )
396     {
397     Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
398     dwReturn = SCARD_E_INVALID_PARAMETER;
399     __leave;
400     }
401     if ( wcscmp(pwszUserId, wszCARD_USER_USER) == 0 )
402     {
403     dwReturn = ResetUserPIN(pCardData, ROLE_PUK,
404     pbAuthenticationData, cbAuthenticationData,
405     pbNewPinData, cbNewPinData);
406     }
407     else if ( wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0)
408     {
409     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
410     Trace(WINEVENT_LEVEL_ERROR, L"wszCARD_USER_ADMIN");
411     __leave;
412     }
413     else
414     {
415     Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId unknown : %s", pwszUserId);
416     dwReturn = SCARD_E_INVALID_PARAMETER;
417     __leave;
418     }
419     }
420     __finally
421     {
422     }
423     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
424     return dwReturn;
425     }
426    
427     /** This function changes the authenticator for the affected card principal.
428     It can be used to change a user’s PIN or to change the challenge/response key.
429     The two usages are distinguished by use of a flag value.*/
430    
431     DWORD WINAPI CardChangeAuthenticator(
432     __in PCARD_DATA pCardData,
433     __in LPWSTR pwszUserId,
434     __in_bcount(cbCurrentAuthenticator)
435     PBYTE pbCurrentAuthenticator,
436     __in DWORD cbCurrentAuthenticator,
437     __in_bcount(cbNewAuthenticator) PBYTE pbNewAuthenticator,
438     __in DWORD cbNewAuthenticator,
439     __in DWORD cRetryCount,
440     __in DWORD dwFlags,
441     __out_opt PDWORD pcAttemptsRemaining
442     )
443     {
444     DWORD dwReturn = 0;
445    
446     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
447     __try
448     {
449     if ( pCardData == NULL )
450     {
451     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
452     dwReturn = SCARD_E_INVALID_PARAMETER;
453     __leave;
454     }
455     if ( pwszUserId == NULL )
456     {
457     Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId == NULL");
458     dwReturn = SCARD_E_INVALID_PARAMETER;
459     __leave;
460     }
461     if ( pbCurrentAuthenticator == NULL )
462     {
463     Trace(WINEVENT_LEVEL_ERROR, L"pbCurrentAuthenticator == NULL");
464     dwReturn = SCARD_E_INVALID_PARAMETER;
465     __leave;
466     }
467     if ( pbNewAuthenticator == NULL )
468     {
469     Trace(WINEVENT_LEVEL_ERROR, L"pbNewAuthenticator == NULL");
470     dwReturn = SCARD_E_INVALID_PARAMETER;
471     __leave;
472     }
473     if (!(dwFlags & CARD_AUTHENTICATE_PIN_PIN))
474     {
475     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
476     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags = 0x%08X", dwFlags);
477     __leave;
478     }
479     dwReturn = CheckContext(pCardData);
480     if ( !dwReturn )
481     {
482     Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
483     dwReturn = SCARD_E_INVALID_PARAMETER;
484     __leave;
485     }
486     if ( wcscmp(pwszUserId, wszCARD_USER_USER) == 0 )
487     {
488     dwReturn = ChangePIN(pCardData, ROLE_USER,
489     pbCurrentAuthenticator, cbCurrentAuthenticator,
490     pbNewAuthenticator, cbNewAuthenticator);
491     if (pcAttemptsRemaining)
492     {
493     GetRemainingPin(pCardData, ROLE_USER, pcAttemptsRemaining);
494     }
495     }
496     else if ( wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0)
497     {
498     dwReturn = ChangePIN(pCardData, ROLE_ADMIN,
499     pbCurrentAuthenticator, cbCurrentAuthenticator,
500     pbNewAuthenticator, cbNewAuthenticator);
501     if (pcAttemptsRemaining)
502     {
503     GetRemainingPin(pCardData,ROLE_ADMIN, pcAttemptsRemaining);
504     }
505     }
506     else
507     {
508     Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId unknown : %s", pwszUserId);
509     dwReturn = SCARD_E_INVALID_PARAMETER;
510     __leave;
511     }
512     }
513     __finally
514     {
515     }
516     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
517     return dwReturn;
518     }
519    
520    
521     /** This function changes the authenticator for the affected card principal.
522     It can be used to change a PIN or unblock a PIN. The usages are distinguished
523     by use of a flag value.*/
524    
525     DWORD WINAPI CardChangeAuthenticatorEx(
526     __in PCARD_DATA pCardData,
527     __in DWORD dwFlags,
528     __in PIN_ID dwAuthenticatingPinId,
529     __in_bcount(cbAuthenticatingPinData)
530     PBYTE pbAuthenticatingPinData,
531     __in DWORD cbAuthenticatingPinData,
532     __in PIN_ID dwTargetPinId,
533     __in_bcount(cbTargetData) PBYTE pbTargetData,
534     __in DWORD cbTargetData,
535     __in DWORD cRetryCount,
536     __out_opt PDWORD pcAttemptsRemaining
537     )
538     {
539     DWORD dwReturn = 0;
540    
541     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
542     __try
543     {
544     if ( pCardData == NULL )
545     {
546     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
547     dwReturn = SCARD_E_INVALID_PARAMETER;
548     __leave;
549     }
550     if ( pbAuthenticatingPinData == NULL )
551     {
552     Trace(WINEVENT_LEVEL_ERROR, L"pbAuthenticatingPinData == NULL");
553     dwReturn = SCARD_E_INVALID_PARAMETER;
554     __leave;
555     }
556     if ( pbTargetData == NULL )
557     {
558     Trace(WINEVENT_LEVEL_ERROR, L"pbTargetData == NULL");
559     dwReturn = SCARD_E_INVALID_PARAMETER;
560     __leave;
561     }
562     if (!(dwFlags & CARD_AUTHENTICATE_PIN_PIN))
563     {
564     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
565     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags = 0x%08X", dwFlags);
566     __leave;
567     }
568     dwReturn = CheckContext(pCardData);
569     if ( !dwReturn )
570     {
571     Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
572     dwReturn = SCARD_E_INVALID_PARAMETER;
573     __leave;
574     }
575     if ( dwAuthenticatingPinId == dwTargetPinId)
576     {
577     dwReturn = ChangePIN(pCardData, dwAuthenticatingPinId,
578     pbAuthenticatingPinData, cbAuthenticatingPinData,
579     pbTargetData, cbTargetData);
580     if (pcAttemptsRemaining)
581     {
582     GetRemainingPin(pCardData, dwAuthenticatingPinId, pcAttemptsRemaining);
583     }
584     }
585     else if ( dwAuthenticatingPinId == ROLE_ADMIN && dwTargetPinId == ROLE_USER)
586     {
587     dwReturn = ResetUserPIN(pCardData, ROLE_ADMIN,
588     pbAuthenticatingPinData, cbAuthenticatingPinData,
589     pbTargetData, cbTargetData);
590     if (pcAttemptsRemaining)
591     {
592     GetRemainingPin(pCardData,dwTargetPinId, pcAttemptsRemaining);
593     }
594     }
595     else
596     {
597     Trace(WINEVENT_LEVEL_ERROR, L"unknown role match: %d %d", dwAuthenticatingPinId, dwTargetPinId);
598     dwReturn = SCARD_E_INVALID_PARAMETER;
599     __leave;
600     }
601     }
602     __finally
603     {
604     }
605     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
606     return dwReturn;
607     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26