2023-06-19 11:08:42 +00:00
|
|
|
|
#include "pch.h"
|
|
|
|
|
#include "misc.h"
|
2023-06-27 02:02:02 +00:00
|
|
|
|
|
2023-06-19 11:08:42 +00:00
|
|
|
|
#include "usrerr.h"
|
|
|
|
|
|
2023-07-10 08:36:19 +00:00
|
|
|
|
#include <shlwapi.h>
|
2023-06-19 11:08:42 +00:00
|
|
|
|
#include <strsafe.h>
|
|
|
|
|
#include <spdlog/spdlog.h>
|
|
|
|
|
|
2023-06-27 02:02:02 +00:00
|
|
|
|
TCHAR *binToHexString(TCHAR *p, const unsigned char *cp, unsigned int count) {
|
|
|
|
|
static const TCHAR hex_asc[] = TEXT("0123456789abcdef");
|
|
|
|
|
while (count) {
|
|
|
|
|
const unsigned char c = *cp++;
|
|
|
|
|
/* put lowercase hex digits */
|
|
|
|
|
*p++ = static_cast<TCHAR>(0x20 | hex_asc[c >> 4]);
|
|
|
|
|
*p++ = static_cast<TCHAR>(0x20 | hex_asc[c & 0xf]);
|
|
|
|
|
count--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 09:25:14 +00:00
|
|
|
|
void RemoveTailLineBreak(TCHAR *pInputStr, int strSize) {
|
2023-06-19 11:08:42 +00:00
|
|
|
|
size_t length;
|
2023-06-20 09:25:14 +00:00
|
|
|
|
if (pInputStr) {
|
|
|
|
|
if (StringCbLength(pInputStr, strSize, &length) == S_OK && length > 0) {
|
|
|
|
|
if (pInputStr[length - 2] == '\r' && pInputStr[length - 1] == '\n') {
|
2023-06-19 11:08:42 +00:00
|
|
|
|
pInputStr[length - 2] = pInputStr[length - 1] = 0;
|
2023-06-20 09:25:14 +00:00
|
|
|
|
} else if (pInputStr[length - 1] == '\n') {
|
2023-06-19 11:08:42 +00:00
|
|
|
|
pInputStr[length - 1] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-25 07:57:47 +00:00
|
|
|
|
int RunCommand(TCHAR *pszCmd, TCHAR *pszResultBuffer, int dwResultBufferSize, unsigned long *pRetCode) {
|
2023-06-20 09:25:14 +00:00
|
|
|
|
BOOL bRet;
|
|
|
|
|
HANDLE hReadPipe = nullptr;
|
|
|
|
|
HANDLE hWritePipe = nullptr;
|
2023-06-25 07:57:47 +00:00
|
|
|
|
DWORD retCode;
|
2023-06-20 09:25:14 +00:00
|
|
|
|
STARTUPINFO si;
|
2023-06-19 11:08:42 +00:00
|
|
|
|
PROCESS_INFORMATION pi;
|
2023-06-27 02:02:02 +00:00
|
|
|
|
SECURITY_ATTRIBUTES securityAttributes;
|
2023-06-19 11:08:42 +00:00
|
|
|
|
|
2023-06-20 10:23:31 +00:00
|
|
|
|
if (pszCmd == nullptr) {
|
|
|
|
|
SPDLOG_ERROR(TEXT("Input params Error: [{0}]"), pszCmd);
|
|
|
|
|
return -ERR_INPUT_PARAMS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pszResultBuffer && dwResultBufferSize > 0) {
|
|
|
|
|
memset(pszResultBuffer, 0, dwResultBufferSize);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-19 11:08:42 +00:00
|
|
|
|
memset(&si, 0, sizeof(STARTUPINFO));
|
|
|
|
|
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
|
|
|
|
|
|
|
|
|
|
// 设定管道的安全属性
|
2023-06-20 09:25:14 +00:00
|
|
|
|
securityAttributes.bInheritHandle = TRUE;
|
|
|
|
|
securityAttributes.nLength = sizeof(securityAttributes);
|
2023-06-19 11:08:42 +00:00
|
|
|
|
securityAttributes.lpSecurityDescriptor = nullptr;
|
|
|
|
|
|
|
|
|
|
// 创建匿名管道
|
|
|
|
|
bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0);
|
2023-06-20 09:25:14 +00:00
|
|
|
|
if (FALSE == bRet) {
|
2023-06-19 11:08:42 +00:00
|
|
|
|
SPDLOG_ERROR(TEXT("CreatePipe Error"));
|
|
|
|
|
return -ERR_SYS_CALL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置新进程参数
|
2023-06-20 09:25:14 +00:00
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
|
si.hStdError = hWritePipe;
|
|
|
|
|
si.hStdOutput = hWritePipe;
|
2023-06-19 11:08:42 +00:00
|
|
|
|
si.wShowWindow = SW_HIDE;
|
2023-06-20 09:25:14 +00:00
|
|
|
|
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
2023-06-19 11:08:42 +00:00
|
|
|
|
|
|
|
|
|
// 创建新进程执行命令, 将执行结果写入匿名管道中
|
|
|
|
|
bRet = ::CreateProcess(nullptr, (pszCmd), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi);
|
2023-06-20 09:25:14 +00:00
|
|
|
|
if (FALSE == bRet) {
|
2023-06-19 11:08:42 +00:00
|
|
|
|
SPDLOG_ERROR(TEXT("CreateProcess Error"));
|
2023-06-21 10:04:16 +00:00
|
|
|
|
return -ERR_CREATE_PROCESS;
|
2023-06-19 11:08:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待命令执行结束
|
2023-07-10 08:36:19 +00:00
|
|
|
|
//::WaitForSingleObject(pi.hThread, INFINITE);
|
|
|
|
|
::WaitForSingleObject(pi.hThread, 3000);
|
|
|
|
|
::WaitForSingleObject(pi.hProcess, 3000);
|
2023-06-19 11:08:42 +00:00
|
|
|
|
|
2023-06-21 10:04:16 +00:00
|
|
|
|
if (pszResultBuffer) {
|
|
|
|
|
// 从匿名管道中读取结果到输出缓冲区
|
|
|
|
|
::RtlZeroMemory(pszResultBuffer, dwResultBufferSize);
|
|
|
|
|
::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, nullptr, nullptr);
|
|
|
|
|
}
|
2023-06-19 11:08:42 +00:00
|
|
|
|
|
2023-06-25 07:57:47 +00:00
|
|
|
|
// 获取调用程序返回值
|
|
|
|
|
if (pRetCode) {
|
|
|
|
|
if (GetExitCodeProcess(pi.hProcess, &retCode)) {
|
|
|
|
|
*pRetCode = retCode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-19 11:08:42 +00:00
|
|
|
|
// 关闭句柄, 释放内存
|
|
|
|
|
::CloseHandle(pi.hThread);
|
|
|
|
|
::CloseHandle(pi.hProcess);
|
|
|
|
|
::CloseHandle(hWritePipe);
|
|
|
|
|
::CloseHandle(hReadPipe);
|
|
|
|
|
|
|
|
|
|
RemoveTailLineBreak(pszResultBuffer, dwResultBufferSize);
|
|
|
|
|
//pszResultBuffer[dwResultBufferSize - 1] = 0;
|
|
|
|
|
return ERR_SUCCESS;
|
2023-06-21 10:04:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShowWindowsErrorMessage(const TCHAR *pMsgHead) {
|
|
|
|
|
LPVOID buf;
|
|
|
|
|
|
|
|
|
|
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM |
|
|
|
|
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
|
|
|
|
nullptr,
|
|
|
|
|
GetLastError(),
|
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
|
(LPSTR)&buf,
|
|
|
|
|
0,
|
|
|
|
|
nullptr)) {
|
2023-07-14 09:29:02 +00:00
|
|
|
|
SPDLOG_ERROR(TEXT("{0} Error({1}): {2}"), pMsgHead, GetLastError(), buf);
|
2023-06-21 10:04:16 +00:00
|
|
|
|
LocalFree(buf);
|
|
|
|
|
} else {
|
2023-07-14 09:29:02 +00:00
|
|
|
|
SPDLOG_ERROR(TEXT("{0} Unknown Error{1}."), pMsgHead, GetLastError());
|
2023-06-21 10:04:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StringReplaceAll(TCHAR *pOrigin, const TCHAR *pOldStr, const TCHAR *pNewStr) {
|
|
|
|
|
using namespace std;
|
|
|
|
|
const int maxSize = lstrlen(pOrigin);
|
2023-07-10 08:36:19 +00:00
|
|
|
|
auto src = string(pOrigin);
|
2023-06-21 10:04:16 +00:00
|
|
|
|
for (string::size_type pos(0); pos != string::npos; pos += lstrlen(pNewStr)) {
|
|
|
|
|
if ((pos = src.find(pOldStr, pos)) != string::npos) {
|
|
|
|
|
src.replace(pos, lstrlen(pOldStr), pNewStr);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(pOrigin, 0, maxSize);
|
|
|
|
|
StringCbCopyA(pOrigin, maxSize, src.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StringRemoveAll(TCHAR *pOrigin, const TCHAR *pString) {
|
|
|
|
|
StringReplaceAll(pOrigin, pString, "");
|
2023-07-10 08:36:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int FindFile(const TCHAR *pPath, PFILE_LIST pFileList, const bool exitWhenMatchOne) {
|
|
|
|
|
std::vector<TCHAR *> pathList;
|
|
|
|
|
TCHAR rootPath[MAX_PATH];
|
|
|
|
|
HANDLE hFind;
|
|
|
|
|
WIN32_FIND_DATA ffd;
|
|
|
|
|
|
|
|
|
|
hFind = FindFirstFile(pPath, &ffd);
|
|
|
|
|
|
|
|
|
|
if (INVALID_HANDLE_VALUE == hFind) {
|
|
|
|
|
return ERR_ITEM_UNEXISTS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StringCbCopy(rootPath, MAX_PATH, pPath);
|
|
|
|
|
PathRemoveFileSpec(rootPath);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
|
|
|
if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
TCHAR tmp[MAX_PATH];
|
|
|
|
|
PathCombine(tmp, rootPath, ffd.cFileName);
|
|
|
|
|
|
|
|
|
|
pathList.push_back(_strdup(tmp));
|
|
|
|
|
if (exitWhenMatchOne) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while (FindNextFile(hFind, &ffd) != 0);
|
|
|
|
|
|
|
|
|
|
FindClose(hFind);
|
|
|
|
|
|
|
|
|
|
if (GetLastError() != ERROR_NO_MORE_FILES) {
|
|
|
|
|
return -ERR_FIND_FILE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pFileList->pFilePath = static_cast<PFILE_PATH>(HeapAlloc(GetProcessHeap(), 0, pathList.size() * sizeof(FILE_PATH)));
|
|
|
|
|
|
|
|
|
|
if (pFileList->pFilePath == nullptr) {
|
2023-07-14 09:29:02 +00:00
|
|
|
|
SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), pathList.size() * sizeof(FILE_PATH));
|
2023-07-10 08:36:19 +00:00
|
|
|
|
return -ERR_MALLOC_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pFileList->nItems = static_cast<unsigned int>(pathList.size());
|
|
|
|
|
|
|
|
|
|
memset(pFileList->pFilePath, 0, pathList.size() * sizeof(FILE_PATH));
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < pathList.size(); i++) {
|
|
|
|
|
StringCbCopy(pFileList->pFilePath[i].path, MAX_PATH, pathList.at(i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto iter = pathList.begin(); iter != pathList.end(); ++iter) {
|
|
|
|
|
if (*iter != nullptr) {
|
|
|
|
|
free(*iter);
|
|
|
|
|
(*iter) = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pathList.clear();
|
|
|
|
|
std::vector<TCHAR *> tmpSwapVector;
|
|
|
|
|
tmpSwapVector.swap(pathList);
|
|
|
|
|
|
|
|
|
|
return ERR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int GetWindowsServiceStatus(const TCHAR *pSvrName, PDWORD pStatus) {
|
|
|
|
|
SC_HANDLE schSCManager;
|
|
|
|
|
SC_HANDLE schService;
|
|
|
|
|
SERVICE_STATUS_PROCESS ssStatus;
|
|
|
|
|
DWORD dwBytesNeeded = 0;
|
|
|
|
|
|
|
|
|
|
if (pSvrName == nullptr || lstrlen(pSvrName) == 0) {
|
2023-07-14 09:29:02 +00:00
|
|
|
|
SPDLOG_ERROR(TEXT("Input pSvrName params error"));
|
2023-07-10 08:36:19 +00:00
|
|
|
|
return -ERR_INPUT_PARAMS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pStatus == nullptr) {
|
2023-07-14 09:29:02 +00:00
|
|
|
|
SPDLOG_ERROR(TEXT("Input pStatus params error"));
|
2023-07-10 08:36:19 +00:00
|
|
|
|
return -ERR_INPUT_PARAMS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get a handle to the SCM database.
|
|
|
|
|
schSCManager = OpenSCManager(nullptr, // local computer
|
|
|
|
|
nullptr, // ServicesActive database
|
|
|
|
|
SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
|
|
|
|
|
|
|
if (nullptr == schSCManager) {
|
|
|
|
|
SPDLOG_ERROR(TEXT("OpenSCManager failed {0}"), GetLastError());
|
|
|
|
|
return -ERR_OPEN_SCM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get a handle to the service.
|
|
|
|
|
schService = OpenService(schSCManager, // SCM database
|
|
|
|
|
pSvrName, // name of service
|
|
|
|
|
SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS); // full access
|
|
|
|
|
|
|
|
|
|
if (schService == nullptr) {
|
|
|
|
|
SPDLOG_ERROR(TEXT("OpenService failed {0}"), GetLastError());
|
|
|
|
|
CloseServiceHandle(schSCManager);
|
|
|
|
|
return -ERR_OPEN_SERVICE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check the status in case the service is not stopped.
|
|
|
|
|
if (!QueryServiceStatusEx(schService, // handle to service
|
|
|
|
|
SC_STATUS_PROCESS_INFO, // information level
|
|
|
|
|
reinterpret_cast<LPBYTE>(&ssStatus), // address of structure
|
|
|
|
|
sizeof(SERVICE_STATUS_PROCESS), // size of structure
|
|
|
|
|
&dwBytesNeeded)) // size needed if buffer is too small
|
|
|
|
|
{
|
|
|
|
|
SPDLOG_ERROR(TEXT("QueryServiceStatusEx failed {0}"), GetLastError());
|
|
|
|
|
CloseServiceHandle(schService);
|
|
|
|
|
CloseServiceHandle(schSCManager);
|
|
|
|
|
return -ERR_GET_SERVICESSTATUS;
|
|
|
|
|
} else {
|
|
|
|
|
*pStatus = ssStatus.dwCurrentState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ERR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int WideCharToTChar(const WCHAR *pWStr, TCHAR *pOutStr, int maxOutLen) {
|
|
|
|
|
if constexpr (sizeof(TCHAR) == sizeof(WCHAR)) {
|
|
|
|
|
if (wcslen(pWStr) * sizeof(WCHAR) >= maxOutLen) {
|
|
|
|
|
SPDLOG_ERROR(TEXT("Output buffer is to short: {0} need {1}"), maxOutLen, wcslen(pWStr) * sizeof(WCHAR));
|
|
|
|
|
return -ERR_INPUT_PARAMS;
|
|
|
|
|
}
|
|
|
|
|
memcpy(pOutStr, pWStr, wcslen(pWStr));
|
|
|
|
|
} else {
|
|
|
|
|
int len = WideCharToMultiByte(CP_ACP, 0, pWStr, static_cast<int>(wcslen(pWStr)), nullptr, 0, nullptr, nullptr);
|
|
|
|
|
|
|
|
|
|
if (len >= maxOutLen) {
|
|
|
|
|
SPDLOG_ERROR(TEXT("Output buffer is to short: {0} need {1}"), maxOutLen, len);
|
|
|
|
|
return -ERR_INPUT_PARAMS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, pWStr, static_cast<int>(wcslen(pWStr)), pOutStr, len, nullptr, nullptr);
|
|
|
|
|
pOutStr[len] = 0;
|
|
|
|
|
|
|
|
|
|
return ERR_SUCCESS;
|
|
|
|
|
}
|
2023-06-20 09:25:14 +00:00
|
|
|
|
}
|