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

Annotation of /trunk/OpenPGPminidriver/CardAndContainerProperties.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: 16301 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 "CryptoOperations.h"
23     #include "PinOperations.h"
24    
25     // 4.4 Card capabilities
26    
27     /** This function queries the card and card-specific minidriver combination
28     for the functionality that is provided at this level, such as certificate or
29     file compression.*/
30    
31     DWORD WINAPI CardQueryCapabilities(
32     __in PCARD_DATA pCardData,
33     __inout PCARD_CAPABILITIES pCardCapabilities
34     )
35     {
36     DWORD dwReturn = 0, dwVersion;
37     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
38     __try
39     {
40     if ( pCardData == NULL )
41     {
42     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
43     dwReturn = SCARD_E_INVALID_PARAMETER;
44     __leave;
45     }
46     if ( pCardCapabilities == NULL )
47     {
48     Trace(WINEVENT_LEVEL_ERROR, L"pCardCapabilities == NULL");
49     dwReturn = SCARD_E_INVALID_PARAMETER;
50     __leave;
51     }
52     dwVersion = (pCardCapabilities->dwVersion == 0) ? 1 : pCardCapabilities->dwVersion;
53     if ( dwVersion != CARD_CAPABILITIES_CURRENT_VERSION )
54     {
55     Trace(WINEVENT_LEVEL_ERROR, L"dwVersion %d", dwVersion);
56     dwReturn = ERROR_REVISION_MISMATCH;
57     __leave;
58     }
59     pCardCapabilities->fCertificateCompression = TRUE;
60     pCardCapabilities->fKeyGen = TRUE;
61     dwReturn = 0;
62     }
63     __finally
64     {
65     }
66     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
67     return dwReturn;
68     }
69    
70     // 4.5 Card and container properties
71    
72     /** The CardGetContainerProperty function is modeled after the query
73     functions of CAPI for keys. It takes a LPWSTR that indicates which parameter
74     is being requested. Then it returns data written into the pbData parameter.*/
75    
76     DWORD WINAPI CardGetContainerProperty(
77     __in PCARD_DATA pCardData,
78     __in BYTE bContainerIndex,
79     __in LPCWSTR wszProperty,
80     __out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData,
81     __in DWORD cbData,
82     __out PDWORD pdwDataLen,
83     __in DWORD dwFlags
84     )
85     {
86     DWORD dwReturn = 0;
87     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter bContainerIndex = %d wszProperty = %s", bContainerIndex, wszProperty);
88     __try
89     {
90     if ( pCardData == NULL )
91     {
92     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
93     dwReturn = SCARD_E_INVALID_PARAMETER;
94     __leave;
95     }
96     if ( pdwDataLen == NULL )
97     {
98     Trace(WINEVENT_LEVEL_ERROR, L"pdwDataLen == NULL");
99     dwReturn = SCARD_E_INVALID_PARAMETER;
100     __leave;
101     }
102     if ( wszProperty == NULL )
103     {
104     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == NULL");
105     dwReturn = SCARD_E_INVALID_PARAMETER;
106     __leave;
107     }
108     if (dwFlags)
109     {
110     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
111     dwReturn = SCARD_E_INVALID_PARAMETER;
112     __leave;
113     }
114     if (bContainerIndex >= MaxContainer)
115     {
116     Trace(WINEVENT_LEVEL_ERROR, L"bContainerIndex == %d", bContainerIndex);
117     dwReturn = SCARD_E_NO_KEY_CONTAINER ;
118     __leave;
119     }
120     if (wcscmp(wszProperty,CCP_CONTAINER_INFO) == 0)
121     {
122     if (cbData < sizeof(CONTAINER_INFO))
123     {
124     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
125     dwReturn = ERROR_INSUFFICIENT_BUFFER;
126     __leave;
127     }
128     *pdwDataLen = cbData;
129     dwReturn = CardGetContainerInfo(pCardData, bContainerIndex, dwFlags, (PCONTAINER_INFO) pbData);
130     }
131     else if (wcscmp(wszProperty,CCP_PIN_IDENTIFIER) == 0)
132     {
133     if (cbData < sizeof(PIN_ID))
134     {
135     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
136     dwReturn = ERROR_INSUFFICIENT_BUFFER;
137     __leave;
138     }
139     *pdwDataLen = cbData;
140     if(bContainerIndex < MaxContainer)
141     {
142     dwReturn = SCARD_E_NO_KEY_CONTAINER;
143     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", bContainerIndex);
144     __leave;
145     }
146     (*(PDWORD)pbData) = Containers[bContainerIndex].PinId;
147     dwReturn = 0;
148     }
149     /*else if (wcscmp(wszProperty,CCP_ASSOCIATED_ECDH_KEY) == 0)
150     {
151     }*/
152     else
153     {
154     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s", wszProperty);
155     dwReturn = SCARD_E_INVALID_PARAMETER;
156     __leave;
157     }
158     }
159     __finally
160     {
161     }
162     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
163     return dwReturn;
164     }
165    
166     /** This function sets the properties on containers. Only two container
167     properties are supported:
168     • CCP_PIN_IDENTIFIER
169     • CCP_ASSOCIATED_ECDH_KEY
170     */
171    
172     DWORD WINAPI CardSetContainerProperty(
173     __in PCARD_DATA pCardData,
174     __in BYTE bContainerIndex,
175     __in LPCWSTR wszProperty,
176     __in_bcount(cbDataLen) PBYTE pbData,
177     __in DWORD cbDataLen,
178     __in DWORD dwFlags
179     )
180     {
181     DWORD dwReturn = 0;
182     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter bContainerIndex = %d wszProperty = %s", bContainerIndex, wszProperty);
183     __try
184     {
185     if ( pCardData == NULL )
186     {
187     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
188     dwReturn = SCARD_E_INVALID_PARAMETER;
189     __leave;
190     }
191     if ( wszProperty == NULL )
192     {
193     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == NULL");
194     dwReturn = SCARD_E_INVALID_PARAMETER;
195     __leave;
196     }
197     if ( pbData == NULL )
198     {
199     Trace(WINEVENT_LEVEL_ERROR, L"pbData == NULL");
200     dwReturn = SCARD_E_INVALID_PARAMETER;
201     __leave;
202     }
203     if (dwFlags)
204     {
205     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
206     dwReturn = SCARD_E_INVALID_PARAMETER;
207     __leave;
208     }
209     if (wcscmp(wszProperty,CCP_PIN_IDENTIFIER) == 0)
210     {
211     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
212     __leave;
213     }
214     else if (wcscmp(wszProperty,CCP_ASSOCIATED_ECDH_KEY) == 0)
215     {
216     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
217     __leave;
218     }
219     else
220     {
221     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s", wszProperty);
222     dwReturn = SCARD_E_INVALID_PARAMETER;
223     __leave;
224     }
225    
226     }
227     __finally
228     {
229     }
230     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
231     return dwReturn;
232     }
233    
234     /** The CardGetProperty function is modeled after the query functions of
235     CAPI for keys. It takes a LPWSTR that indicates which parameter is being
236     requested. The function returns data in the pbData parameter.*/
237    
238     DWORD WINAPI CardGetProperty(
239     __in PCARD_DATA pCardData,
240     __in LPCWSTR wszProperty,
241     __out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData,
242     __in DWORD cbData,
243     __out PDWORD pdwDataLen,
244     __in DWORD dwFlags
245     )
246     {
247     DWORD dwReturn = 0;
248     PBYTE pbTempData = NULL;
249     DWORD dwTempSize = 0;
250     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter wszProperty = %s", wszProperty);
251     __try
252     {
253     if ( pCardData == NULL )
254     {
255     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
256     dwReturn = SCARD_E_INVALID_PARAMETER;
257     __leave;
258     }
259     if ( wszProperty == NULL )
260     {
261     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == NULL");
262     dwReturn = SCARD_E_INVALID_PARAMETER;
263     __leave;
264     }
265     if ( pdwDataLen == NULL )
266     {
267     Trace(WINEVENT_LEVEL_ERROR, L"pdwDataLen == NULL");
268     dwReturn = SCARD_E_INVALID_PARAMETER;
269     __leave;
270     }
271     if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0)
272     {
273     *pdwDataLen = sizeof(CARD_FREE_SPACE_INFO);
274     if (cbData < *pdwDataLen)
275     {
276     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
277     dwReturn = ERROR_INSUFFICIENT_BUFFER;
278     __leave;
279     }
280     dwReturn = CardQueryFreeSpace(pCardData, dwFlags, (PCARD_FREE_SPACE_INFO) pbData);
281     }
282     else if (wcscmp(wszProperty,CP_CARD_CAPABILITIES) == 0)
283     {
284     *pdwDataLen = sizeof(CARD_CAPABILITIES);
285     if (cbData < *pdwDataLen)
286     {
287     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
288     dwReturn = ERROR_INSUFFICIENT_BUFFER;
289     __leave;
290     }
291     dwReturn = CardQueryCapabilities(pCardData, (PCARD_CAPABILITIES) pbData);
292     }
293     else if (wcscmp(wszProperty,CP_CARD_KEYSIZES) == 0)
294     {
295     *pdwDataLen = sizeof(CARD_KEY_SIZES);
296     if (cbData < *pdwDataLen)
297     {
298     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
299     dwReturn = ERROR_INSUFFICIENT_BUFFER;
300     __leave;
301     }
302     dwReturn = CardQueryKeySizes(pCardData, dwFlags, 0, (PCARD_KEY_SIZES) pbData);
303     }
304     else if (wcscmp(wszProperty,CP_CARD_READ_ONLY) == 0)
305     {
306     *pdwDataLen = sizeof(BOOL);
307     if (cbData < *pdwDataLen)
308     {
309     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
310     dwReturn = ERROR_INSUFFICIENT_BUFFER;
311     __leave;
312     }
313     *((PBOOL)pbData) = TRUE;
314     }
315     else if (wcscmp(wszProperty,CP_CARD_CACHE_MODE) == 0)
316     {
317     *pdwDataLen = sizeof(DWORD);
318     if (cbData < *pdwDataLen)
319     {
320     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
321     dwReturn = ERROR_INSUFFICIENT_BUFFER;
322     __leave;
323     }
324     *((PDWORD)pbData) = CP_CACHE_MODE_NO_CACHE;
325     }
326     else if (wcscmp(wszProperty,CP_SUPPORTS_WIN_X509_ENROLLMENT) == 0)
327     {
328     *pdwDataLen = sizeof(BOOL);
329     if (cbData < *pdwDataLen)
330     {
331     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
332     dwReturn = ERROR_INSUFFICIENT_BUFFER;
333     __leave;
334     }
335     *((PBOOL)pbData) = FALSE;
336     }
337     else if (wcscmp(wszProperty,CP_CARD_GUID) == 0)
338     {
339     dwReturn = CardReadFile(pCardData, NULL, szCARD_IDENTIFIER_FILE, 0, &pbTempData, &dwTempSize);
340     if (dwReturn)
341     {
342     __leave;
343     }
344     *pdwDataLen = dwTempSize;
345     if (cbData < *pdwDataLen)
346     {
347     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
348     dwReturn = ERROR_INSUFFICIENT_BUFFER;
349     __leave;
350     }
351     memcpy(pbData, pbTempData, dwTempSize);
352     }
353     else if (wcscmp(wszProperty,CP_CARD_SERIAL_NO) == 0)
354     {
355     *pdwDataLen = sizeof(OPENPGP_AID);
356     if (cbData < *pdwDataLen)
357     {
358     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
359     dwReturn = ERROR_INSUFFICIENT_BUFFER;
360     __leave;
361     }
362     memcpy(pbData, &(((POPENPGP_CONTEXT)pCardData->pvVendorSpecific)->Aid), sizeof(OPENPGP_AID));
363     dwReturn = 0;
364     }
365     else if (wcscmp(wszProperty,CP_CARD_PIN_INFO) == 0)
366     {
367     PPIN_INFO pPinInfo;
368     *pdwDataLen = sizeof(PIN_INFO);
369     if (cbData < *pdwDataLen)
370     {
371     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
372     dwReturn = ERROR_INSUFFICIENT_BUFFER;
373     __leave;
374     }
375     pPinInfo = (PPIN_INFO) pbData;
376     dwReturn = GetPinInfo(dwFlags, pPinInfo);
377     }
378     else if (wcscmp(wszProperty,CP_CARD_LIST_PINS) == 0)
379     {
380     PPIN_SET pPinSet;
381     *pdwDataLen = sizeof(PIN_SET);
382     if (cbData < *pdwDataLen)
383     {
384     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
385     dwReturn = ERROR_INSUFFICIENT_BUFFER;
386     __leave;
387     }
388     pPinSet = (PPIN_SET) pbData;
389     }
390     else if (wcscmp(wszProperty,CP_CARD_AUTHENTICATED_STATE) == 0)
391     {
392     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
393     }
394     else if (wcscmp(wszProperty,CP_CARD_PIN_STRENGTH_VERIFY) == 0)
395     {
396     PPIN_SET pPinSet;
397     *pdwDataLen = sizeof(PIN_SET);
398     if (cbData < *pdwDataLen)
399     {
400     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
401     dwReturn = ERROR_INSUFFICIENT_BUFFER;
402     __leave;
403     }
404     pPinSet = (PPIN_SET) pbData;
405     *pPinSet = CARD_PIN_STRENGTH_PLAINTEXT;
406     }
407     else if (wcscmp(wszProperty,CP_KEY_IMPORT_SUPPORT) == 0)
408     {
409     *pdwDataLen = sizeof(DWORD);
410     if (cbData < *pdwDataLen)
411     {
412     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
413     dwReturn = ERROR_INSUFFICIENT_BUFFER;
414     __leave;
415     }
416     *((PDWORD)pbData) = CARD_KEY_IMPORT_RSA_KEYEST;
417     }
418     else if (wcscmp(wszProperty,CP_ENUM_ALGORITHMS ) == 0)
419     {
420     if (dwFlags == CARD_CIPHER_OPERATION)
421     {
422     *pdwDataLen = sizeof(OPENPGP_SUPPORTED_CYPHER_ALGORITHM);
423     if (cbData < *pdwDataLen)
424     {
425     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
426     dwReturn = ERROR_INSUFFICIENT_BUFFER;
427     __leave;
428     }
429     memcpy(pbData,OPENPGP_SUPPORTED_CYPHER_ALGORITHM,*pdwDataLen);
430     }
431     else if (dwFlags == CARD_ASYMMETRIC_OPERATION )
432     {
433     *pdwDataLen = sizeof(OPENPGP_SUPPORTED_ASYMETRIC_ALGORITHM);
434     if (cbData < *pdwDataLen)
435     {
436     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
437     dwReturn = ERROR_INSUFFICIENT_BUFFER;
438     __leave;
439     }
440     memcpy(pbData,OPENPGP_SUPPORTED_ASYMETRIC_ALGORITHM,*pdwDataLen);
441     }
442     else
443     {
444     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
445     dwReturn = SCARD_E_INVALID_PARAMETER;
446     }
447     }
448     else if (wcscmp(wszProperty,CP_PADDING_SCHEMES ) == 0)
449     {
450     if (dwFlags == CARD_CIPHER_OPERATION)
451     {
452     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
453     }
454     else if (dwFlags == CARD_ASYMMETRIC_OPERATION )
455     {
456     *pdwDataLen = sizeof(DWORD);
457     if (cbData < *pdwDataLen)
458     {
459     Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
460     dwReturn = ERROR_INSUFFICIENT_BUFFER;
461     __leave;
462     }
463     *((PDWORD)pbData) = CARD_PADDING_PKCS1;
464     }
465     else
466     {
467     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
468     dwReturn = SCARD_E_INVALID_PARAMETER;
469     }
470    
471     }
472     else if (wcscmp(wszProperty,CP_CHAINING_MODES ) == 0)
473     {
474     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
475     }
476     else
477     {
478     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s", wszProperty);
479     dwReturn = SCARD_E_INVALID_PARAMETER;
480     __leave;
481     }
482     }
483     __finally
484     {
485     if (pbTempData)
486     {
487     pCardData->pfnCspFree(pbTempData);
488     }
489     }
490     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
491     return dwReturn;
492     }
493    
494     /** This function can be used to set properties on the card.*/
495    
496     DWORD WINAPI CardSetProperty(
497     __in PCARD_DATA pCardData,
498     __in LPCWSTR wszProperty,
499     __in_bcount(cbDataLen) PBYTE pbData,
500     __in DWORD cbDataLen,
501     __in DWORD dwFlags
502     )
503     {
504     DWORD dwReturn = 0;
505     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter wszProperty = %s", wszProperty);
506     __try
507     {
508     if ( pCardData == NULL )
509     {
510     Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
511     dwReturn = SCARD_E_INVALID_PARAMETER;
512     __leave;
513     }
514     if ( wszProperty == NULL )
515     {
516     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == NULL");
517     dwReturn = SCARD_E_INVALID_PARAMETER;
518     __leave;
519     }
520     if (dwFlags)
521     {
522     Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
523     dwReturn = SCARD_E_INVALID_PARAMETER;
524     __leave;
525     }
526     if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0
527     || wcscmp(wszProperty,CP_CARD_CAPABILITIES) == 0
528     || wcscmp(wszProperty,CP_CARD_KEYSIZES) == 0
529     || wcscmp(wszProperty,CP_CARD_LIST_PINS) == 0
530     || wcscmp(wszProperty,CP_CARD_AUTHENTICATED_STATE) == 0
531     || wcscmp(wszProperty,CP_KEY_IMPORT_SUPPORT) == 0
532     || wcscmp(wszProperty,CP_ENUM_ALGORITHMS) == 0
533     || wcscmp(wszProperty,CP_PADDING_SCHEMES) == 0
534     || wcscmp(wszProperty,CP_CHAINING_MODES) == 0)
535     {
536     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s SCARD_E_UNSUPPORTED_FEATURE", wszProperty);
537     dwReturn = SCARD_E_UNSUPPORTED_FEATURE ;
538     __leave;
539     }
540     else if (wcscmp(wszProperty,CP_CARD_READ_ONLY) == 0)
541     {
542     dwReturn = SCARD_E_UNSUPPORTED_FEATURE ;
543     }
544     else if (wcscmp(wszProperty,CP_CARD_CACHE_MODE) == 0)
545     {
546     dwReturn = SCARD_E_UNSUPPORTED_FEATURE ;
547     }
548     else if (wcscmp(wszProperty,CP_SUPPORTS_WIN_X509_ENROLLMENT) == 0)
549     {
550     dwReturn = SCARD_E_UNSUPPORTED_FEATURE ;
551     }
552     else if (wcscmp(wszProperty,CP_CARD_GUID) == 0)
553     {
554     dwReturn = SCARD_E_UNSUPPORTED_FEATURE ;
555     }
556     else if (wcscmp(wszProperty,CP_CARD_SERIAL_NO) == 0)
557     {
558     dwReturn = SCARD_E_UNSUPPORTED_FEATURE ;
559     }
560     else if (wcscmp(wszProperty,CP_CARD_PIN_INFO) == 0)
561     {
562     dwReturn = SCARD_E_UNSUPPORTED_FEATURE ;
563     }
564     else if (wcscmp(wszProperty,CP_CARD_PIN_STRENGTH_VERIFY) == 0)
565     {
566     dwReturn = SCARD_E_UNSUPPORTED_FEATURE ;
567     }
568     else
569     {
570     Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s", wszProperty);
571     dwReturn = SCARD_E_INVALID_PARAMETER;
572     __leave;
573     }
574     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
575     }
576     __finally
577     {
578     }
579     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
580     return dwReturn;
581     }
582    

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26