#include "wl_base_help_plugin.h" // This must be included before many other Windows headers. #include #include #include #include #include #include #include #include "raserror.h" #pragma comment(lib, "wininet") #pragma comment(lib, "Rasapi32") #pragma comment(lib, "rasapi32.lib") #include // For getPlatformVersion; remove unless needed for your plugin implementation. #include #include #include #include #include #include typedef LONG NTSTATUS, * PNTSTATUS; #define STATUS_SUCCESS (0x00000000) typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); void startProxy(const int port) { INTERNET_PER_CONN_OPTION_LIST list; DWORD dwBufSize = sizeof(list); list.dwSize = sizeof(list); list.pszConnection = nullptr; auto url = "127.0.0.1:" + std::to_string(port); auto wUrl = std::wstring(url.begin(), url.end()); auto fullAddr = new WCHAR[url.length() + 1]; wcscpy_s(fullAddr, url.length() + 1, wUrl.c_str()); list.dwOptionCount = 2; list.pOptions = new INTERNET_PER_CONN_OPTION[2]; if (!list.pOptions) { return; } list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY; list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER; list.pOptions[1].Value.pszValue = fullAddr; InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); RASENTRYNAME entry; entry.dwSize = sizeof(entry); std::vector entries; DWORD size = sizeof(entry), count; LPRASENTRYNAME entryAddr = &entry; auto ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count); if (ret == ERROR_BUFFER_TOO_SMALL) { entries.resize(count); entries[0].dwSize = sizeof(RASENTRYNAME); entryAddr = entries.data(); ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count); } if (ret != ERROR_SUCCESS) { return; } for (DWORD i = 0; i < count; i++) { list.pszConnection = entryAddr[i].szEntryName; InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); } delete[] list.pOptions; InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); } void stopProxy() { INTERNET_PER_CONN_OPTION_LIST list; DWORD dwBufSize = sizeof(list); list.dwSize = sizeof(list); list.pszConnection = nullptr; list.dwOptionCount = 1; list.pOptions = new INTERNET_PER_CONN_OPTION[1]; if (nullptr == list.pOptions) { return; } list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT; InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); RASENTRYNAME entry; entry.dwSize = sizeof(entry); std::vector entries; DWORD size = sizeof(entry), count; LPRASENTRYNAME entryAddr = &entry; auto ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count); if (ret == ERROR_BUFFER_TOO_SMALL) { entries.resize(count); entries[0].dwSize = sizeof(RASENTRYNAME); entryAddr = entries.data(); ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count); } if (ret != ERROR_SUCCESS) { return; } for (DWORD i = 0; i < count; i++) { list.pszConnection = entryAddr[i].szEntryName; InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); } delete[] list.pOptions; InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); } // 检测代理是否启用的函数 bool isProxyEnabled() { INTERNET_PER_CONN_OPTION_LIST list; DWORD dwBufSize = sizeof(list); list.dwSize = sizeof(list); list.pszConnection = nullptr; list.dwOptionCount = 1; list.pOptions = new INTERNET_PER_CONN_OPTION[1]; list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; bool proxyEnabled = false; if (InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, &dwBufSize)) { proxyEnabled = (list.pOptions[0].Value.dwValue & PROXY_TYPE_PROXY) != 0; } delete[] list.pOptions; return proxyEnabled; } RTL_OSVERSIONINFOW GetRealOSVersion() { HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll"); if (hMod) { RtlGetVersionPtr fnRtlGetVersion = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion"); if (fnRtlGetVersion != nullptr) { RTL_OSVERSIONINFOW rovi = { 0 }; rovi.dwOSVersionInfoSize = sizeof(rovi); if (STATUS_SUCCESS == fnRtlGetVersion(&rovi)) { return rovi; } } } RTL_OSVERSIONINFOW rovi = { 0 }; return rovi; } bool IsWindows11OrGreater() { RTL_OSVERSIONINFOW rovi = GetRealOSVersion(); return (rovi.dwMajorVersion > 10) || (rovi.dwMajorVersion == 10 && rovi.dwBuildNumber >= 22000); } void ShowConsole() { HWND consoleWindow = GetConsoleWindow(); if (consoleWindow != NULL) { ShowWindow(consoleWindow, SW_SHOW); } } void HideConsole() { HWND consoleWindow = GetConsoleWindow(); if (consoleWindow != NULL) { ShowWindow(consoleWindow, SW_HIDE); } } bool IsProcessRunning(const std::wstring& processName) { bool isRunning = false; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot != INVALID_HANDLE_VALUE) { PROCESSENTRY32 pe32; pe32.dwSize = sizeof(PROCESSENTRY32); if (Process32First(hSnapshot, &pe32)) { do { if (processName == pe32.szExeFile) { isRunning = true; break; } } while (Process32Next(hSnapshot, &pe32)); } CloseHandle(hSnapshot); } return isRunning; } void KillProcess(const std::wstring& processName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot != INVALID_HANDLE_VALUE) { PROCESSENTRY32 pe32; pe32.dwSize = sizeof(PROCESSENTRY32); if (Process32First(hSnapshot, &pe32)) { do { if (processName == pe32.szExeFile) { HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID); if (hProcess != NULL) { TerminateProcess(hProcess, 0); CloseHandle(hProcess); break; } } } while (Process32Next(hSnapshot, &pe32)); } CloseHandle(hSnapshot); } } bool isDialUpEnabled() { DWORD dwCb = 0; DWORD dwRet = ERROR_SUCCESS; DWORD dwConnections = 0; LPRASCONN lpRasConn = NULL; // 第一次调用 RasEnumConnections 来获取所需的缓冲区大小 dwRet = RasEnumConnections(lpRasConn, &dwCb, &dwConnections); if (dwRet == ERROR_BUFFER_TOO_SMALL) { // 分配内存来保存 RAS 连接信息 lpRasConn = (LPRASCONN)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCb); if (lpRasConn == NULL) { wprintf(L"HeapAlloc failed!\n"); return false; } // 初始化结构体大小 lpRasConn[0].dwSize = sizeof(RASCONN); // 再次调用 RasEnumConnections 以填充连接信息 dwRet = RasEnumConnections(lpRasConn, &dwCb, &dwConnections); // 检查是否成功,并且有连接 if (ERROR_SUCCESS == dwRet && dwConnections > 0) { // 遍历连接,检查是否有 PPP 或 PPPoE 类型的拨号连接 for (DWORD i = 0; i < dwConnections; i++) { if (wcscmp(lpRasConn[i].szDeviceType, L"RASDT_PPP") == 0 || wcscmp(lpRasConn[i].szDeviceType, L"RASDT_PPPoE") == 0) { // 释放内存后返回 true,表示有拨号连接 HeapFree(GetProcessHeap(), 0, lpRasConn); return true; } } } // 释放内存 HeapFree(GetProcessHeap(), 0, lpRasConn); } // 没有找到符合条件的拨号连接,返回 false return false; } namespace wl_base_help { // static void WlBaseHelpPlugin::RegisterWithRegistrar( flutter::PluginRegistrarWindows *registrar) { auto channel = std::make_unique>( registrar->messenger(), "wl_base_help", &flutter::StandardMethodCodec::GetInstance()); auto plugin = std::make_unique(registrar); channel->SetMethodCallHandler( [plugin_pointer = plugin.get()](const auto &call, auto result) { plugin_pointer->HandleMethodCall(call, std::move(result)); }); registrar->AddPlugin(std::move(plugin)); } WlBaseHelpPlugin::WlBaseHelpPlugin(flutter::PluginRegistrarWindows* registrar) : registrar(registrar) {} WlBaseHelpPlugin::~WlBaseHelpPlugin() {} void WlBaseHelpPlugin::HandleMethodCall( const flutter::MethodCall& method_call, std::unique_ptr> result) { if (method_call.method_name().compare("isDialUpEnabled") == 0) { bool dialUpEnabled = isDialUpEnabled(); result->Success(flutter::EncodableValue(dialUpEnabled)); } else if (method_call.method_name().compare("startProxy") == 0) { const auto* arguments = std::get_if(method_call.arguments()); int port = std::get(arguments->at(flutter::EncodableValue("port"))); startProxy(port); result->Success(); } else if (method_call.method_name().compare("stopProxy") == 0) { stopProxy(); result->Success(); } else if (method_call.method_name().compare("isProxyEnabled") == 0) { bool enabled = isProxyEnabled(); result->Success(flutter::EncodableValue(enabled)); } else if (method_call.method_name().compare("isProcessRunning") == 0) { const auto* arguments = std::get_if(method_call.arguments()); auto processName = std::get(arguments->find(flutter::EncodableValue("processName"))->second); bool isRunning = IsProcessRunning(std::wstring(processName.begin(), processName.end())); result->Success(flutter::EncodableValue(isRunning)); } else if (method_call.method_name().compare("killProcess") == 0) { const auto* arguments = std::get_if(method_call.arguments()); auto processName = std::get(arguments->find(flutter::EncodableValue("processName"))->second); KillProcess(std::wstring(processName.begin(), processName.end())); result->Success(); } else if (method_call.method_name().compare("showConsole") == 0) { ShowConsole(); result->Success(); } else if (method_call.method_name().compare("hideConsole") == 0) { HideConsole(); result->Success(); }else if (method_call.method_name().compare("runAsAdministrator") == 0) { HWND hwnd = GetMainWindow(); // 调用您的提权逻辑,传递 hwnd TryRunAsAdmin(hwnd, result); //result->Success(flutter::EncodableValue(true)); } else if (method_call.method_name().compare("isRunningAsAdmin") == 0) { bool isAdmin = IsRunningAsAdmin(); result->Success(flutter::EncodableValue(isAdmin)); } else if (method_call.method_name().compare("getPlatformVersion") == 0) { std::ostringstream version_stream; version_stream << "Windows "; if (IsWindows11OrGreater()) { version_stream << "11+"; }else if (IsWindows10OrGreater()) { version_stream << "10+"; } else if (IsWindows8OrGreater()) { version_stream << "8"; } else if (IsWindows7OrGreater()) { version_stream << "7"; } result->Success(flutter::EncodableValue(version_stream.str())); } else { result->NotImplemented(); } } HWND WlBaseHelpPlugin::GetMainWindow() { if (registrar) { windowHwnd = registrar->GetView()->GetNativeWindow(); } return ::GetAncestor(windowHwnd, GA_ROOT); } bool WlBaseHelpPlugin::IsRunningAsAdmin() { BOOL isAdmin = FALSE; PSID adminGroup = NULL; SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; if (AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminGroup)) { if (!CheckTokenMembership(NULL, adminGroup, &isAdmin)) { isAdmin = FALSE; } FreeSid(adminGroup); } return isAdmin != FALSE; } void WlBaseHelpPlugin::TryRunAsAdmin(HWND hwnd, std::unique_ptr>& result){ wchar_t szPath[MAX_PATH]; if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath))) { std::wstring params = L"--runas-admin"; SHELLEXECUTEINFO sei = { sizeof(sei) }; sei.lpVerb = L"runas"; sei.lpFile = szPath; sei.lpParameters = params.c_str(); sei.hwnd = hwnd; sei.nShow = SW_NORMAL; if (!ShellExecuteEx(&sei)) { DWORD dwError = GetLastError(); if (dwError == ERROR_CANCELLED) { // 用户拒绝了 UAC 提示 result->Error("UAC_CANCELLED", "User cancelled the UAC prompt."); } else { // 发生其他错误 std::ostringstream errMsg; errMsg << "Failed to execute with error code: " << dwError; result->Error("EXECUTION_FAILED", errMsg.str()); } } else { result->Success(); ExitProcess(0); // 退出当前进程 } } else { result->Error("GET_MODULE_FAILED", "Failed to get module file name."); } } } // namespace wl_base_help