ActiveX(ocx) + DLL(wosa) + JS:实现BS硬件调用框架(三)

今日从API层解读SP封装的ActiveX层,因为我的ActiveX层将调用基于wosa规范的SP也就是会调用wosa规范的API,那问题也就归到了综述文档(API和SPI的概述)中去。XFSManger将API经过预处理...等转换变成SP中的spi函数。因而调用第一步就是启动XFXManger环境。文档中给出的一个简单调用的流程:startup-open-register-lock-getinfo-execute..-unlock-deregister-close-cleanup.针对编码我们要注意以下几点问题。

1,版本处理,尽管在大部分测试应用中,版本管理经常是最后实现有时甚至忽略,但由于金融软件有着严格的版本管理体制,我的项目使用DWORD值表示版本号。

2,创建Application句柄及hService。

3,open代表着开启会话(session),具体的设备的状态信息需要通过后续的getinfo获取。

4,lock加锁是设备独占式访问机制的实现,主要对于多应用多会话的execute函数是非常必要的。

5,当然很关键的一点,由于sp只负责返回数据的内存分配,因而释放由ap层解决,调用support functions,WFMFreeBuffer();

贴上一段有注释的代码,展示整个过程,主要注意结构的使用。

    CrdSan* l_poCrdSan;

    l_poCrdSan = (CrdSan*)p_pVoid;
    
    TCHAR l_acTempData[100];
    memset(l_acTempData, 0x00, sizeof(l_acTempData));

    l_poCrdSan->m_ContinueFlag = TRUE; // 连续工作标志,用于外面的线程循环的一个标志
    // 下面是完整的XFS调用过程
    // 启动XFS的环境
    DWORD dwRVersion = l_poCrdSan->dwCombineVersion(LOW_APIVERSUPPORT, HIGH_APIVERSUPPORT);
   // 启动XFS的环境 WFSStartUp为即时调用函数,入口参数分别是应用可以支持的版本范围和一个用于接收当前xfsmanager信息的指针
    HRESULT hr = WFSStartUp(dwRVersion, &(l_poCrdSan->m_wv)); //启动XFS Manager
    if (FAILED(hr))
    {
        l_poCrdSan->Log("WFSStartUp Fail\n");
        return 1;
    }
    else
    {
        l_poCrdSan->Log("WFSStartUp OK\n");
    }

    // 创建Application句柄
    hr = WFSCreateAppHandle(&l_poCrdSan->m_hXFSApp);
    if (FAILED(hr))
    {
        l_poCrdSan->Log("WFSCreateAppHandle Fail\n");
        return 1;
    }
    else
    {
        l_poCrdSan->Log("WFSCreateAppHandle OK\n");
    }

 
    WFSVERSION w;
    DWORD l_dwSupVersion = l_poCrdSan->dwCombineVersion(LOW_SRVCVERSUPPORT, HIGH_SRVCVERSUPPORT);

    HSERVICE hService;
    hr = WFSOpen(l_poCrdSan->m_acLogicalName, l_poCrdSan->m_hXFSApp, NULL, NULL, 
        WFS_INDEFINITE_WAIT, l_dwSupVersion, &l_poCrdSan->m_wv, &w, &hService);
    if (hr != WFS_SUCCESS)
    {
        sprintf(l_acTempData, "WFSOpen %s Fail %d\n", l_poCrdSan->m_acLogicalName, hr);
        l_poCrdSan->Log(l_acTempData);
        return 1;
    }
/*  注册窗体部分代码
//    hr = WFSRegister(hService, SERVICE_EVENTS, theApp.GetSafeHwnd());
//    hr = WFSRegister(hService, USER_EVENTS, theApp.GetSafeHwnd());
//    hr = WFSRegister(hService, EXECUTE_EVENTS, theApp.GetSafeHwnd());
*/    
    
    WFSRESULT* pResult;
    
    // 加锁
    hr = WFSLock(hService, WFS_INDEFINITE_WAIT, &pResult);
    if(hr != WFS_SUCCESS)
    {
        l_poCrdSan->Log("Lock failed");
        return -1 ;
    }
    hr = WFSGetInfo(hService,WFS_INF_CRD_CAPABILITIES,NULL,WFS_INDEFINITE_WAIT,&pResult);
    if(hr == WFS_SUCCESS)
    {
        LPWFSCRDCAPS  lpCaps = (LPWFSCRDCAPS)pResult->lpBuffer;
    }
    WFSCRDDISPENSE* lpcrddis = new WFSCRDDISPENSE;
    lpcrddis->usNumber = 1;
    lpcrddis->bPresent = false;
    hr = WFSExecute(hService,WFS_CMD_CRD_DISPENSE_CARD,lpcrddis,WFS_INDEFINITE_WAIT,&pResult);
    delete lpcrddis;
    if(hr == WFS_SUCCESS)
    {
        //LPWFSCRDCAPS  lpCaps = (LPWFSCRDCAPS)pResult->lpBuffer;
        l_poCrdSan->Log("dispense success");
    }


    // 解锁
    hr = WFSUnlock(hService);
    //释放SP申请的内存
    WFMFreeBuffer(&pResult);

这就在一个应用中调用了一个sp,而现实的封装要求需要在一个ActiveX空间中封装4个左右的sp操作,因而下一步任务就是通过设计模式实现在同一个应用中实现多个SP的调用,下篇我们将继续探讨。不过中途可能要插播一个DES的封装。

posted @ 2012-08-10 09:33  beeshow00  阅读(1446)  评论(0编辑  收藏  举报