title: Implementing NEW service provide (SP) with CEN-XFS compliance
body: <p>We are trying to develop windows application + device driver with CEN XFS compliance.Also, NOOB to WINDOWS applications.</p>
  
  <p><a href="http://en.wikipedia.org/wiki/CEN/XFS" rel="nofollow">http://en.wikipedia.org/wiki/CEN/XFS</a></p>
  
  <p>simple architectural flow:</p>
  
  <pre><code>   Windows Application
             |
    _____________________
   |      XFS APIs         |
      (CEN/XFS SDK DLL)
   |                       |
   |      XFS SPIs         |
   |_____________________|---XFS Manager   
             |
             |
      Service providers (SP)
      (DEVICE DRIVER)
  </code></pre>
  
  <p>To understand the SP's functionality, we recently took one of the device vendors SP's DLL for accessing their device and we were able to successfully communicate with their device using our windows application(Eclipse MINGW based).</p>
  
  <p>Then we started  to check for some sample  SP source in internet to try our implementation. (<a href="https://drive.google.com/file/d/0B60pejPe6yiSejRGQ3JnLUl4dzA/view" rel="nofollow">https://drive.google.com/file/d/0B60pejPe6yiSejRGQ3JnLUl4dzA/view</a>)</p>
  
  <p>With the linked source we were able to compile and create an output DLL. But , when we tried to access the SP, It always return error.</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>Trial FLow 1 :</p>
  
  <pre><code>    Application Call to manager:
  
          hResult = WFSOpen(    "QuantumT",    hApp,lpszAppID,    dwTraceLevel,dwTimeOut,    VER_SPI_REQUIRE,&amp;SrvcVersion,&amp;SPIVersion,&amp;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
  </code></pre>
  
  <p>Trial FLow 2 (Just removed WINAPI interface for WFPOPEN in SP):</p>
  
  <pre><code>    Application Call to manager:
          hResult = WFSOpen(    "QuantumT",    hApp,lpszAppID,    dwTraceLevel,dwTimeOut,    VER_SPI_REQUIRE,&amp;SrvcVersion,&amp;SPIVersion,&amp;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 
  </code></pre>
  
  <p><strong>I am  confused why MANAGER returns different error codes to application if WINAPI definition is removed from WFPOPEN.</strong></p>
  
  <p>Link for WINDOWS APPLICATION SAMPLE: 
  <a href="https://drive.google.com/open?id=0B60pejPe6yiSUEp1N2xzdGlXWFE&amp;authuser=0" rel="nofollow">https://drive.google.com/open?id=0B60pejPe6yiSUEp1N2xzdGlXWFE&amp;authuser=0</a></p>
  
  <p>SP Source (VS C++ 2010 Express):
  <a href="https://drive.google.com/file/d/0B60pejPe6yiSejRGQ3JnLUl4dzA/view" rel="nofollow">https://drive.google.com/file/d/0B60pejPe6yiSejRGQ3JnLUl4dzA/view</a>)</p>
  
  <p>XFSMANAGER INSTALLER:
  <a href="ftp://ftp.cencenelec.eu/CEN/WhatWeDo/Fields/ICT/eBusiness/WS/XFS/CWA15748/XFS310SDKInstall.zip" rel="nofollow">ftp://ftp.cencenelec.eu/CEN/WhatWeDo/Fields/ICT/eBusiness/WS/XFS/CWA15748/XFS310SDKInstall.zip</a></p>
  
  <p>However, whneni investigate  between working DLL and DLL created by me(Using PE Studio). I see some differnece.
  DLL Created by ME:</p>
  
  <pre><code>_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
  </code></pre>
  
  <p>Vendor created DLL:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Even I made sure that Extern is added in my header.</p>
  
  <pre><code>#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
  </code></pre>
  
  <p><strong>Update1:</strong></p>
  
  <p>based on the pointers giver by <strong>Voltage</strong> verified my code and i did not find any erro in the code flow.</p>
  
  <p>Application code:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;conio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;windows.h&gt;
  #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, &amp;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,
              &amp;SrvcVersion,
              &amp;SPIVersion,
              &amp;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(&amp;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;
  }
  </code></pre>
  
  <p><strong>SP's WFPOpen call:</strong></p>
  
  <pre><code>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(&amp;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**)&amp;lpWFSResult);
          //result = WFMAllocateBuffer(sizeof(WFSRESULT), WFS_MEM_SHARE|WFS_MEM_ZEROINIT, &amp;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(&amp;g_lDefThreadRef);
              return WFS_SUCCESS;
          }else{
          bQuit=FALSE;
              g_hDefThread=BEGINTHREADEX(NULL, 0, DefThread, NULL, 0, &amp;g_dwDefThreadId);
          if(!g_hDefThread ||g_dwDefThreadId==0)
            return WFS_ERR_CANCELED;
              InterlockedIncrement(&amp;g_lDefThreadRef);
          }
  
  
          lpSPIVersion-&gt;wVersion=(unsigned short) dwCombineVersion(LOW_APIVERSUPPORT,HIGH_APIVERSUPPORT);
          lpSPIVersion-&gt;wLowVersion=wFloattoVersion(LOW_APIVERSUPPORT);
          lpSPIVersion-&gt;wHighVersion=wFloattoVersion(HIGH_APIVERSUPPORT);
  
  
          lpSrvcVersion-&gt;wVersion=(unsigned short ) dwCombineVersion(LOW_APIVERSUPPORT,HIGH_APIVERSUPPORT);
          lpSrvcVersion-&gt;wLowVersion=wFloattoVersion(LOW_APIVERSUPPORT);
          lpSrvcVersion-&gt;wHighVersion=wFloattoVersion(HIGH_APIVERSUPPORT);
  
          strcpy(lpSPIVersion-&gt;szDescription,"shHicom");
          strcpy(lpSPIVersion-&gt;szSystemStatus,"Good");
          CServiceBasic *pServiceBasic=new CServiceBasic;
          pServiceBasic-&gt;m_hService=hService;
  
          UINT uNameLen=min(256, strlen(lpszLogicalName));
          memcpy(pServiceBasic-&gt;m_strLogicalName, lpszLogicalName, uNameLen);
          pServiceBasic-&gt;m_strLogicalName[uNameLen]='\0';
  
          pServiceBasic-&gt;m_pServiceThread=hApp;
          pServiceBasic-&gt;m_strAppID=lpszAppID;
          pServiceBasic-&gt;m_dwTraceLevel=dwTraceLevel;
          pServiceBasic-&gt;m_dwTimeOut=dwTimeOut;
          pServiceBasic-&gt;m_hWND=hWnd;
          pServiceBasic-&gt;m_lpRequestID=new REQUESTID;
          *pServiceBasic-&gt;m_lpRequestID=ReqID;
          pServiceBasic-&gt;m_bAutoDeleteRequestID=TRUE;
          pServiceBasic-&gt;m_hLib=hProvider;
          pServiceBasic-&gt;m_dwSrvcVersionsRequired=dwSrvcVersionsRequired;
          pServiceBasic-&gt;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;
  }
  </code></pre>
  
  <p><strong>Service thread callback with onSpOpen</strong></p>
  
  <pre><code>LRESULT OnSPOpen(WPARAM wParam, LPARAM lParam)
  {
      LRESULT lr=WFS_SUCCESS;
      //return WFS_SUCCESS;
      CServiceBasic *pServiceBasic=(CServiceBasic*)wParam;
      if(pServiceBasic){
      int nLock=pServiceBasic-&gt;QueryLogicalServiceLock(pServiceBasic-&gt;m_strLogicalName);
      if(nLock&lt;=0){
        UINT uBytes=min(strlen(pServiceBasic-&gt;m_strLogicalName), sizeof(g_strLogicalName)-1);
        memcpy(g_strLogicalName, pServiceBasic-&gt;m_strLogicalName, uBytes);
        g_strLogicalName[uBytes]='\0';
        //lr=pServiceBasic-&gt;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**)&amp;pResult);
      pResult-&gt;RequestID=*pServiceBasic-&gt;m_lpRequestID;
      pResult-&gt;hService=pServiceBasic-&gt;m_hService;
      pResult-&gt;hResult=lr;//indicate the result.
      GetLocalTime(&amp;pResult-&gt;tsTimestamp);
      HWND hWnd=pServiceBasic-&gt;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;
  }
  </code></pre>
  
  <p><strong>Console Output during execution</strong></p>
  
  <p>C:\gtkTrials\StandAloneApp\Debug>StandAloneApp.exe</p>
  
  <p><strong>(Print from StandAloneApp )</strong></p>
  
  <pre><code>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
  </code></pre>
  
  <p><strong>(Print from SP DLL )</strong></p>
  
  <pre><code>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
  </code></pre>
  
  <p><strong>(Print from StandAloneApp )</strong></p>
  
  <pre><code>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)
  </code></pre>
  
  <p>Request some pointers on understanding this issue.</p>