Commit d7099574 by wuyang.zou

fix bug: 为客户[服务端存在多多用户时,pos外卖插件程序启动不了] 完善新增功能【新增指定pos 登陆用户名的配置功能:实现将程序以配置的用户下启动】

parent 2701981e
#include "fmcontrol.h"
#include "fmcontrol.h"
#include "fmtools.h"
#include "QsLog.h"
#include "fmdefine.h"
......@@ -17,6 +17,10 @@
#include <QProcess>
#include "JlCompress.h"
#include <WtsApi32.h>
#include <windows.h>
#include <WinNT.h>
FmControl::FmControl()
{
m_keepTimer.setInterval(KEEP_INTERVAL);
......@@ -97,13 +101,24 @@ bool FmControl::_GetDiedProcess(const QStringList &exeList, QStringList &diedPro
bool FmControl::_LaunchProcess(const QString &exePath, QString& error)
{
QLOG_INFO()<< QString("Begin ..... _LaunchProcess--------------------> ");
// 在XP下用户环境可能没有wtsapi32.dll,XP下可直接调用程序
/***<1> 载入动态库:Wtsapi32.dll ***/
HMODULE hDllLib = LoadLibrary(L"Wtsapi32.dll");
if(hDllLib){
QLOG_INFO()<< QString("LoadLibrary [Wtsapi32.dll] successed...");
}else{
QLOG_ERROR()<< QString("LoadLibrary [Wtsapi32.dll] failed [%1]").arg(QString::number(::GetLastError()));
return false;
}
/***<2> 声明函数指针来接受动态库中导出的函数【WTSQueryUserToken】 ***/
typedef BOOL (WINAPI *_pfnWTSQueryUserToken)( ULONG SessionId, PHANDLE phToken );
_pfnWTSQueryUserToken pfnWTSQueryUserToken = NULL;
pfnWTSQueryUserToken = (_pfnWTSQueryUserToken)GetProcAddress(LoadLibrary(L"Wtsapi32.dll"), "WTSQueryUserToken");
if(pfnWTSQueryUserToken == NULL)
{
error = QString("get WTSQueryUserToken failed");
pfnWTSQueryUserToken = (_pfnWTSQueryUserToken)GetProcAddress(hDllLib, "WTSQueryUserToken");
if(pfnWTSQueryUserToken == NULL) {
QLOG_ERROR()<< QString("LoadLibrary->GetProcAddress[WTSQueryUserToken] failed [%1]").arg(QString::number(::GetLastError()));
error = QString("get WTSQueryUserToken function point failed");
FreeLibrary(hDllLib);
return QProcess::startDetached(exePath, QStringList(exePath));
}
// 进程信息
......@@ -112,16 +127,98 @@ bool FmControl::_LaunchProcess(const QString &exePath, QString& error)
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
// 获得当前Session ID
DWORD dwSessionID = WTSGetActiveConsoleSessionId();
/***<3> 获取活动的用户会话ID 用于后期 令牌的拷贝 ***/
DWORD dwSessionID;
/***<3.1>:if:判断是否开启<指定POS登录用户名功能> ***/
if(FmTools::GetInstance().GetPosLoginUserEnable()){
QString posLoginUserName = FmTools::GetInstance().GetPosLoginUserName();
std::string strPosLoginUserName = posLoginUserName.toStdString();
//<3.1.1> 获得全部的Session ID
/*** 声明函数指针来接受动态库中导出的函数【WTSEnumerateSessions:获取全部的会话窗口】 ***/
typedef BOOL (WINAPI *_pfnWTSEnumerateSessions)( HANDLE,DWORD,DWORD,PWTS_SESSION_INFO*, DWORD*);
_pfnWTSEnumerateSessions pfnWTSEnumerateSessions = NULL;
pfnWTSEnumerateSessions = (_pfnWTSEnumerateSessions)GetProcAddress(hDllLib, "WTSEnumerateSessionsW");
if(!pfnWTSEnumerateSessions){
QLOG_ERROR()<< QString("LoadLibrary->GetProcAddress[WTSEnumerateSessions] failed [%1]").arg(QString::number(::GetLastError()));
FreeLibrary(hDllLib);
return false;
}
/*** 声明函数指针来接受动态库中导出的函数【WTSQuerySessionInformation:获取全部的会话窗口】 ***/
typedef BOOL (WINAPI *_pfnWTSQuerySessionInformation)( HANDLE,DWORD,DWORD, LPTSTR*,DWORD*);
_pfnWTSQuerySessionInformation pfnWTSQuerySessionInformation = NULL;
pfnWTSQuerySessionInformation = (_pfnWTSQuerySessionInformation)GetProcAddress(hDllLib, "WTSQuerySessionInformationW");
if(!pfnWTSQuerySessionInformation){
QLOG_ERROR()<< QString("LoadLibrary->GetProcAddress[WTSQuerySessionInformation] failed [%1]").arg(QString::number(::GetLastError()));
FreeLibrary(hDllLib);
return false;
}
/***<3.1.2> 遍历全部 Session ID 用来获取是否存在 POS登录用户名 ***/
WTS_SESSION_INFO *sessionInfo = NULL;
DWORD sessionInfoCount;
char dwUserName[256];
BOOL result = pfnWTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessionInfo, &sessionInfoCount);
QLOG_INFO()<< QString("WTSEnumerateSessions->getAllSessionsResult[%1][1:sucessed 0:failed]").arg(QString::number(result));
if (result){
QLOG_INFO()<< QString("WTSEnumerateSessions->sessionInfoCount[%1]").arg(QString::number(sessionInfoCount));
// look over obtained list in search of the active session
/*<3.1.2.1> 遍历全部的会话*/
for(DWORD i = 0; i < sessionInfoCount; ++i)
{
QLOG_INFO()<< QString("WTSEnumerateSessions->sessionInfo[%1]->sessionState:[%2]").arg(i).arg(sessionInfo[i].State);
QLOG_INFO()<< QString("WTSEnumerateSessions->SessionId[%1]").arg(QString::number(sessionInfo[i].SessionId));
WTS_SESSION_INFO si = sessionInfo[i];
dwSessionID = si.SessionId;
LPTSTR pBuffer = NULL;
DWORD dwBufferLen;
/*** 依次获取 SessionID 对应的 POS登录用户名 ***/
BOOL bRes = pfnWTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionID, WTSUserName, &pBuffer, &dwBufferLen);
/*<3.1.2.1.1> 获取指定SessionID用户名失败 直接进行下一个SessionID的判断*/
if (bRes == FALSE) continue;
WideCharToMultiByte(CP_ACP, 0, pBuffer, -1, dwUserName, dwBufferLen, NULL, NULL );
dwUserName[dwBufferLen] = 0;
QLOG_INFO()<< QString("WTSQuerySessionInformation->SessionUserName[%1]").arg(QString(dwUserName));
WTSFreeMemory(pBuffer);
/*<3.1.2.1.2> 如果遇到配置文件中的POS登录用户名则 跳出循环*/
if (!strcmp(dwUserName,strPosLoginUserName.c_str())){
break;
}
}
QLOG_INFO()<< QString("WTSEnumerateSessions->curSessionId[%1]").arg(QString::number(dwSessionID));
QLOG_INFO()<< QString("WTSEnumerateSessions->curSessionName[%1]").arg(QString(dwUserName));
WTSFreeMemory(sessionInfo); //释放
}/***<3.1.3> WTSEnumerateSessions:获取全部会话信息失败 ***/
else{
QLOG_ERROR()<< QString("WTSEnumerateSessions->getAllSessionsResult error [%1]").arg(QString::number(::GetLastError()));
FreeLibrary(hDllLib);
return false;
}
/***<3.1.4> 判断是否筛选出 指定POS登录用户名***/
if( strcmp(dwUserName,strPosLoginUserName.c_str() )){
QLOG_INFO()<< QString("WTSEnumerateSessions: Don't exist [%1] count or [%1] havn't login in").arg(QString::fromStdString(strPosLoginUserName));
FreeLibrary(hDllLib);
return false;
}
}else{ /***3.2:else:默认不开启 <指定POS登录用户名功能> ***/
dwSessionID = WTSGetActiveConsoleSessionId();
}
//<4> 获得 SessionID 的用户令牌
HANDLE hToken = NULL;
// 获得当前Session的用户令牌
if (pfnWTSQueryUserToken(dwSessionID, &hToken) == FALSE)
if(pfnWTSQueryUserToken(dwSessionID, &hToken)==FALSE)
{
error = QString("get session failed [%1]").arg(QString::number(::GetLastError()));
QLOG_ERROR() << QString("hToken= [%1]").arg(reinterpret_cast<int>(hToken));
QLOG_ERROR()<< QString("get session:LastError:[%1]").arg(QString::number(::GetLastError()));
error = QString("get session:LastError:[%1]").arg(QString::number(::GetLastError()));
FreeLibrary(hDllLib);
return false;
}
// 复制令牌
QLOG_INFO() << QString("dwSessionID= [%1]").arg(dwSessionID);
QLOG_INFO() << QString("hToken= [%1]").arg(reinterpret_cast<int>(hToken));
//<5> 复制令牌
HANDLE hDuplicatedToken = NULL;
if (DuplicateTokenEx(hToken,
MAXIMUM_ALLOWED, NULL,
......@@ -133,9 +230,11 @@ bool FmControl::_LaunchProcess(const QString &exePath, QString& error)
CloseHandle(hToken);
}
error = QString("copy token failed [%1]").arg(QString::number(::GetLastError()));
QLOG_ERROR()<< QString("copy token failed [%1]").arg(QString::number(::GetLastError()));
FreeLibrary(hDllLib);
return false;
}
// 创建用户Session环境
//<6> 创建用户Session环境
LPVOID lpEnvironment = NULL;
if (CreateEnvironmentBlock(&lpEnvironment, hDuplicatedToken, FALSE) == FALSE)
{
......@@ -144,9 +243,11 @@ bool FmControl::_LaunchProcess(const QString &exePath, QString& error)
CloseHandle(hDuplicatedToken);
}
error = QString("create environment failed [%1]").arg(QString::number(::GetLastError()));
QLOG_ERROR()<< QString("create environment failed [%1]").arg(QString::number(::GetLastError()));
FreeLibrary(hDllLib);
return false;
}
// 在复制的用户Session下执行应用程序,创建进程。
//<7> 在复制的用户Session下执行应用程序,创建进程。
if (CreateProcessAsUser(hDuplicatedToken,
exePath.toStdWString().c_str(), NULL, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
......@@ -157,10 +258,14 @@ bool FmControl::_LaunchProcess(const QString &exePath, QString& error)
DestroyEnvironmentBlock(lpEnvironment);
}
error = QString("CreateProcessAsUser failed [%1]").arg(QString::number(::GetLastError()));
QLOG_ERROR()<< QString("CreateProcessAsUser failed [%1]").arg(QString::number(::GetLastError()));
FreeLibrary(hDllLib);
return false;
}
/***<8> :关闭句柄等 回收资源操作 ***/
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
FreeLibrary(hDllLib);
return true;
}
......
......@@ -3,6 +3,9 @@
#define INIFILE_NAME "update.ini"
#define INIPATH_EXELIST "ExeList/value"
#define INIPATH_POSLOGINUSERENABLE "PosLoginUserInfo/bEnable"
#define INIPATH_POSLOGINUSERNAME "PosLoginUserInfo/sLoginUserName"
#define INIPATH_UPDATE_URL "ServerUrl/update"
#define INIPATH_REPORT_URL "ServerUrl/report"
#define INIPATH_VERSION "SoftInfo/version"
......
......@@ -51,5 +51,8 @@ else {
win32 {
LIBS += -luser32 -lAdvapi32
LIBS += -luser32 -lAdvapi32 -lWtsapi32
}
......@@ -169,6 +169,17 @@ QStringList FmTools::GetKeepExes()
return m_config->value(INIPATH_EXELIST).toStringList();
}
bool FmTools::GetPosLoginUserEnable()
{
return m_config->value(INIPATH_POSLOGINUSERENABLE).toBool();
}
QString FmTools::GetPosLoginUserName()
{
return m_config->value(INIPATH_POSLOGINUSERNAME).toString();
}
QString FmTools::GetVersion()
{
return m_config->value(INIPATH_VERSION).toString();
......
......@@ -16,6 +16,20 @@ public:
* 返回:程序列表(带相对路径)
* */
QStringList GetKeepExes();
/* 功能:获取收银机器(pos)是否开启<POS登陆用户名>功能
* 参数:NULL
* 返回: 是否开启<POS登陆用户名>功能
* */
bool GetPosLoginUserEnable();
/* 功能:获取收银机器(pos) POS登陆用户名
* 参数:NULL
* 返回:POS登陆机器的用户名
* */
QString GetPosLoginUserName();
/* 功能:获取软件版本信息
* 参数:NULL
* 返回:软件版本
......
......@@ -19,3 +19,7 @@ timeout1=20
;守护的程序列表
[ExeList]
value=
[PosLoginUserInfo]
bEnable=FALSE
sLoginUserName=wuyang.zou
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment