wl_base_help_plugin.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. #include "wl_base_help_plugin.h"
  2. // This must be included before many other Windows headers.
  3. #include <windows.h>
  4. #include <tlhelp32.h>
  5. #include <WinInet.h>
  6. #include <Ras.h>
  7. #include <RasError.h>
  8. #include <vector>
  9. #include <iostream>
  10. #include "raserror.h"
  11. #pragma comment(lib, "wininet")
  12. #pragma comment(lib, "Rasapi32")
  13. #pragma comment(lib, "rasapi32.lib")
  14. #include <string>
  15. // For getPlatformVersion; remove unless needed for your plugin implementation.
  16. #include <VersionHelpers.h>
  17. #include <flutter/method_channel.h>
  18. #include <flutter/plugin_registrar_windows.h>
  19. #include <flutter/standard_method_codec.h>
  20. #include <memory>
  21. #include <sstream>
  22. typedef LONG NTSTATUS, * PNTSTATUS;
  23. #define STATUS_SUCCESS (0x00000000)
  24. typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
  25. void startProxy(const int port)
  26. {
  27. INTERNET_PER_CONN_OPTION_LIST list;
  28. DWORD dwBufSize = sizeof(list);
  29. list.dwSize = sizeof(list);
  30. list.pszConnection = nullptr;
  31. auto url = "127.0.0.1:" + std::to_string(port);
  32. auto wUrl = std::wstring(url.begin(), url.end());
  33. auto fullAddr = new WCHAR[url.length() + 1];
  34. wcscpy_s(fullAddr, url.length() + 1, wUrl.c_str());
  35. list.dwOptionCount = 2;
  36. list.pOptions = new INTERNET_PER_CONN_OPTION[2];
  37. if (!list.pOptions)
  38. {
  39. return;
  40. }
  41. list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
  42. list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY;
  43. list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
  44. list.pOptions[1].Value.pszValue = fullAddr;
  45. InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
  46. RASENTRYNAME entry;
  47. entry.dwSize = sizeof(entry);
  48. std::vector<RASENTRYNAME> entries;
  49. DWORD size = sizeof(entry), count;
  50. LPRASENTRYNAME entryAddr = &entry;
  51. auto ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
  52. if (ret == ERROR_BUFFER_TOO_SMALL)
  53. {
  54. entries.resize(count);
  55. entries[0].dwSize = sizeof(RASENTRYNAME);
  56. entryAddr = entries.data();
  57. ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
  58. }
  59. if (ret != ERROR_SUCCESS)
  60. {
  61. return;
  62. }
  63. for (DWORD i = 0; i < count; i++)
  64. {
  65. list.pszConnection = entryAddr[i].szEntryName;
  66. InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
  67. }
  68. delete[] list.pOptions;
  69. InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0);
  70. InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0);
  71. }
  72. void stopProxy()
  73. {
  74. INTERNET_PER_CONN_OPTION_LIST list;
  75. DWORD dwBufSize = sizeof(list);
  76. list.dwSize = sizeof(list);
  77. list.pszConnection = nullptr;
  78. list.dwOptionCount = 1;
  79. list.pOptions = new INTERNET_PER_CONN_OPTION[1];
  80. if (nullptr == list.pOptions)
  81. {
  82. return;
  83. }
  84. list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
  85. list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT;
  86. InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
  87. RASENTRYNAME entry;
  88. entry.dwSize = sizeof(entry);
  89. std::vector<RASENTRYNAME> entries;
  90. DWORD size = sizeof(entry), count;
  91. LPRASENTRYNAME entryAddr = &entry;
  92. auto ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
  93. if (ret == ERROR_BUFFER_TOO_SMALL)
  94. {
  95. entries.resize(count);
  96. entries[0].dwSize = sizeof(RASENTRYNAME);
  97. entryAddr = entries.data();
  98. ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
  99. }
  100. if (ret != ERROR_SUCCESS)
  101. {
  102. return;
  103. }
  104. for (DWORD i = 0; i < count; i++)
  105. {
  106. list.pszConnection = entryAddr[i].szEntryName;
  107. InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
  108. }
  109. delete[] list.pOptions;
  110. InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0);
  111. InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0);
  112. }
  113. // 检测代理是否启用的函数
  114. bool isProxyEnabled() {
  115. INTERNET_PER_CONN_OPTION_LIST list;
  116. DWORD dwBufSize = sizeof(list);
  117. list.dwSize = sizeof(list);
  118. list.pszConnection = nullptr;
  119. list.dwOptionCount = 1;
  120. list.pOptions = new INTERNET_PER_CONN_OPTION[1];
  121. list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
  122. bool proxyEnabled = false;
  123. if (InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, &dwBufSize)) {
  124. proxyEnabled = (list.pOptions[0].Value.dwValue & PROXY_TYPE_PROXY) != 0;
  125. }
  126. delete[] list.pOptions;
  127. return proxyEnabled;
  128. }
  129. RTL_OSVERSIONINFOW GetRealOSVersion() {
  130. HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
  131. if (hMod) {
  132. RtlGetVersionPtr fnRtlGetVersion = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
  133. if (fnRtlGetVersion != nullptr) {
  134. RTL_OSVERSIONINFOW rovi = { 0 };
  135. rovi.dwOSVersionInfoSize = sizeof(rovi);
  136. if (STATUS_SUCCESS == fnRtlGetVersion(&rovi)) {
  137. return rovi;
  138. }
  139. }
  140. }
  141. RTL_OSVERSIONINFOW rovi = { 0 };
  142. return rovi;
  143. }
  144. bool IsWindows11OrGreater() {
  145. RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
  146. return (rovi.dwMajorVersion > 10) ||
  147. (rovi.dwMajorVersion == 10 && rovi.dwBuildNumber >= 22000);
  148. }
  149. void ShowConsole() {
  150. HWND consoleWindow = GetConsoleWindow();
  151. if (consoleWindow != NULL) {
  152. ShowWindow(consoleWindow, SW_SHOW);
  153. }
  154. }
  155. void HideConsole() {
  156. HWND consoleWindow = GetConsoleWindow();
  157. if (consoleWindow != NULL) {
  158. ShowWindow(consoleWindow, SW_HIDE);
  159. }
  160. }
  161. bool IsProcessRunning(const std::wstring& processName) {
  162. bool isRunning = false;
  163. HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  164. if (hSnapshot != INVALID_HANDLE_VALUE) {
  165. PROCESSENTRY32 pe32;
  166. pe32.dwSize = sizeof(PROCESSENTRY32);
  167. if (Process32First(hSnapshot, &pe32)) {
  168. do {
  169. if (processName == pe32.szExeFile) {
  170. isRunning = true;
  171. break;
  172. }
  173. } while (Process32Next(hSnapshot, &pe32));
  174. }
  175. CloseHandle(hSnapshot);
  176. }
  177. return isRunning;
  178. }
  179. void KillProcess(const std::wstring& processName) {
  180. HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  181. if (hSnapshot != INVALID_HANDLE_VALUE) {
  182. PROCESSENTRY32 pe32;
  183. pe32.dwSize = sizeof(PROCESSENTRY32);
  184. if (Process32First(hSnapshot, &pe32)) {
  185. do {
  186. if (processName == pe32.szExeFile) {
  187. HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID);
  188. if (hProcess != NULL) {
  189. TerminateProcess(hProcess, 0);
  190. CloseHandle(hProcess);
  191. break;
  192. }
  193. }
  194. } while (Process32Next(hSnapshot, &pe32));
  195. }
  196. CloseHandle(hSnapshot);
  197. }
  198. }
  199. bool isDialUpEnabled() {
  200. DWORD dwCb = 0;
  201. DWORD dwRet = ERROR_SUCCESS;
  202. DWORD dwConnections = 0;
  203. LPRASCONN lpRasConn = NULL;
  204. // 第一次调用 RasEnumConnections 来获取所需的缓冲区大小
  205. dwRet = RasEnumConnections(lpRasConn, &dwCb, &dwConnections);
  206. if (dwRet == ERROR_BUFFER_TOO_SMALL) {
  207. // 分配内存来保存 RAS 连接信息
  208. lpRasConn = (LPRASCONN)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCb);
  209. if (lpRasConn == NULL) {
  210. wprintf(L"HeapAlloc failed!\n");
  211. return false;
  212. }
  213. // 初始化结构体大小
  214. lpRasConn[0].dwSize = sizeof(RASCONN);
  215. // 再次调用 RasEnumConnections 以填充连接信息
  216. dwRet = RasEnumConnections(lpRasConn, &dwCb, &dwConnections);
  217. // 检查是否成功,并且有连接
  218. if (ERROR_SUCCESS == dwRet && dwConnections > 0) {
  219. // 遍历连接,检查是否有 PPP 或 PPPoE 类型的拨号连接
  220. for (DWORD i = 0; i < dwConnections; i++) {
  221. if (wcscmp(lpRasConn[i].szDeviceType, L"RASDT_PPP") == 0 ||
  222. wcscmp(lpRasConn[i].szDeviceType, L"RASDT_PPPoE") == 0) {
  223. // 释放内存后返回 true,表示有拨号连接
  224. HeapFree(GetProcessHeap(), 0, lpRasConn);
  225. return true;
  226. }
  227. }
  228. }
  229. // 释放内存
  230. HeapFree(GetProcessHeap(), 0, lpRasConn);
  231. }
  232. // 没有找到符合条件的拨号连接,返回 false
  233. return false;
  234. }
  235. namespace wl_base_help {
  236. // static
  237. void WlBaseHelpPlugin::RegisterWithRegistrar(
  238. flutter::PluginRegistrarWindows *registrar) {
  239. auto channel =
  240. std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
  241. registrar->messenger(), "wl_base_help",
  242. &flutter::StandardMethodCodec::GetInstance());
  243. auto plugin = std::make_unique<WlBaseHelpPlugin>(registrar);
  244. channel->SetMethodCallHandler(
  245. [plugin_pointer = plugin.get()](const auto &call, auto result) {
  246. plugin_pointer->HandleMethodCall(call, std::move(result));
  247. });
  248. registrar->AddPlugin(std::move(plugin));
  249. }
  250. WlBaseHelpPlugin::WlBaseHelpPlugin(flutter::PluginRegistrarWindows* registrar) : registrar(registrar) {}
  251. WlBaseHelpPlugin::~WlBaseHelpPlugin() {}
  252. void WlBaseHelpPlugin::HandleMethodCall(
  253. const flutter::MethodCall<flutter::EncodableValue>& method_call,
  254. std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
  255. if (method_call.method_name().compare("isDialUpEnabled") == 0) {
  256. bool dialUpEnabled = isDialUpEnabled();
  257. result->Success(flutter::EncodableValue(dialUpEnabled));
  258. } else if (method_call.method_name().compare("startProxy") == 0) {
  259. const auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
  260. int port = std::get<int>(arguments->at(flutter::EncodableValue("port")));
  261. startProxy(port);
  262. result->Success();
  263. } else if (method_call.method_name().compare("stopProxy") == 0) {
  264. stopProxy();
  265. result->Success();
  266. } else if (method_call.method_name().compare("isProxyEnabled") == 0) {
  267. bool enabled = isProxyEnabled();
  268. result->Success(flutter::EncodableValue(enabled));
  269. } else if (method_call.method_name().compare("isProcessRunning") == 0) {
  270. const auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
  271. auto processName = std::get<std::string>(arguments->find(flutter::EncodableValue("processName"))->second);
  272. bool isRunning = IsProcessRunning(std::wstring(processName.begin(), processName.end()));
  273. result->Success(flutter::EncodableValue(isRunning));
  274. }
  275. else if (method_call.method_name().compare("killProcess") == 0) {
  276. const auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
  277. auto processName = std::get<std::string>(arguments->find(flutter::EncodableValue("processName"))->second);
  278. KillProcess(std::wstring(processName.begin(), processName.end()));
  279. result->Success();
  280. }
  281. else if (method_call.method_name().compare("showConsole") == 0) {
  282. ShowConsole();
  283. result->Success();
  284. }
  285. else if (method_call.method_name().compare("hideConsole") == 0) {
  286. HideConsole();
  287. result->Success();
  288. }else if (method_call.method_name().compare("runAsAdministrator") == 0) {
  289. HWND hwnd = GetMainWindow();
  290. // 调用您的提权逻辑,传递 hwnd
  291. TryRunAsAdmin(hwnd, result);
  292. //result->Success(flutter::EncodableValue(true));
  293. }
  294. else if (method_call.method_name().compare("isRunningAsAdmin") == 0) {
  295. bool isAdmin = IsRunningAsAdmin();
  296. result->Success(flutter::EncodableValue(isAdmin));
  297. }
  298. else if (method_call.method_name().compare("getPlatformVersion") == 0) {
  299. std::ostringstream version_stream;
  300. version_stream << "Windows ";
  301. if (IsWindows11OrGreater()) {
  302. version_stream << "11+";
  303. }else if (IsWindows10OrGreater()) {
  304. version_stream << "10+";
  305. } else if (IsWindows8OrGreater()) {
  306. version_stream << "8";
  307. } else if (IsWindows7OrGreater()) {
  308. version_stream << "7";
  309. }
  310. result->Success(flutter::EncodableValue(version_stream.str()));
  311. } else {
  312. result->NotImplemented();
  313. }
  314. }
  315. HWND WlBaseHelpPlugin::GetMainWindow() {
  316. if (registrar)
  317. {
  318. windowHwnd = registrar->GetView()->GetNativeWindow();
  319. }
  320. return ::GetAncestor(windowHwnd, GA_ROOT);
  321. }
  322. bool WlBaseHelpPlugin::IsRunningAsAdmin() {
  323. BOOL isAdmin = FALSE;
  324. PSID adminGroup = NULL;
  325. SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
  326. if (AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
  327. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
  328. &adminGroup)) {
  329. if (!CheckTokenMembership(NULL, adminGroup, &isAdmin)) {
  330. isAdmin = FALSE;
  331. }
  332. FreeSid(adminGroup);
  333. }
  334. return isAdmin != FALSE;
  335. }
  336. void WlBaseHelpPlugin::TryRunAsAdmin(HWND hwnd,
  337. std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>& result){
  338. wchar_t szPath[MAX_PATH];
  339. if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath))) {
  340. std::wstring params = L"--runas-admin";
  341. SHELLEXECUTEINFO sei = { sizeof(sei) };
  342. sei.lpVerb = L"runas";
  343. sei.lpFile = szPath;
  344. sei.lpParameters = params.c_str();
  345. sei.hwnd = hwnd;
  346. sei.nShow = SW_NORMAL;
  347. if (!ShellExecuteEx(&sei)) {
  348. DWORD dwError = GetLastError();
  349. if (dwError == ERROR_CANCELLED) {
  350. // 用户拒绝了 UAC 提示
  351. result->Error("UAC_CANCELLED", "User cancelled the UAC prompt.");
  352. } else {
  353. // 发生其他错误
  354. std::ostringstream errMsg;
  355. errMsg << "Failed to execute with error code: " << dwError;
  356. result->Error("EXECUTION_FAILED", errMsg.str());
  357. }
  358. } else {
  359. result->Success();
  360. ExitProcess(0); // 退出当前进程
  361. }
  362. } else {
  363. result->Error("GET_MODULE_FAILED", "Failed to get module file name.");
  364. }
  365. }
  366. } // namespace wl_base_help