我们正在尝试开发符合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 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
然而,whneni调查了我创建的工作DLL和DLL(使用PE Studio)。我看到一些不同之处。 DLL由ME创建:
_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:
根据指针给予电压验证我的代码,我没有在代码流中找到任何错误。
申请代码:
#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 \调试和GT; 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)
请求了解此问题的一些指示。
答案 0 :(得分:1)
这些导出比较看起来像是在使用错误的调用约定 将所有SPI导出从WINAPI更改为__cdecl(只需删除WINAPI,因为__cdecl是默认值),它应该有所不同。
为什么示例中返回代码的差异:
第一个例子甚至没有进入WFPOpen调用,因为管理器在DLL加载后没有找到正确的WFPOpen符号 - &gt; ServiceProvider无效。
第二个案例接缝进入WFPOpen,但第一次测试失败 - &gt; INTERNAL_ERROR:
if(!g_hMutex ||!g_hLib ||!g_hMsgQueueEvent)返回WFS_ERR_INTERNAL_ERROR;
因此,在调用约定修复之后,您需要更详细地检查您的初始化代码,以了解它失败的原因。
通过查看测试全局变量我发现的一件事是你永远不应该从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
答案 1 :(得分:0)
这段代码还可以。 我认为你应该在注册中搜索&#34; QuantumT&#34;,可能它没有在那里注册。
逻辑服务名称: 1-注册 2- HKEY_CURRENT_USER / XFS / LOGICAL_SERVICES /
我使用&#34; JournalPrinter1&#34;和WFSOpen将成功归还给我。
答案 2 :(得分:0)
调用约定已在XFSSPI.H
中定义,我认为您不应该更改它。
您需要使用&#34;正确的&#34;将.def文件添加到您的解决方案中。导出函数的名称,并将其设置为解决方案模块定义文件Properties->Linker->Input->Module Definition File
:
EXPORTS
WFPCancelAsyncRequest
WFPClose
WFPDeregister
WFPExecute
WFPGetInfo
WFPLock
WFPOpen
WFPRegister
WFPSetTraceLevel
WFPUnloadService
WFPUnlock
我这样调用了SPI
WFPOpen
函数。