簡體   English   中英

實施符合CEN-XFS要求的新服務提供(SP)

[英]Implementing NEW service provide (SP) with CEN-XFS compliance

我們正在嘗試開發符合CEN XFS要求的Windows應用程序+設備驅動程序。此外,NOOB到WINDOWS應用程序。

http://en.wikipedia.org/wiki/CEN/XFS

簡單的架構流程:

   Windows Application
           |
  _____________________
 |      XFS APIs         |
    (CEN/XFS SDK DLL)
 |                       |
 |      XFS SPIs         |
 |_____________________|---XFS Manager   
           |
           |
    Service providers (SP)
    (DEVICE DRIVER)

為了了解SP的功能,我們最近使用了設備供應商之一的SP的DLL來訪問他們的設備,並且我們能夠使用Windows應用程序(基於Eclipse MINGW)與他們的設備成功通信。

然后,我們開始在互聯網上檢查一些樣本SP源,以嘗試實施。 https://drive.google.com/file/d/0B60pejPe6yiSejRGQ3JnLUl4dzA/view

使用鏈接源,我們能夠編譯並創建輸出DLL。 但是,當我們嘗試訪問SP時,它總是返回錯誤。

With windows sample application, we just tried to open the device with call (WFSOPEN) which always returned (-15 WFS_ERR_INTERNAL_ERROR ) or (-29 WFS_ERR_INVALID_SERVPROV)

試用流程1:

    Application Call to manager:

        hResult = WFSOpen(    "QuantumT",    hApp,lpszAppID,    dwTraceLevel,dwTimeOut,    VER_SPI_REQUIRE,&SrvcVersion,&SPIVersion,&hService);    

    manager translates WFSOPEN call to SP's WFPOPEN call:

        HRESULT WINAPI  WFPOpen(HSERVICE hService, LPSTR lpszLogicalName, HAPP hApp, LPSTR lpszAppID, DWORD dwTraceLevel, DWORD dwTimeOut, HWND hWnd, 
            REQUESTID ReqID, HPROVIDER hProvider, DWORD dwSPIVersionsRequired, LPWFSVERSION lpSPIVersion, DWORD dwSrvcVersionsRequired, LPWFSVERSION lpSrvcVersion)

    With above call flow I get (-29 WFS_ERR_INVALID_SERVPROV) as an error for my application

試用FLow 2(只需在SP中刪除WFPOPEN的WINAPI接口):

    Application Call to manager:
        hResult = WFSOpen(    "QuantumT",    hApp,lpszAppID,    dwTraceLevel,dwTimeOut,    VER_SPI_REQUIRE,&SrvcVersion,&SPIVersion,&hService);    

    manager translates WFSOPEN call to SP's WFPOPEN call:
        HRESULT  WFPOpen(HSERVICE hService, LPSTR lpszLogicalName, HAPP hApp, LPSTR lpszAppID, DWORD dwTraceLevel, DWORD dwTimeOut, HWND hWnd, 
            REQUESTID ReqID, HPROVIDER hProvider, DWORD dwSPIVersionsRequired, LPWFSVERSION lpSPIVersion, DWORD dwSrvcVersionsRequired, LPWFSVERSION lpSrvcVersion)

With above call flow I get (-15 WFS_ERR_INTERNAL_ERROR ) as an error for my application from manger even though i force SUCCESS as return from SP to manager 

我很困惑,如果從WFPOPEN中刪除WINAPI定義,則MANAGER為什么將不同的錯誤代碼返回給應用程序。

WINDOWS應用程序示例的鏈接: https : //drive.google.com/open? id = 0B60pejPe6yiSUEp1N2xzdGlXWFE & authuser =0

SP來源(VS C ++ 2010 Express): https : //drive.google.com/file/d/0B60pejPe6yiSejRGQ3JnLUl4dzA/view

XFSMANAGER安裝程序: ftp ://ftp.cencenelec.eu/CEN/WhatWeDo/Fields/ICT/eBusiness/WS/XFS/CWA15748/XFS310SDKInstall.zip

但是,whyneni在工作的DLL和我創建的DLL之間進行了調查(使用PE Studio)。 我看到一些區別。 我創建的DLL:

_WFPCancelAsyncRequest@8,-,1,-,-,.rdata:0x00001096
_WFPClose@12,-,2,-,-,.rdata:0x00001005
_WFPDeregister@20,-,3,-,-,.rdata:0x00001140
_WFPExecute@24,-,4,-,-,.rdata:0x00001131
_WFPGetInfo@24,-,5,-,-,.rdata:0x000010EB
_WFPLock@16,-,6,-,-,.rdata:0x00001023
_WFPOpen@52,-,7,-,-,.rdata:0x0000102D
_WFPRegister@20,-,8,-,-,.rdata:0x00001073
_WFPSetTraceLevel@8,-,9,-,-,.rdata:0x0000113B
_WFPUnloadService@0,-,10,-,-,.rdata:0x0000100A
_WFPUnlock@12,-,11,-,-,.rdata:0x00001082

供應商創建的DLL:

WFPCancelAsyncRequest,-,1,-,-,.rdata:0x0000C450
WFPClose,-,2,-,-,.rdata:0x0000C6E0
WFPDeregister,-,3,-,-,.rdata:0x0000C7F0
WFPExecute,-,4,-,-,.rdata:0x0000C970
WFPGetInfo,-,5,-,-,.rdata:0x0000DFA0
WFPLock,-,6,-,-,.rdata:0x0000E490
WFPOpen,-,7,-,-,.rdata:0x0000C030
WFPRegister,-,8,-,-,.rdata:0x0000E590
WFPSetTraceLevel,-,9,-,-,.rdata:0x0000E710
WFPUnloadService,-,10,-,-,.rdata:0x0000E770
WFPUnlock,-,11,-,-,.rdata:0x0000E8F0

甚至我也確保將Extern添加到標題中。

#ifdef __cplusplus
extern "C" {
#endif
SPITEST_API HRESULT  WINAPI WFPCancelAsyncRequest(HSERVICE hService, REQUESTID RequestID);
SPITEST_API HRESULT  WINAPI WFPClose(HSERVICE hService, HWND hWnd, REQUESTID ReqID);
SPITEST_API HRESULT  WINAPI WFPDeregister(HSERVICE hService, DWORD dwEventClass, HWND hWndReg, HWND hWnd, REQUESTID ReqID);
SPITEST_API HRESULT  WINAPI WFPExecute(HSERVICE hService, DWORD dwCommand, LPVOID lpCmdData, DWORD dwTimeOut, HWND hWnd, REQUESTID ReqID);
SPITEST_API HRESULT  WINAPI WFPGetInfo(HSERVICE hService, DWORD dwCategory, LPVOID lpQueryDetails, DWORD dwTimeOut, HWND hWnd, REQUESTID ReqID);
SPITEST_API HRESULT  WINAPI WFPLock(HSERVICE hService, DWORD dwTimeOut, HWND hWnd, REQUESTID ReqID);
SPITEST_API HRESULT  WINAPI WFPOpen(HSERVICE hService, LPSTR lpszLogicalName, HAPP hApp, LPSTR lpszAppID, DWORD dwTraceLevel, DWORD dwTimeOut, HWND hWnd, REQUESTID ReqID, HPROVIDER hProvider, DWORD dwSPIVersionsRequired, LPWFSVERSION lpSPIVersion, DWORD dwSrvcVersionsRequired, LPWFSVERSION lpSrvcVersion);
SPITEST_API HRESULT  WINAPI WFPRegister(HSERVICE hService,  DWORD dwEventClass, HWND hWndReg, HWND hWnd, REQUESTID ReqID);
SPITEST_API HRESULT  WINAPI WFPSetTraceLevel(HSERVICE hService, DWORD dwTraceLevel);
SPITEST_API HRESULT  WINAPI WFPUnloadService();
SPITEST_API HRESULT  WINAPI WFPUnlock(HSERVICE hService, HWND hWnd, REQUESTID ReqID);
#ifdef __cplusplus
};
#endif

UPDATE1:

根據Voltage給定的指針給定者驗證了我的代碼,而我在代碼流中未發現任何錯誤。

應用代碼:

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include "XFSAPI.H"

const char g_szClassName[] = "myWindowClass";

DWORD   dwThreadID;
HANDLE  hThread;
HANDLE  hEvent[2];
HWND hwnd;
#define VER_SPI_REQUIRE     0x0B020003
#define VER_XFS_REQUIRE     0x0B020003

HSERVICE        hService;


HRESULT SessionOpen(void)
{
    WFSVERSION      WFSVersion;
    DWORD           dwVersionRequired;
    HRESULT         hResult;
    HAPP            hApp=0;
    LPSTR           lpszAppID;
    DWORD           dwTraceLevel = 0;
    WFSVERSION      SrvcVersion,SPIVersion;


    hApp = WFS_DEFAULT_HAPP;
    lpszAppID = (LPSTR)"XFSTEST";

    dwVersionRequired = VER_XFS_REQUIRE;
    hResult = WFSStartUp(dwVersionRequired, &WFSVersion);

    printf("\nStart up result = %ld \n",hResult);
    printf("\n wVersion: %d \n LowVersion: %d \n wHighVersion: %d \n szDescription: %s \n szSystemStatus: %s \n",WFSVersion.wVersion,WFSVersion.wLowVersion,WFSVersion.wHighVersion,WFSVersion.szDescription,WFSVersion.szSystemStatus);
    if(hResult != WFS_SUCCESS)
    {
        return hResult;
    }

    hResult = WFSOpen(  "QuantumT",
            hApp,
            lpszAppID,
            dwTraceLevel,
            WFS_INDEFINITE_WAIT,
            VER_SPI_REQUIRE,
            &SrvcVersion,
            &SPIVersion,
            &hService);

    if(hResult == WFS_SUCCESS)
    {
        printf("SrvcVersion Records: \n wVersion: %d \n LowVersion: %d \n wHighVersion: %d \n szDescription: %s \n szSystemStatus: %s \n",SrvcVersion.wVersion,SrvcVersion.wLowVersion,SrvcVersion.wHighVersion,SrvcVersion.szDescription,SrvcVersion.szSystemStatus);
    }
    printf("SrvcVersion Records: \n wVersion: %d \n LowVersion: %d \n wHighVersion: %d \n szDescription: %s \n szSystemStatus: %s \n",SrvcVersion.wVersion,SrvcVersion.wLowVersion,SrvcVersion.wHighVersion,SrvcVersion.szDescription,SrvcVersion.szSystemStatus);
    printf("SPIVersion Records: \n wVersion: %d \n LowVersion: %d \n wHighVersion: %d \n szDescription: %s \n szSystemStatus: %s \n",SPIVersion.wVersion,SPIVersion.wLowVersion,SPIVersion.wHighVersion,SPIVersion.szDescription,SPIVersion.szSystemStatus);
    printf("\nHService Address ; %ld",hService);
    Sleep(1000);

    return hResult;
}



LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        LPWFSRESULT             lpwfsResult;

        switch ( msg )
        {

            case WFS_SERVICE_EVENT:
            case WFS_USER_EVENT:
            case WFS_SYSTEM_EVENT:
            case WFS_EXECUTE_EVENT:

                lpwfsResult = (LPWFSRESULT) lParam;
                printf("\nEvent Received from XFS" );
                WFSFreeResult(lpwfsResult);
            break;

            default:
                return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{

    HRESULT hResult = 0;
    WNDCLASSEX wc;

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    printf("\nSession Open In progress");


    hResult = SessionOpen();
    printf("\nSessionOpen result = %d",hResult);
    getch();
    return 0;
}

SP的WFPOpen呼叫:

HRESULT WFPOpen(HSERVICE hService, LPSTR lpszLogicalName, HAPP hApp, LPSTR lpszAppID, DWORD dwTraceLevel, DWORD dwTimeOut, HWND hWnd, REQUESTID ReqID, HPROVIDER hProvider, DWORD dwSPIVersionsRequired, LPWFSVERSION lpSPIVersion, DWORD dwSrvcVersionsRequired, LPWFSVERSION lpSrvcVersion)
{
        WFSRESULT * lpWFSResult;
        HRESULT  result;

        SYSTEMTIME   st;
        HRESULT  rt;

        GetSystemTime(&st);
        OutputDebugString("INTO  WFPOpen");

        printf("\nmsxfs DLL load\n");
        char strManager[MAX_PATH];
        if(0==RegGetManagerPath(strManager, sizeof(strManager))){
            if(0==GetSystemDirectoryA(strManager, sizeof(strManager)))
              return WFS_ERR_INTERNAL_ERROR;
            strcat_s(strManager, "\\msxfs.dll");
          }
          if(0!=LoadManagerFunction(strManager))
            return WFS_ERR_INTERNAL_ERROR;
          printf("\nmsxfs DLL load completed\n");
        result = m_pfnWFMAllocateBuffer(sizeof(WFSRESULT), WFS_MEM_ZEROINIT, (void**)&lpWFSResult);
        //result = WFMAllocateBuffer(sizeof(WFSRESULT), WFS_MEM_SHARE|WFS_MEM_ZEROINIT, &lpWFSResult);
        if(result!=WFS_SUCCESS)
            return WFS_ERR_INTERNAL_ERROR;
        printf("\nWFPOpen Process start\n");
        if(!g_hMutex ||!g_hLib ||!g_hMsgQueueEvent) return WFS_ERR_INTERNAL_ERROR;
        if(IsCancel(ReqID)) return WFS_ERR_CANCELED;
        CAutoLock AutoLock(g_hMutex);

      if(g_hDefThread){
            InterlockedIncrement(&g_lDefThreadRef);
            return WFS_SUCCESS;
        }else{
        bQuit=FALSE;
            g_hDefThread=BEGINTHREADEX(NULL, 0, DefThread, NULL, 0, &g_dwDefThreadId);
        if(!g_hDefThread ||g_dwDefThreadId==0)
          return WFS_ERR_CANCELED;
            InterlockedIncrement(&g_lDefThreadRef);
        }


        lpSPIVersion->wVersion=(unsigned short) dwCombineVersion(LOW_APIVERSUPPORT,HIGH_APIVERSUPPORT);
        lpSPIVersion->wLowVersion=wFloattoVersion(LOW_APIVERSUPPORT);
        lpSPIVersion->wHighVersion=wFloattoVersion(HIGH_APIVERSUPPORT);


        lpSrvcVersion->wVersion=(unsigned short ) dwCombineVersion(LOW_APIVERSUPPORT,HIGH_APIVERSUPPORT);
        lpSrvcVersion->wLowVersion=wFloattoVersion(LOW_APIVERSUPPORT);
        lpSrvcVersion->wHighVersion=wFloattoVersion(HIGH_APIVERSUPPORT);

        strcpy(lpSPIVersion->szDescription,"shHicom");
        strcpy(lpSPIVersion->szSystemStatus,"Good");
        CServiceBasic *pServiceBasic=new CServiceBasic;
        pServiceBasic->m_hService=hService;

        UINT uNameLen=min(256, strlen(lpszLogicalName));
        memcpy(pServiceBasic->m_strLogicalName, lpszLogicalName, uNameLen);
        pServiceBasic->m_strLogicalName[uNameLen]='\0';

        pServiceBasic->m_pServiceThread=hApp;
        pServiceBasic->m_strAppID=lpszAppID;
        pServiceBasic->m_dwTraceLevel=dwTraceLevel;
        pServiceBasic->m_dwTimeOut=dwTimeOut;
        pServiceBasic->m_hWND=hWnd;
        pServiceBasic->m_lpRequestID=new REQUESTID;
        *pServiceBasic->m_lpRequestID=ReqID;
        pServiceBasic->m_bAutoDeleteRequestID=TRUE;
        pServiceBasic->m_hLib=hProvider;
        pServiceBasic->m_dwSrvcVersionsRequired=dwSrvcVersionsRequired;
        pServiceBasic->m_lpSrvcVersion=lpSrvcVersion;

      if(WAIT_OBJECT_0!=WaitForSingleObject(g_hMsgQueueEvent, INFINITE))
        return WFS_ERR_CANCELED;
      BOOL b=PostThreadMessage(g_dwDefThreadId, WM_NI_SP_Open, WPARAM(pServiceBasic), 0);
      if(!b){
            return WFS_ERR_CANCELED;
      }
      printf("WFPOpen return with success\n");
    return WFS_SUCCESS;
}

使用onSpOpen進行服務線程回調

LRESULT OnSPOpen(WPARAM wParam, LPARAM lParam)
{
    LRESULT lr=WFS_SUCCESS;
    //return WFS_SUCCESS;
    CServiceBasic *pServiceBasic=(CServiceBasic*)wParam;
    if(pServiceBasic){
    int nLock=pServiceBasic->QueryLogicalServiceLock(pServiceBasic->m_strLogicalName);
    if(nLock<=0){
      UINT uBytes=min(strlen(pServiceBasic->m_strLogicalName), sizeof(g_strLogicalName)-1);
      memcpy(g_strLogicalName, pServiceBasic->m_strLogicalName, uBytes);
      g_strLogicalName[uBytes]='\0';
      //lr=pServiceBasic->OpenDev(g_strLogicalName, g_osp);
      lr=WFS_SUCCESS;
    }else{
        lr=WFS_ERR_CANCELED;
        }
    }else{
        lr=WFS_ERR_INVALID_HSERVICE;
    }
    WFSRESULT *pResult=NULL;
    m_pfnWFMAllocateBuffer(sizeof(WFSRESULT), WFS_MEM_ZEROINIT, (void**)&pResult);
    pResult->RequestID=*pServiceBasic->m_lpRequestID;
    pResult->hService=pServiceBasic->m_hService;
    pResult->hResult=lr;//indicate the result.
    GetLocalTime(&pResult->tsTimestamp);
    HWND hWnd=pServiceBasic->m_hWND;
    delete pServiceBasic;
  BOOL b=::PostMessage(hWnd, WFS_OPEN_COMPLETE, NULL, (LONG)pResult);
  printf ("SP Open made sure it sends WFS_OPEN_COMPLETE via POST MESSAGE\n");

  return 0;
}

執行期間的控制台輸出

C:\\ gtkTrials \\ StandAloneApp \\調試> StandAloneApp.exe

(從StandAloneApp打印)

Session Open In progress 
Start up result = 0  (WFS_SUCCESS)

 wVersion: 3
 LowVersion: 257
 wHighVersion: 39171
 szDescription: WOSA/XFS API v3.00/v2.00
 szSystemStatus:
DllMainProcessAttach is executed

(從SP DLL打印)

msxfs DLL load  
DLL path : C:\xfs_sdks\SDK\DLL\msxfs.dll

msxfs DLL load completed

WFPOpen Process start
DllMainProcessAttach is executed
WFPOpen return with success
SP Open made sure it sends WFS_OPEN_COMPLETE via POST MESSAGE

(從StandAloneApp打印)

SrvcVersion Records:
 wVersion: 3
 LowVersion: 5121
 wHighVersion: 3
 szDescription: α╝`
 szSystemStatus:
SPIVersion Records:
 wVersion: 3
 LowVersion: 5121
 wHighVersion: 3
 szDescription: shHicom
 szSystemStatus: Good



HService Address ; 1
SessionOpen result = -15 (WFS_ERR_INTERNAL_ERROR)

要求了解如何解決此問題的一些指示。

這些導出比較似乎您使用了錯誤的調用約定。
將所有SPI導出從WINAPI更改為__cdecl(只需刪除WINAPI,因為__cdecl是默認設置),這應該有所作為。

以及為什么示例中的返回碼不同:
第一個示例甚至都沒有轉到WFPOpen調用,因為在DLL加載->無效的ServiceProvider之后,管理器找不到正確的WFPOpen符號。

第二種情況接縫進入WFPOpen,但是第一種情況測試失敗-> INTERNAL_ERROR:
if(!g_hMutex ||!g_hLib ||!g_hMsgQueueEvent)返回WFS_ERR_INTERNAL_ERROR;

因此,在調用約定修復后,您需要更詳細地檢查initailization代碼以查看失敗的原因。

通過查看那些經過測試的全局變量,我發現的一件事是,永遠不要從DLLMain中執行的代碼中調用LoadLibrary。

您可以只創建互斥鎖並將DLL模塊句柄保存在DLLMain中,然后執行其余的初始化工作,例如在WFPOpen的開始時加載庫。

不能簡單地從WFPOpen返回WFS_SUCCESS。 以下是對最小實現的非常粗略的描述:
1.填寫版本結構(參數之一是為此的指針)
2.返回WFS_SUCCESS或錯誤代碼。
3.如果WFPOpen返回WFS_SUCCESS,則調用者需要異步響應。 因此,您必須將帶有所有必需信息的WFS_OPEN_COMPLETE消息發送到給定的(hwnd參數)消息窗口句柄。

請參見以下文檔(SPI API第6章),以獲取更多詳細信息。
ftp://ftp.cenorm.be/CWA/CEN/WS-XFS/CWA16374/CWA16374-1-2011_December.pdf

這個代碼還可以。 我認為您應該在注冊表中搜索“ QuantumT”,因為它可能尚未在此處進行注冊。

邏輯服務名稱:1- regedit 2- HKEY_CURRENT_USER / XFS / LOGICAL_SERVICES /

我使用“ JournalPrinter1”,WFSOpen向我返回成功。

調用約定已經在XFSSPI.H定義,我不認為您應該更改它。

您需要使用功能的“正確”導出名稱將.def文件添加到您的解決方案中,並將其設置為您的解決方案模塊定義文件Properties->Linker->Input->Module Definition File

EXPORTS
WFPCancelAsyncRequest
WFPClose
WFPDeregister
WFPExecute
WFPGetInfo
WFPLock
WFPOpen
WFPRegister
WFPSetTraceLevel
WFPUnloadService
WFPUnlock

我以這種方式獲得了SPI WFPOpen函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM