Внедрение НОВОГО сервисного обеспечения (SP) с соответствием CEN-XFS

Мы пытаемся разработать приложение для Windows + драйвер устройства с соблюдением CEN XFS. Кроме того, приложения 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, мы недавно взяли DLL-библиотеку SP одного из производителей устройств для доступа к их устройству, и мы смогли успешно установить связь с их устройством с помощью нашего приложения 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

Пробная версия 2 (только что удаленный интерфейс WINAPI для WFPOPEN в SP):

    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

Я запутался, почему MANAGER возвращает различные коды ошибок в приложение, если определение WINAPI удалено из WFPOPEN.

Ссылка на образец приложения для Windows:
https://drive.google.com/open?id=0B60pejPe6yiSUEp1N2xzdGlXWFE&AuthUser = 0

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

XFSMANAGER INSTALLER:
ftp://ftp.cencenelec.eu/CEN/WhatWeDo/Fields/ICT/eBusiness/WS/XFS/CWA15748/XFS310SDKInstall.zip

Тем не менее, выясните, между рабочей 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

Даже я убедился, что Экстерн добавлен в мой заголовок.

#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:

на основе указателей, дающих вольтаж проверил мой код, и я не нашел никаких ошибок в потоке кода.

Код приложения:

#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 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)
{
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 \ Debug> 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: GoodHService Address ; 1
SessionOpen result = -15 (WFS_ERR_INTERNAL_ERROR)

Запросите несколько советов по пониманию этой проблемы.

0

Решение

Эти сравнения экспорта выглядят так, как будто вы используете неправильное соглашение о вызовах.

Измените все экспорты SPI из WINAPI на __cdecl (просто удалите WINAPI, так как __cdecl используется по умолчанию), и это должно иметь значение.

И почему разница в кодах возврата в ваших примерах:

Первый пример даже не доходит до вызова WFPOpen, потому что менеджер не находит правильный символ WFPOpen после загрузки DLL -> Invalid ServiceProvider.



Второй случай швов, чтобы войти в WFPOpen, но первый тест не пройден -> INTERNAL_ERROR:

if (! g_hMutex ||! g_hLib ||! g_hMsgQueueEvent) return WFS_ERR_INTERNAL_ERROR;

Поэтому после исправления соглашения о вызовах вам необходимо более подробно проверить код инициализации, чтобы понять, почему он не работает.

Просматривая эти проверенные глобальные переменные, я понял, что НИКОГДА не следует вызывать LoadLibrary из кода, который выполняется в DLLMain.

Вы можете просто создать мьютекс и сохранить дескриптор модуля DLL в DLLMain и выполнить остальную часть инициализации, например, загрузку библиотеки в начале WFPOpen.

Нельзя просто вернуть WFS_SUCCESS из WFPOpen.
Ниже приведено очень грубое описание минимальной реализации:

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

1

Другие решения

этот код в порядке.
Я думаю, что Вы должны Искать в реестре «QuantumT», возможно, он еще не зарегистрировался там.

логические имена сервисов:
1- regedit
2- HKEY_CURRENT_USER / XFS / LOGICAL_SERVICES /

Я использую «JournalPrinter1» и WFSOpen возвращает мне Успех.

0

Соглашение о вызовах уже определено в XFSSPI.HЯ не думаю, что вы должны изменить это.

Вам необходимо добавить файл .def в ваше решение с «правильным» экспортированным именем функций и установить его в качестве вашего файла определения модуля решения. Properties->Linker->Input->Module Definition File:

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

Я получил свой SPI WFPOpen Функция называется так.

0