#include "ActiveXWrapper.h" #include "Logger.h" #include #include #include #include // 添加这个包含以使用_com_util::ConvertBSTRToString // ActiveXEventSink 实现 ActiveXEventSink::ActiveXEventSink(CommEventCallback callback) : ref_count_(1), callback_(callback) { } ActiveXEventSink::~ActiveXEventSink() { } // 修复QueryInterface函数 - 支持ICommModifyKitEvents接口 STDMETHODIMP ActiveXEventSink::QueryInterface(REFIID riid, void **ppvObject) { if (!ppvObject) { return E_POINTER; } *ppvObject = nullptr; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDispatch)) { *ppvObject = static_cast(this); AddRef(); return S_OK; } // 支持事件接口 if (IsEqualIID(riid, IID_ICommModifyKitEvents)) { *ppvObject = static_cast(this); AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) ActiveXEventSink::AddRef() { return InterlockedIncrement(&ref_count_); } STDMETHODIMP_(ULONG) ActiveXEventSink::Release() { ULONG count = InterlockedDecrement(&ref_count_); if (count == 0) { delete this; } return count; } STDMETHODIMP ActiveXEventSink::GetTypeInfoCount(UINT *pctinfo) { *pctinfo = 0; return S_OK; } STDMETHODIMP ActiveXEventSink::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { return E_NOTIMPL; } STDMETHODIMP ActiveXEventSink::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { return E_NOTIMPL; } STDMETHODIMP ActiveXEventSink::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { // 清空并重写函数,只处理6个参数的情况 // 6个参数从DISPPARAMS *pDispParams中解析出来 // 检查参数是否有效 if (!pDispParams) { LOG_ERROR("Invalid DISPPARAMS"); return E_INVALIDARG; } // 检查参数数量是否为6 if (pDispParams->cArgs != 6) { LOG_ERROR("Expected 6 parameters, but got " + std::to_string(pDispParams->cArgs)); return E_INVALIDARG; } try { // 从pDispParams中解析6个参数 VARIANT *args = pDispParams->rgvarg; // 解析参数(注意:VARIANT参数是逆序的) // 参数6: lpData (char*) char *lpData = nullptr; if (args[0].vt == VT_BYREF || args[0].vt == (VT_ARRAY | VT_UI1)) { // 处理数组数据 if (args[0].vt == (VT_ARRAY | VT_UI1) && args[0].parray) { SAFEARRAY *data = args[0].parray; BYTE *data_ptr; SafeArrayAccessData(data, reinterpret_cast(&data_ptr)); lpData = reinterpret_cast(data_ptr); } } else if (args[0].vt == VT_BSTR) { // 处理字符串数据 lpData = _com_util::ConvertBSTRToString(args[0].bstrVal); } // 参数5: dwSize (DWORD) DWORD dwSize = 0; if (args[1].vt == VT_I4 || args[1].vt == VT_UI4) { dwSize = static_cast(args[1].lVal); } // 参数4: Irp (DWORD) DWORD Irp = 0; if (args[2].vt == VT_I4 || args[2].vt == VT_UI4) { Irp = static_cast(args[2].lVal); } // 参数3: ComNumber (DWORD) DWORD ComNumber = 0; if (args[3].vt == VT_I4 || args[3].vt == VT_UI4) { ComNumber = static_cast(args[3].lVal); } // 参数2: dTime (TDateTime/double) // TDateTime dTime = 0.0; // if (args[4].vt == VT_R8) //{ // dTime = static_cast(args[4].dblVal); //} // 参数1: Sequence (int) int Sequence = 0; if (args[5].vt == VT_I4) { Sequence = args[5].lVal; } // 打印6个参数值的日志 LOG_DEBUG("ActiveX event parameters:"); // LOG_DEBUG(" Sequence: " + std::to_string(Sequence)); // LOG_DEBUG(" dTime: " + std::to_string(dTime)); LOG_DEBUG(" ComNumber: " + std::to_string(ComNumber)); LOG_DEBUG(" Irp: " + std::to_string(Irp)); LOG_DEBUG(" dwSize: " + std::to_string(dwSize)); LOG_DEBUG(" lpData: " + std::to_string(reinterpret_cast(lpData))); // 调用回调函数 if (callback_) { try { // 创建CommEventData结构以传递给回调函数 CommEventData event_data; event_data.event_type = static_cast(Irp); event_data.port = static_cast(ComNumber); if (lpData && dwSize > 0) { event_data.data.assign(reinterpret_cast(lpData), reinterpret_cast(lpData) + dwSize); } event_data.data_size = dwSize; callback_(event_data); LOG_DEBUG("ActiveX event processed successfully"); } catch (const std::exception &e) { LOG_ERROR("Error in ActiveX event callback: " + std::string(e.what())); // 释放分配的内存 if (args[0].vt == VT_BSTR && lpData) { delete[] lpData; } else if (args[0].vt == (VT_ARRAY | VT_UI1) && args[0].parray) { SafeArrayUnaccessData(args[0].parray); } return E_FAIL; } } // 释放分配的内存 if (args[0].vt == VT_BSTR && lpData) { delete[] lpData; } else if (args[0].vt == (VT_ARRAY | VT_UI1) && args[0].parray) { SafeArrayUnaccessData(args[0].parray); } } catch (const std::exception &e) { LOG_ERROR("Error processing ActiveX event: " + std::string(e.what())); return E_FAIL; } return S_OK; } // ActiveXWrapper 实现 ActiveXWrapper::ActiveXWrapper() : activex_control_(nullptr), connection_point_(nullptr), connection_cookie_(0), event_sink_(nullptr), event_connected_(false) { } ActiveXWrapper::~ActiveXWrapper() { Cleanup(); } bool ActiveXWrapper::Initialize() { if (initialized_) { return true; } // 初始化COM HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(hr) && hr != S_FALSE) { LOG_ERROR("Failed to initialize COM, HRESULT: " + std::to_string(hr)); return false; } // 使用正确的CLSID创建ActiveX控件 hr = CoCreateInstance(CLSID_CommModifyKit, nullptr, CLSCTX_INPROC_SERVER, IID_IDispatch, reinterpret_cast(&activex_control_)); if (FAILED(hr)) { LOG_ERROR("Failed to create ActiveX control, HRESULT: " + std::to_string(hr)); // 尝试使用ProgID创建 CLSID clsid; hr = CLSIDFromProgID(L"PCommMKit.CommModifyKit", &clsid); if (SUCCEEDED(hr)) { hr = CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, IID_IDispatch, reinterpret_cast(&activex_control_)); } if (FAILED(hr)) { LOG_ERROR("Failed to create ActiveX control using ProgID, HRESULT: " + std::to_string(hr)); return false; } } if (!InitializeMethodIds()) { LOG_ERROR("Failed to initialize method IDs"); return false; } // 连接事件 if (!ConnectEvents()) { LOG_ERROR("Failed to connect events"); return false; } initialized_ = true; LOG_INFO("ActiveX control initialized successfully"); return true; } bool ActiveXWrapper::ConnectEvents() { if (!activex_control_) { return false; } // 获取连接点容器 IConnectionPointContainer *cpc = nullptr; HRESULT hr = activex_control_->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast(&cpc)); if (FAILED(hr)) { LOG_ERROR("Failed to get connection point container, HRESULT: " + std::to_string(hr)); return false; } // 首先尝试直接查找事件接口的连接点 hr = cpc->FindConnectionPoint(IID_ICommModifyKitEvents, &connection_point_); if (SUCCEEDED(hr)) { LOG_INFO("Found connection point for ICommModifyKitEvents directly"); } else { LOG_WARNING("Direct connection point lookup failed, HRESULT: " + std::to_string(hr) + ", trying enumeration"); // 如果直接查找失败,枚举所有连接点 IEnumConnectionPoints *enum_cp = nullptr; hr = cpc->EnumConnectionPoints(&enum_cp); if (SUCCEEDED(hr)) { IConnectionPoint *cp = nullptr; ULONG fetched = 0; // 枚举所有连接点,查找正确的事件接口 while (enum_cp->Next(1, &cp, &fetched) == S_OK && fetched > 0) { IID iid; if (SUCCEEDED(cp->GetConnectionInterface(&iid))) { // 记录找到的接口ID用于调试 char iid_str[64]; sprintf_s(iid_str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", iid.Data1, iid.Data2, iid.Data3, iid.Data4[0], iid.Data4[1], iid.Data4[2], iid.Data4[3], iid.Data4[4], iid.Data4[5], iid.Data4[6], iid.Data4[7]); LOG_DEBUG("Found connection point with IID: " + std::string(iid_str)); // 检查是否是我们需要的事件接口 if (IsEqualIID(iid, IID_ICommModifyKitEvents)) { connection_point_ = cp; connection_point_->AddRef(); cp->Release(); // 释放枚举得到的引用 LOG_INFO("Found ICommModifyKitEvents connection point through enumeration"); break; } } cp->Release(); } enum_cp->Release(); } } cpc->Release(); if (!connection_point_) { LOG_ERROR("Failed to find any connection point for ICommModifyKitEvents"); return false; } // 创建事件接收器 event_sink_ = new ActiveXEventSink([this](const CommEventData &event_data) { // 直接使用通用事件数据调用通用回调 if (event_callback_) { event_callback_(event_data); } }); // 连接事件接收器 hr = connection_point_->Advise(event_sink_, &connection_cookie_); if (FAILED(hr)) { LOG_ERROR("Failed to advise connection point, HRESULT: " + std::to_string(hr)); event_sink_->Release(); event_sink_ = nullptr; return false; } event_connected_ = true; LOG_INFO("ActiveX events connected successfully, cookie: " + std::to_string(connection_cookie_)); return true; } void ActiveXWrapper::DisconnectEvents() { if (event_connected_ && connection_point_ && connection_cookie_ != 0) { connection_point_->Unadvise(connection_cookie_); connection_cookie_ = 0; event_connected_ = false; } if (connection_point_) { connection_point_->Release(); connection_point_ = nullptr; } if (event_sink_) { event_sink_->Release(); event_sink_ = nullptr; } } bool ActiveXWrapper::InitializeMethodIds() { if (!activex_control_) { return false; } // 获取方法的DISPID LPOLESTR method_names[] = { const_cast(L"InitMonitor"), const_cast(L"MonitorPort"), const_cast(L"StopPort"), const_cast(L"ReadData"), const_cast(L"WriteData"), const_cast(L"FreeMonitor"), const_cast(L"GetLastError")}; DISPID *method_ids[] = { &init_monitor_id_, &monitor_port_id_, &stop_port_id_, &read_data_id_, &write_data_id_, &free_monitor_id_, &get_last_error_id_}; for (int i = 0; i < 7; i++) { HRESULT hr = activex_control_->GetIDsOfNames(IID_NULL, &method_names[i], 1, LOCALE_USER_DEFAULT, method_ids[i]); if (FAILED(hr)) { LOG_ERROR("Failed to get method ID for method"); return false; } } return true; } HRESULT ActiveXWrapper::InvokeMethod(DISPID dispid, VARIANT *params, int param_count, VARIANT *result) { if (!activex_control_) { return E_FAIL; } DISPPARAMS disp_params = {params, nullptr, param_count, 0}; EXCEPINFO excep_info = {0}; UINT arg_err = 0; return activex_control_->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp_params, result, &excep_info, &arg_err); } bool ActiveXWrapper::InitMonitor(const std::string &key) { if (!initialized_) { LOG_ERROR("ActiveX control not initialized"); return false; } std::lock_guard lock(mutex_); if (callback_initialized_) { return true; } // 转换字符串参数 _bstr_t bstr_key(key.c_str()); VARIANT param; VariantInit(¶m); param.vt = VT_BSTR; param.bstrVal = bstr_key; VARIANT result; VariantInit(&result); HRESULT hr = InvokeMethod(init_monitor_id_, ¶m, 1, &result); bool success = false; if (SUCCEEDED(hr) && result.vt == VT_BOOL) { success = result.boolVal != VARIANT_FALSE; callback_initialized_ = success; } VariantClear(¶m); VariantClear(&result); if (success) { LOG_INFO("InitMonitor succeeded"); } else { LOG_ERROR("InitMonitor failed, error code: " + std::to_string(GetLastError())); } return success; } bool ActiveXWrapper::MonitorPort(int port) { if (!initialized_ || !callback_initialized_) { LOG_ERROR("ActiveX control not properly initialized"); return false; } std::lock_guard lock(mutex_); VARIANT param; VariantInit(¶m); param.vt = VT_I4; param.lVal = port; VARIANT result; VariantInit(&result); HRESULT hr = InvokeMethod(monitor_port_id_, ¶m, 1, &result); bool success = false; if (SUCCEEDED(hr) && result.vt == VT_BOOL) { success = result.boolVal != VARIANT_FALSE; if (success) { monitored_ports_[port] = true; } } VariantClear(¶m); VariantClear(&result); if (success) { LOG_INFO("MonitorPort succeeded for port " + std::to_string(port)); } else { LOG_ERROR("MonitorPort failed for port " + std::to_string(port) + ", error code: " + std::to_string(GetLastError())); } return success; } bool ActiveXWrapper::StopPort(int port) { if (!initialized_) { LOG_ERROR("ActiveX control not initialized"); return false; } std::lock_guard lock(mutex_); VARIANT param; VariantInit(¶m); param.vt = VT_I4; param.lVal = port; VARIANT result; VariantInit(&result); HRESULT hr = InvokeMethod(stop_port_id_, ¶m, 1, &result); bool success = false; if (SUCCEEDED(hr) && result.vt == VT_BOOL) { success = result.boolVal != VARIANT_FALSE; if (success) { monitored_ports_[port] = false; } } VariantClear(¶m); VariantClear(&result); if (success) { LOG_INFO("StopPort succeeded for port " + std::to_string(port)); } else { LOG_ERROR("StopPort failed for port " + std::to_string(port) + ", error code: " + std::to_string(GetLastError())); } return success; } // 修复ReadData函数 - 移除SafeArrayDestroy双重释放 bool ActiveXWrapper::ReadData(int port, const std::string &hex_data) { if (!initialized_) { LOG_ERROR("ActiveX control not initialized"); return false; } std::lock_guard lock(mutex_); // 将十六进制字符串转换为字节数组 std::vector bytes = Utils::ConvertHexStringToBytes(hex_data); // 使用辅助函数创建SafeArray SAFEARRAY *sa = CreateSafeArrayFromBytes(bytes); if (!sa) { LOG_ERROR("Failed to create SafeArray"); return false; } // 准备参数 VARIANT params[3]; VariantInit(¶ms[0]); VariantInit(¶ms[1]); VariantInit(¶ms[2]); params[0].vt = VT_I4; params[0].lVal = port; params[1].vt = VT_ARRAY | VT_UI1; params[1].parray = sa; params[2].vt = VT_I4; params[2].lVal = static_cast(bytes.size()); VARIANT result; VariantInit(&result); // 调用ActiveX控件的ReadData方法 HRESULT hr = InvokeMethod(read_data_id_, params, 3, &result); bool success = SUCCEEDED(hr); if (success && result.vt == VT_BOOL) { success = result.boolVal != VARIANT_FALSE; } // 只清理VARIANT,VariantClear会自动处理SafeArray for (int i = 0; i < 3; i++) { VariantClear(¶ms[i]); } VariantClear(&result); // 不要调用SafeArrayDestroy(sa) - 这会导致双重释放崩溃 if (success) { LOG_DEBUG("ReadData succeeded for port " + std::to_string(port) + ", data: " + hex_data); } else { LOG_ERROR("ReadData failed for port " + std::to_string(port) + ", HRESULT: " + std::to_string(hr)); } return success; } // 修复WriteData函数 - 移除SafeArrayDestroy双重释放 bool ActiveXWrapper::WriteData(int port, const std::string &hex_data) { if (!initialized_) { LOG_ERROR("ActiveX control not initialized"); return false; } std::lock_guard lock(mutex_); // 将十六进制字符串转换为字节数组 std::vector bytes = Utils::ConvertHexStringToBytes(hex_data); // 使用辅助函数创建SafeArray SAFEARRAY *sa = CreateSafeArrayFromBytes(bytes); if (!sa) { LOG_ERROR("Failed to create SafeArray"); return false; } // 准备参数 VARIANT params[3]; VariantInit(¶ms[0]); VariantInit(¶ms[1]); VariantInit(¶ms[2]); params[0].vt = VT_I4; params[0].lVal = port; params[1].vt = VT_ARRAY | VT_UI1; params[1].parray = sa; params[2].vt = VT_I4; params[2].lVal = static_cast(bytes.size()); VARIANT result; VariantInit(&result); // 调用ActiveX控件的WriteData方法 HRESULT hr = InvokeMethod(write_data_id_, params, 3, &result); bool success = SUCCEEDED(hr); if (success && result.vt == VT_BOOL) { success = result.boolVal != VARIANT_FALSE; } // 只清理VARIANT,VariantClear会自动处理SafeArray for (int i = 0; i < 3; i++) { VariantClear(¶ms[i]); } VariantClear(&result); // 不要调用SafeArrayDestroy(sa) - 这会导致双重释放崩溃 if (success) { LOG_DEBUG("WriteData succeeded for port " + std::to_string(port) + ", data: " + hex_data); } else { LOG_ERROR("WriteData failed for port " + std::to_string(port) + ", HRESULT: " + std::to_string(hr)); } return success; } bool ActiveXWrapper::FreeMonitor() { if (!initialized_) { return true; } std::lock_guard lock(mutex_); VARIANT result; VariantInit(&result); HRESULT hr = InvokeMethod(free_monitor_id_, nullptr, 0, &result); bool success = SUCCEEDED(hr); if (success) { callback_initialized_ = false; monitored_ports_.clear(); LOG_INFO("FreeMonitor succeeded"); } else { LOG_ERROR("FreeMonitor failed"); } VariantClear(&result); return success; } int ActiveXWrapper::GetLastError() { if (!initialized_) { return -1; } VARIANT result; VariantInit(&result); HRESULT hr = InvokeMethod(get_last_error_id_, nullptr, 0, &result); int error_code = -1; if (SUCCEEDED(hr) && result.vt == VT_I4) { error_code = result.lVal; } VariantClear(&result); return error_code; } void ActiveXWrapper::SetEventCallback(CommEventCallback callback) { // 调用基类的实现来设置回调 CommWrapperBase::SetEventCallback(callback); // 设置ActiveX事件回调,将ActiveX事件数据转换为通用事件数据后再调用通用回调 event_callback_ = [this](const CommEventData &event_data) { // 调用通用回调 if (event_callback_) { event_callback_(event_data); } }; } std::string ActiveXWrapper::GetErrorMessage(int error_code) { switch (error_code) { case -241: return "安装驱动失败"; case -243: return "其他错误"; case -244: return "驱动文件"; case -255: return "绑定串口失败"; case -254: return "第一次启动安装,必须以管理员权限运行"; case -253: return "启动驱动服务失败"; case -252: return "请检查Key是否有效"; case -1: return "无效操作"; case 0: return "成功"; case 1: return "串口打开失败"; case 2: return "串口配置失败"; case 3: return "串口读取失败"; case 4: return "串口写入失败"; case 5: return "串口关闭失败"; default: return "未知错误"; } } bool ActiveXWrapper::IsPortMonitored(int port) { std::lock_guard lock(mutex_); auto it = monitored_ports_.find(port); return it != monitored_ports_.end() && it->second; } SAFEARRAY *ActiveXWrapper::CreateSafeArrayFromBytes(const std::vector &bytes) { // 创建SafeArray来传递字节数组 SAFEARRAYBOUND bounds[1]; bounds[0].lLbound = 0; bounds[0].cElements = static_cast(bytes.size()); SAFEARRAY *sa = SafeArrayCreate(VT_UI1, 1, bounds); if (!sa) { LOG_ERROR("Failed to create SafeArray"); return nullptr; } // 将数据复制到SafeArray BYTE *data_ptr; HRESULT hr = SafeArrayAccessData(sa, reinterpret_cast(&data_ptr)); if (SUCCEEDED(hr)) { memcpy(data_ptr, bytes.data(), bytes.size()); SafeArrayUnaccessData(sa); } else { LOG_ERROR("Failed to access SafeArray data"); SafeArrayDestroy(sa); return nullptr; } return sa; } void ActiveXWrapper::Cleanup() { if (initialized_) { FreeMonitor(); DisconnectEvents(); if (activex_control_) { activex_control_->Release(); activex_control_ = nullptr; } // 释放COM CoUninitialize(); initialized_ = false; LOG_INFO("ActiveX control cleaned up"); } }