wl_base_help_plugin.cpp 12 KB

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