PCSC那事儿(九--SCardEstablishContext)

SCardEstablishContext

305 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,

  306         LPCVOID pvReserved2, LPSCARDCONTEXT phContext)

  307 {

  308         LONG rv;

  309

  310         PROFILE_START

  311

  312         /* Check if the server is running */

  313         rv = SCardCheckDaemonAvailability();

  314         if (SCARD_E_INVALID_HANDLE == rv)

  315                  /* we reconnected to a daemon or we got called from a forked child */

  316                 rv = SCardCheckDaemonAvailability();

  317

  318         if (rv != SCARD_S_SUCCESS)

  319                 return rv;

  320

  321         (void) SCardLockThread ();

  322         rv = SCardEstablishContextTH (dwScope, pvReserved1,

  323                 pvReserved2, phContext);

  324         (void) SCardUnlockThread ();

  325

  326         PROFILE_END (rv)

  327

  328         return rv;

  329 }

 

 

312~319 都在 SCardCheckDaemonAvailability

也在 winscard_clnt.c 中实现。

3790 LONG SCardCheckDaemonAvailability(void)

3791 {

3792         LONG rv;

3793         struct stat statBuffer;

3794         int need_restart = 0;

3795

3796         rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);

3797

3798         if (rv != 0)

3799         {

3800                 Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s",

3801                         strerror(errno));

3802                 return SCARD_E_NO_SERVICE;

 

3803         }

3804

3805          /* when the _first_ reader is connected the ctime changes

3806          * I don't know why yet */

3807         if (daemon_ctime && statBuffer.st_ctime > daemon_ctime)

3808         {

3809                 /* so we also check the daemon pid to be sure it is a new pcscd */

3810                 if (GetDaemonPid() != daemon_pid)

3811                 {

3812                         Log1(PCSC_LOG_INFO, "PCSC restarted");

3813                         need_restart = 1;

3814                 }

3815         }

3816

3817         /* after fork() need to restart */

3818         if (client_pid && client_pid != getpid())

3819         {

3820                 Log1(PCSC_LOG_INFO, "Client forked");

3821                 need_restart = 1;

3822         }

3823

3824         if (need_restart)

3825         {

3826                 int i;

3827

3828                 /* invalid all handles */

3829                 (void)SCardLockThread();

3830

3831                 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)

3832                          if (psContextMap[i].hContext)

3833                                 (void)SCardCleanContext(i);

3834

3835                 (void)SCardUnlockThread();

3836

3837                 /* reset pcscd status */

3838                 daemon_ctime = 0;

3839                  client_pid = 0;

3840

3841                 /* reset the lib */

3842                 SCardUnload();

3843

3844                 return SCARD_E_INVALID_HANDLE;

3845         }

 

3846

3847         daemon_ctime = statBuffer.st_ctime;

3848         daemon_pid = GetDaemonPid();

3849         client_pid = getpid();

3850

3851         return SCARD_S_SUCCESS;

3852 }

 

 

pcscd.h:

#define PCSCLITE_PUBSHM_FILE          PCSCLITE_IPC_DIR "/pcscd.pub"

#define PCSCLITE_IPC_DIR  /var/run/pcscd

原来 PCSCLITE_PUBSHM_FILE 表示临时文件。

3896~3803 行,首先应用探测这个临时文件是否存在,如果不存在,就表示服务器 pcscd 例程还没有启动。

原因是 pcscd 启动的时候会创建这个临时文件。

 

先启动 pcscd ,再启动 testpcsc 后, daemon_ctime daemon_pid client_pid

都是 0. 所以

3807 行,条件判断无法成立。

3818 行,也无法成立,则越过 3824 行,并首次

对以上 3 个变量进行了初始化。

如果启动 pcscd 后,再启动 testpcsc, 但是正如

3805~3815 行, pcscd 因为某种原因,重新启动或者正如

3817~3822 行,应用

本身 clone 自身,则 need_restart=1

 

回到 SCardEstablishContext, 再次出现调用 SCardCheckDaemonAvailability

313~316 行,处理处理上一次 SCardCheckDaemonAvailability 调用过程中 need_restart 等于 1 的情况,

因为上一次调用 SCardCheckDaemonAvailability 如果 need_restart 等于 1 ,则会返回 SCARD_E_INVALID_HANDLE, 引起第二次调用 SCardCheckDaemonAvailability.

目的是正确设置 daemon_ctime daemon_pid client_pid 这些变量。

 

 

 

SCardEstablishContext 就做了这些,加锁后,然后代理给 SCardEstablishContextTH.

  357 static LONG SCardEstablishContextTH(DWORD dwScope,

  358         /*@unused@*/ LPCVOID pvReserved1,

  359         /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)

  360 {

  361         LONG rv;

  362         int i;

  363         establish_struct scEstablishStruct;

  364         sharedSegmentMsg msgStruct;

  365         uint32_t dwClientID = 0;

  366

  367         (void)pvReserved1;

  368         (void)pvReserved2;

 

  369         if (phContext == NULL)

 

  370                 return SCARD_E_INVALID_PARAMETER;

  371         else

  372                 *phContext = 0;

  373

  374          /*

  375          * Do this only once:

  376          * - Initialize debug of need.

  377          * - Set up the memory mapped structures for reader states.

  378          * - Allocate each reader structure.

  379          * - Initialize context struct.

  380           */

  381         if (isExecuted == 0)

  382         {

  383                 int pageSize;

  384

  385                 /*

  386                  * Do any system initilization here

  387                  */

  388                 (void)SYS_Initialize();

  389

  390                 /*

  391                  * Set up the memory mapped reader stats structures

  392                  */

  393                 mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);

  394                 if (mapAddr < 0)

  395                  {

  396                         Log3(PCSC_LOG_CRITICAL, "Cannot open public shared file %s: %s",

  397                                 PCSCLITE_PUBSHM_FILE, strerror(errno));

  398                         return SCARD_E_NO_SERVICE;

  399                  }

  400

  401                 /* close on exec so that child processes do not inherits the file

  402                  * descriptor. The child process will call SCardEstablishContext()

  403                  * if needed. */

 

  404                 (void)fcntl(mapAddr, F_SETFD, FD_CLOEXEC);

  405

  406                 pageSize = SYS_GetPageSize();

  407

  408                 /*

 

  409                  * Allocate each reader structure in the memory map

 

  410                  */

  411                 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

  412                 {

  413                         readerStates[i] =

  414                                 (PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),

  415                                 mapAddr, (i * pageSize));

  416                         if (readerStates[i] == NULL)

  417                         {

  418                                 Log2(PCSC_LOG_CRITICAL, "Cannot public memory map: %s",

  419                                         strerror(errno));

  420                                 (void)SYS_CloseFile(mapAddr);   /* Close the memory map file */

  421                                 return SCARD_F_INTERNAL_ERROR;

  422                         }

  423                 }

  424

  425                 /*

  426                   * Initializes the application contexts and all channels for each one

  427                  */

  428                 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)

  429                 {

  430                         int j;

  431

  432                          /*

  433                          * Initially set the context struct to zero

  434                          */

  435                         psContextMap[i].dwClientID = 0;

  436                         psContextMap[i].hContext = 0;

  437                         psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;

  438                         psContextMap[i].mMutex = NULL;

  439

  440                         for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)

  441                          {

  442                                 /*

  443                                  * Initially set the hcard structs to zero

  444                                  */

  445                                 psContextMap[i].psChannelMap[j].hCard = 0;

  446                                 psContextMap[i].psChannelMap[j].readerName = NULL;

  447                         }

  448                 }

 

  449

  450         }

  451

  452         /*

  453          * Is there a free slot for this connection ?

  454           */

  455

  456         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)

  457         {

  458                 if (psContextMap[i].dwClientID == 0)

  459                         break;

  460         }

  461

  462         if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)

  463         {

  464                 return SCARD_E_NO_MEMORY;

  465         }

  466

  467         /* Establishes a connection to the server */

  468         if (SHMClientSetupSession(&dwClientID) != 0)

  469         {

  470                 (void)SYS_CloseFile(mapAddr);

  471                 return SCARD_E_NO_SERVICE;

  472         }

  473

  474         {       /* exchange client/server protocol versions */

  475                 version_struct *veStr;

  476

  477                 memset(&msgStruct, 0, sizeof(msgStruct));

  478                 msgStruct.mtype = CMD_VERSION;

  479                 msgStruct.user_id = SYS_GetUID();

  480                 msgStruct.group_id = SYS_GetGID();

  481                 msgStruct.command = 0;

  482                 msgStruct.date = time(NULL);

  483

  484                 veStr = &msgStruct.veStr;

  485                 veStr->major = PROTOCOL_VERSION_MAJOR;

  486                 veStr->minor = PROTOCOL_VERSION_MINOR;

  487

  488                 if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,

  489                         PCSCLITE_MCLIENT_ATTEMPTS))

  490                         return SCARD_E_NO_SERVICE;

  491

 

  492                 /*

  493                  * Read a message from the server

  494                  */

  495                 if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,

  496                         PCSCLITE_CLIENT_ATTEMPTS))

  497                 {

  498                         Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");

  499                         return SCARD_F_COMM_ERROR;

  500                 }

  501

  502                 Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",

  503                         veStr->major, veStr->minor);

  504

  505                 if (veStr->rv != SCARD_S_SUCCESS)

  506                         return veStr->rv;

  507

  508                 isExecuted = 1;

  509         }

  510

  511 again:

  512         /*

  513          * Try to establish an Application Context with the server

  514          */

  515         scEstablishStruct.dwScope = dwScope;

  516         scEstablishStruct.hContext = 0;

  517         scEstablishStruct.rv = SCARD_S_SUCCESS;

  518

  519         rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,

  520                  sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,

  521                 (void *) &scEstablishStruct);

  522

  523         if (rv == -1)

  524                 return SCARD_E_NO_SERVICE;

  525

  526         /*

  527          * Read the response from the server

  528          */

  529         rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);

  530

  531         if (rv == -1)

 

  532                 return SCARD_F_COMM_ERROR;

  533

  534         memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));

  535

  536         if (scEstablishStruct.rv != SCARD_S_SUCCESS)

  537                 return scEstablishStruct.rv;

  538

  539         /* check we do not reuse an existing phContext */

  540         if (-1 != SCardGetContextIndiceTH(scEstablishStruct.hContext))

  541                 /* we do not need to release the allocated context since

  542                  * SCardReleaseContext() does nothing on the server side */

  543                 goto again;

  544

  545         *phContext = scEstablishStruct.hContext;

  546

  547         /*

  548          * Allocate the new hContext - if allocator full return an error

  549          */

  550         rv = SCardAddContext(*phContext, dwClientID);

  551

  552         return rv;

  553 }

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
最新的PCSC、CCID以及测试源码。 贴一段源码: LONG SCardEstablishContext(DWORD dwScope, /*@unused@*/ LPCVOID pvReserved1, /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext) { (void)pvReserved1; (void)pvReserved2; if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL && dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL) { *phContext = 0; return SCARD_E_INVALID_VALUE; } /* * Unique identifier for this server so that it can uniquely be * identified by clients and distinguished from others */ *phContext = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535)); Log2(PCSC_LOG_DEBUG, "Establishing Context: 0x%X", *phContext); return SCARD_S_SUCCESS; } LONG SCardReleaseContext(SCARDCONTEXT hContext) { /* * Nothing to do here RPC layer will handle this */ Log2(PCSC_LOG_DEBUG, "Releasing Context: 0x%X", hContext); return SCARD_S_SUCCESS; } LONG SCardConnect(/*@unused@*/ SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { LONG rv; READER_CONTEXT * rContext = NULL; uint32_t readerState; (void)hContext; PROFILE_START *phCard = 0; if ((dwShareMode != SCARD_SHARE_DIRECT) && !(dwPreferredProtocols & SCARD_PROTOCOL_T0) && !(dwPreferredProtocols & SCARD_PROTOCOL_T1) && !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) && !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)) return SCARD_E_PROTO_MISMATCH; if (dwShareMode != SCARD_SHARE_EXCLUSIVE && dwShareMode != SCARD_SHARE_SHARED && dwShareMode != SCARD_SHARE_DIRECT) return SCARD_E_INVALID_VALUE; Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %d", szReader, dwPreferredProtocols); rv = RFReaderInfo((LPSTR) szReader, &rContext); if (rv != SCARD_S_SUCCESS) { Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader); return rv; } /* * Make sure the reader is working properly */ rv = RFCheckReaderStatus(rContext); if (rv != SCARD_S_SUCCESS) re
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值