main.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #include <flutter/dart_project.h>
  2. #include <flutter/flutter_view_controller.h>
  3. #include <tchar.h>
  4. #include <uni_links_desktop/uni_links_desktop_plugin.h>
  5. #include <windows.h>
  6. #include <algorithm>
  7. #include <iostream>
  8. #include "flutter_window.h"
  9. #include "utils.h"
  10. typedef char** (*FUNC_RUSTDESK_CORE_MAIN)(int*);
  11. typedef void (*FUNC_RUSTDESK_FREE_ARGS)( char**, int);
  12. typedef int (*FUNC_RUSTDESK_GET_APP_NAME)(wchar_t*, int);
  13. /// Note: `--server`, `--service` are already handled in [core_main.rs].
  14. const std::vector<std::string> parameters_white_list = {"--install", "--cm"};
  15. const wchar_t* getWindowClassName();
  16. int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
  17. _In_ wchar_t *command_line, _In_ int show_command)
  18. {
  19. HINSTANCE hInstance = LoadLibraryA("librustdesk.dll");
  20. if (!hInstance)
  21. {
  22. std::cout << "Failed to load librustdesk.dll." << std::endl;
  23. return EXIT_FAILURE;
  24. }
  25. FUNC_RUSTDESK_CORE_MAIN rustdesk_core_main =
  26. (FUNC_RUSTDESK_CORE_MAIN)GetProcAddress(hInstance, "rustdesk_core_main_args");
  27. if (!rustdesk_core_main)
  28. {
  29. std::cout << "Failed to get rustdesk_core_main." << std::endl;
  30. return EXIT_FAILURE;
  31. }
  32. FUNC_RUSTDESK_FREE_ARGS free_c_args =
  33. (FUNC_RUSTDESK_FREE_ARGS)GetProcAddress(hInstance, "free_c_args");
  34. if (!free_c_args)
  35. {
  36. std::cout << "Failed to get free_c_args." << std::endl;
  37. return EXIT_FAILURE;
  38. }
  39. std::vector<std::string> command_line_arguments =
  40. GetCommandLineArguments();
  41. // Remove possible trailing whitespace from command line arguments
  42. for (auto& argument : command_line_arguments) {
  43. argument.erase(argument.find_last_not_of(" \n\r\t"));
  44. }
  45. int args_len = 0;
  46. char** c_args = rustdesk_core_main(&args_len);
  47. if (!c_args)
  48. {
  49. std::string args_str = "";
  50. for (const auto& argument : command_line_arguments) {
  51. args_str += (argument + " ");
  52. }
  53. // std::cout << "RustDesk [" << args_str << "], core returns false, exiting without launching Flutter app." << std::endl;
  54. return EXIT_SUCCESS;
  55. }
  56. std::vector<std::string> rust_args(c_args, c_args + args_len);
  57. free_c_args(c_args, args_len);
  58. std::wstring app_name = L"RustDesk";
  59. FUNC_RUSTDESK_GET_APP_NAME get_rustdesk_app_name = (FUNC_RUSTDESK_GET_APP_NAME)GetProcAddress(hInstance, "get_rustdesk_app_name");
  60. if (get_rustdesk_app_name) {
  61. wchar_t app_name_buffer[512] = {0};
  62. if (get_rustdesk_app_name(app_name_buffer, 512) == 0) {
  63. app_name = std::wstring(app_name_buffer);
  64. }
  65. }
  66. // Uri links dispatch
  67. HWND hwnd = ::FindWindowW(getWindowClassName(), app_name.c_str());
  68. if (hwnd != NULL) {
  69. // Allow multiple flutter instances when being executed by parameters
  70. // contained in whitelists.
  71. bool allow_multiple_instances = false;
  72. for (auto& whitelist_param : parameters_white_list) {
  73. allow_multiple_instances =
  74. allow_multiple_instances ||
  75. std::find(command_line_arguments.begin(),
  76. command_line_arguments.end(),
  77. whitelist_param) != command_line_arguments.end();
  78. }
  79. if (!allow_multiple_instances) {
  80. if (!command_line_arguments.empty()) {
  81. // Dispatch command line arguments
  82. DispatchToUniLinksDesktop(hwnd);
  83. } else {
  84. // Not called with arguments, or just open the app shortcut on desktop.
  85. // So we just show the main window instead.
  86. ::ShowWindow(hwnd, SW_NORMAL);
  87. ::SetForegroundWindow(hwnd);
  88. }
  89. return EXIT_FAILURE;
  90. }
  91. }
  92. // Attach to console when present (e.g., 'flutter run') or create a
  93. // new console when running with a debugger.
  94. if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent())
  95. {
  96. CreateAndAttachConsole();
  97. }
  98. // Initialize COM, so that it is available for use in the library and/or
  99. // plugins.
  100. ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
  101. flutter::DartProject project(L"data");
  102. // connection manager hide icon from taskbar
  103. bool is_cm_page = false;
  104. auto cmParam = std::string("--cm");
  105. if (!command_line_arguments.empty() && command_line_arguments.front().compare(0, cmParam.size(), cmParam.c_str()) == 0) {
  106. is_cm_page = true;
  107. }
  108. bool is_install_page = false;
  109. auto installParam = std::string("--install");
  110. if (!command_line_arguments.empty() && command_line_arguments.front().compare(0, installParam.size(), installParam.c_str()) == 0) {
  111. is_install_page = true;
  112. }
  113. command_line_arguments.insert(command_line_arguments.end(), rust_args.begin(), rust_args.end());
  114. project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
  115. FlutterWindow window(project);
  116. Win32Window::Point origin(10, 10);
  117. Win32Window::Size size(800, 600);
  118. std::wstring window_title;
  119. if (is_cm_page) {
  120. window_title = app_name + L" - Connection Manager";
  121. } else if (is_install_page) {
  122. window_title = app_name + L" - Install";
  123. } else {
  124. window_title = app_name;
  125. }
  126. if (!window.CreateAndShow(window_title, origin, size, !is_cm_page)) {
  127. return EXIT_FAILURE;
  128. }
  129. window.SetQuitOnClose(true);
  130. ::MSG msg;
  131. while (::GetMessage(&msg, nullptr, 0, 0))
  132. {
  133. ::TranslateMessage(&msg);
  134. ::DispatchMessage(&msg);
  135. }
  136. ::CoUninitialize();
  137. return EXIT_SUCCESS;
  138. }