Forráskód Böngészése

win32 systray functionality

valenok 15 éve
szülő
commit
1a9b36e842
3 módosított fájl, 104 hozzáadás és 57 törlés
  1. 103 57
      main.c
  2. 1 0
      win32/res.rc
  3. BIN
      win32/systray.ico

+ 103 - 57
main.c

@@ -17,9 +17,9 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
- 
+
 #if defined(_WIN32)
-#define _CRT_SECURE_NO_WARNINGS	// Disable deprecation warning in VS2005
+#define _CRT_SECURE_NO_WARNINGS  // Disable deprecation warning in VS2005
 #else
 #define _XOPEN_SOURCE 600  // For PATH_MAX on linux
 #endif
@@ -42,9 +42,9 @@
 #define PATH_MAX MAX_PATH
 #define S_ISDIR(x) ((x) & _S_IFDIR)
 #define DIRSEP '\\'
-#define	snprintf _snprintf
-#define	vsnprintf _vsnprintf
-#define	sleep(x) Sleep((x) * 1000)
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define sleep(x) Sleep((x) * 1000)
 #define WINCDECL __cdecl
 #else
 #include <sys/wait.h>
@@ -58,10 +58,11 @@
 static int exit_flag;
 static char *options[MAX_OPTIONS];
 static char server_name[40];
+static char *config_file;
 static struct mg_context *ctx;
 
 #if !defined(CONFIG_FILE)
-#define	CONFIG_FILE "mongoose.conf"
+#define CONFIG_FILE "mongoose.conf"
 #endif /* !CONFIG_FILE */
 
 static void WINCDECL signal_handler(int sig_num) {
@@ -98,7 +99,7 @@ static void die(const char *fmt, ...) {
  */
 static int mg_edit_passwords(const char *fname, const char *domain,
                              const char *user, const char *pass) {
-  struct mg_context	*ctx;
+  struct mg_context *ctx;
   const char *options[] = {"authentication_domain", NULL, NULL};
   int success;
 
@@ -178,27 +179,26 @@ static void set_option(char **options, const char *name, const char *value) {
 }
 
 static void process_command_line_arguments(char *argv[], char **options) {
-  const char	*config_file = NULL;
   char line[512], opt[512], val[512], path[PATH_MAX], *p;
   FILE *fp = NULL;
-  struct stat st;
   size_t i, line_no = 0;
 
   /* Should we use a config file ? */
   if (argv[1] != NULL && argv[2] == NULL) {
     config_file = argv[1];
-  } else if (argv[1] == NULL && (p = strrchr(argv[0], DIRSEP)) == NULL) {
+  } else if ((p = strrchr(argv[0], DIRSEP)) == NULL) {
     // No command line flags specified. Look where binary lives
     config_file = CONFIG_FILE;
-  } else if (argv[1] == NULL) {
+  } else {
     snprintf(path, sizeof(path), "%.*s%c%s",
              (int) (p - argv[0]), argv[0], DIRSEP, CONFIG_FILE);
-    if (stat(path, &st) == 0) {
-      config_file = path;
-    }
+    config_file = path;
   }
+
+  fp = fopen(config_file, "r");
+
   /* If config file was set in command line and open failed, exit */
-  if (config_file != NULL && (fp = fopen(config_file, "r")) == NULL) {
+  if (argv[1] != NULL && argv[2] == NULL && fp == NULL) {
     die("Cannot open config file %s: %s", config_file, strerror(errno));
   }
 
@@ -231,12 +231,14 @@ static void process_command_line_arguments(char *argv[], char **options) {
   }
 }
 
+static void init_server_name(void) {
+  snprintf(server_name, sizeof(server_name), "Mongoose web server v.%s",
+           mg_version());
+}
+
 static void start_mongoose(int argc, char *argv[]) {
   int i;
 
-  snprintf(server_name, sizeof(server_name),
-           "Mongoose %s web server", mg_version());
-
   /* Edit passwords file if -A option is specified */
   if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'A') {
     if (argc != 6) {
@@ -294,7 +296,6 @@ static void WINAPI ServiceMain(void) {
   hStatus = RegisterServiceCtrlHandler(server_name, ControlHandler);
   SetServiceStatus(hStatus, &ss);
 
-  //Sleep(3000);
   while (ss.dwCurrentState == SERVICE_RUNNING) {
     Sleep(1000);
   }
@@ -305,43 +306,89 @@ static void WINAPI ServiceMain(void) {
   SetServiceStatus(hStatus, &ss);
 }
 
-static void try_to_run_as_nt_service(void) {
-  static SERVICE_TABLE_ENTRY service_table[] = {
-    {server_name, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
-    {NULL, NULL}
-  };
-
-  if (StartServiceCtrlDispatcher(service_table)) {
-    exit(EXIT_SUCCESS);
+#define ID_TRAYICON 100
+#define ID_QUIT 101
+#define ID_EDIT_CONFIG 102
+#define ID_SEPARATOR 103
+#define ID_INSTALL_SERVICE 104
+#define ID_REMOVE_SERVICE 105
+#define ID_ICON 200
+static NOTIFYICONDATA TrayIcon;
+
+static void edit_config_file(void) {
+  const char **names, *value;
+  FILE *fp;
+  int i;
+  char cmd[200];
+
+  // Create config file if it is not present yet
+  if ((fp = fopen(config_file, "r")) != NULL) {
+    fclose(fp);
+  } else if ((fp = fopen(config_file, "a+")) != NULL) {
+    fprintf(fp,
+            "# Mongoose web server configuration file.\n"
+            "# Lines starting with '#' and empty lines are ignored.\n"
+            "# For detailed description of every option, visit\n"
+            "# http://code.google.com/p/mongoose/wiki/MongooseManual\n\n");
+    names = mg_get_valid_option_names();
+    for (i = 0; names[i] != NULL; i += 3) {
+      value = mg_get_option(ctx, names[i]);
+      fprintf(fp, "# %s %s\n", names[i + 1], *value ? value : "<value>");
+    }
+    fclose(fp);
   }
-}
 
-#define	ID_TRAYICON	100
-#define	ID_QUIT		101
-static NOTIFYICONDATA	ni;
+  snprintf(cmd, sizeof(cmd), "notepad.exe %s", config_file);
+  WinExec(cmd, SW_SHOW);
+}
 
 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam,
                                    LPARAM lParam) {
-  POINT	pt;
-  HMENU	hMenu; 	 
+  static SERVICE_TABLE_ENTRY service_table[] = {
+    {server_name, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
+    {NULL, NULL}
+  };
+  POINT pt;
+  HMENU hMenu;
 
   switch (msg) {
-
+    case WM_CREATE:
+      // Win32 runtime must prepare __argc and __argv for us
+      start_mongoose(__argc, __argv);
+      // TODO(lsm): figure out why this executes long time
+      if (StartServiceCtrlDispatcher(service_table)) {
+        exit(EXIT_SUCCESS);
+      }
+      break;
     case WM_COMMAND:
       switch (LOWORD(wParam)) {
         case ID_QUIT:
-          exit(EXIT_SUCCESS);
+          mg_stop(ctx);
+          Shell_NotifyIcon(NIM_DELETE, &TrayIcon);
+          PostQuitMessage(0);
+          break;
+        case ID_EDIT_CONFIG:
+          edit_config_file();
           break;
       }
       break;
-
     case WM_USER:
       switch (lParam) {
         case WM_RBUTTONUP:
         case WM_LBUTTONUP:
         case WM_LBUTTONDBLCLK:
           hMenu = CreatePopupMenu();
-          AppendMenu(hMenu, 0, ID_QUIT, "Exit");
+          AppendMenu(hMenu, MF_STRING | MF_GRAYED, ID_SEPARATOR, server_name);
+          AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
+#if 0
+          AppendMenu(hMenu, MF_STRING | MF_GRAYED, ID_SEPARATOR,
+                     "NT service: not installed");
+          AppendMenu(hMenu, MF_STRING, ID_INSTALL_SERVICE, "Install");
+          AppendMenu(hMenu, MF_STRING, ID_REMOVE_SERVICE, "Deinstall");
+          AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
+#endif
+          AppendMenu(hMenu, MF_STRING, ID_EDIT_CONFIG, "Edit config file");
+          AppendMenu(hMenu, MF_STRING, ID_QUIT, "Exit");
           GetCursorPos(&pt);
           TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hWnd, NULL);
           DestroyMenu(hMenu);
@@ -358,12 +405,9 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show) {
   HWND hWnd;
   MSG msg;
 
-  // Win32 runtime must prepare __argc and __argv for us
-  start_mongoose(__argc, __argv);
-  try_to_run_as_nt_service();
-
+  init_server_name();
   memset(&cls, 0, sizeof(cls));
-  cls.lpfnWndProc = (WNDPROC) WindowProc; 
+  cls.lpfnWndProc = (WNDPROC) WindowProc;
   cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
   cls.lpszClassName = server_name;
 
@@ -372,23 +416,24 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show) {
                       0, 0, 0, 0, NULL, NULL, NULL, NULL);
   ShowWindow(hWnd, SW_HIDE);
 
-  ni.cbSize = sizeof(ni);
-  ni.uID = ID_TRAYICON;
-  ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
-  ni.hIcon = LoadIcon(NULL, IDI_APPLICATION);
-  ni.hWnd = hWnd;
-  snprintf(ni.szTip, sizeof(ni.szTip), "%s", server_name);
-  ni.uCallbackMessage = WM_USER;
-  Shell_NotifyIcon(NIM_ADD, &ni);
-
-  while (GetMessage(&msg, hWnd, 0, 0)) { 
-    TranslateMessage(&msg); 
-    DispatchMessage(&msg); 
+  TrayIcon.cbSize = sizeof(TrayIcon);
+  TrayIcon.uID = ID_TRAYICON;
+  TrayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+  TrayIcon.hIcon = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_ICON),
+                             IMAGE_ICON, 16, 16, 0);
+  TrayIcon.hWnd = hWnd;
+  snprintf(TrayIcon.szTip, sizeof(TrayIcon.szTip), "%s", server_name);
+  TrayIcon.uCallbackMessage = WM_USER;
+  Shell_NotifyIcon(NIM_ADD, &TrayIcon);
+
+  while (GetMessage(&msg, hWnd, 0, 0)) {
+    TranslateMessage(&msg);
+    DispatchMessage(&msg);
   }
 }
-#endif /* _WIN32 */
-
-int WINCDECL main(int argc, char *argv[]) {
+#else
+int main(int argc, char *argv[]) {
+  init_server_name();
   start_mongoose(argc, argv);
   printf("%s started on port(s) %s with web root [%s]\n",
          server_name, mg_get_option(ctx, "listening_ports"),
@@ -404,3 +449,4 @@ int WINCDECL main(int argc, char *argv[]) {
 
   return EXIT_SUCCESS;
 }
+#endif /* _WIN32 */

+ 1 - 0
win32/res.rc

@@ -0,0 +1 @@
+200 ICON DISCARDABLE "systray.ico"

BIN
win32/systray.ico