Pass parameters around in a data structure.
[nssm.git] / gui.cpp
diff --git a/gui.cpp b/gui.cpp
index c094657..7773a18 100644 (file)
--- a/gui.cpp
+++ b/gui.cpp
@@ -1,13 +1,19 @@
 #include "nssm.h"\r
 \r
-int nssm_gui(int resource, char *name) {\r
-  char blurb[256];\r
+static void strip_basename(char *buffer) {\r
+  size_t len = strlen(buffer);\r
+  size_t i;\r
+  for (i = len; i && buffer[i] != '\\' && buffer[i] != '/'; i--);\r
+  /* X:\ is OK. */\r
+  if (i && buffer[i-1] == ':') i++;\r
+  buffer[i] = '\0';\r
+}\r
 \r
+int nssm_gui(int resource, char *name) {\r
   /* Create window */\r
   HWND dlg = CreateDialog(0, MAKEINTRESOURCE(resource), 0, install_dlg);\r
   if (! dlg) {\r
-    snprintf(blurb, sizeof(blurb), "CreateDialog() failed with error code %d", GetLastError());\r
-    MessageBox(0, blurb, NSSM, MB_OK);\r
+    popup_message(MB_OK, NSSM_GUI_CREATEDIALOG_FAILED, error_string(GetLastError()));\r
     return 1;\r
   }\r
 \r
@@ -31,11 +37,12 @@ int nssm_gui(int resource, char *name) {
   /* Go! */\r
   MSG message;\r
   while (GetMessage(&message, 0, 0, 0)) {\r
+    if (IsDialogMessage(dlg, &message)) continue;\r
     TranslateMessage(&message);\r
     DispatchMessage(&message);\r
   }\r
 \r
-  return message.wParam;\r
+  return (int) message.wParam;\r
 }\r
 \r
 void centre_window(HWND window) {\r
@@ -58,92 +65,75 @@ void centre_window(HWND window) {
   /* Centre window */\r
   x = (desktop_size.right - size.right) / 2;\r
   y = (desktop_size.bottom - size.bottom) / 2;\r
-  MoveWindow(window, x, y, size.right, size.bottom, 0);\r
+  MoveWindow(window, x, y, size.right - size.left, size.bottom - size.top, 0);\r
 }\r
 \r
 /* Install the service */\r
 int install(HWND window) {\r
   if (! window) return 1;\r
 \r
-  /* Check parameters in the window */\r
-  char name[STRING_SIZE];\r
-  char exe[MAX_PATH];\r
-  char flags[STRING_SIZE];\r
-  char dir[MAX_PATH];\r
+  nssm_service_t *service = alloc_nssm_service();\r
+  if (service) {\r
+    /* Get service name. */\r
+    if (! GetDlgItemText(window, IDC_NAME, service->name, sizeof(service->name))) {\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);\r
+      cleanup_nssm_service(service);\r
+      return 2;\r
+    }\r
 \r
-  /* Get service name */\r
-  if (! GetDlgItemText(window, IDC_NAME, name, sizeof(name))) {\r
-    MessageBox(0, "No valid service name was specified!", NSSM, MB_OK);\r
-    return 2;\r
-  }\r
+    /* Get executable name */\r
+    if (! GetDlgItemText(window, IDC_PATH, service->exe, sizeof(service->exe))) {\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PATH);\r
+      return 3;\r
+    }\r
+  \r
+    /* Get flags */\r
+    if (SendMessage(GetDlgItem(window, IDC_FLAGS), WM_GETTEXTLENGTH, 0, 0)) {\r
+      if (! GetDlgItemText(window, IDC_FLAGS, service->flags, sizeof(service->flags))) {\r
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS);\r
+        return 4;\r
+      }
+    }\r
 \r
-  /* Get executable name */\r
-  if (! GetDlgItemText(window, IDC_PATH, exe, sizeof(exe))) {\r
-    MessageBox(0, "No valid executable path was specified!", NSSM, MB_OK);\r
-    return 3;\r
+    memmove(service->dir, service->exe, strlen(service->exe));\r
+    strip_basename(service->dir);\r
   }\r
 \r
-  /* Get flags */\r
-  if (SendMessage(GetDlgItem(window, IDC_FLAGS), WM_GETTEXTLENGTH, 0, 0)) {\r
-    if (! GetDlgItemText(window, IDC_FLAGS, flags, sizeof(flags))) {\r
-      MessageBox(0, "No valid options were specified!", NSSM, MB_OK);\r
+  /* See if it works. */\r
+  switch (install_service(service)) {\r
+    case 1:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "service", "install()");\r
+      cleanup_nssm_service(service);\r
+      return 1;\r
+\r
+    case 2:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);\r
+      cleanup_nssm_service(service);\r
+      return 2;\r
+\r
+    case 3:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);\r
+      cleanup_nssm_service(service);\r
+      return 3;\r
+\r
+    case 4:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);\r
+      cleanup_nssm_service(service);\r
       return 4;\r
-    }\r
-  }\r
-  else ZeroMemory(&flags, sizeof(flags));\r
-\r
-  /* Work out directory name */\r
-  unsigned int len = strlen(exe);\r
-  unsigned int i;\r
-  for (i = len; i && exe[i] != '\\' && exe[i] != '/'; i--);\r
-  memmove(dir, exe, i);\r
-  dir[i] = '\0';\r
-\r
-  /* Open service manager */\r
-  SC_HANDLE services = open_service_manager();\r
-  if (! services) {\r
-    MessageBox(0, "Can't open service manager!\nPerhaps you need to be an administrator...", NSSM, MB_OK);\r
-    return 2;\r
-  }\r
-  \r
-  /* Get path of this program */\r
-  char path[MAX_PATH];\r
-  GetModuleFileName(0, path, MAX_PATH);\r
-\r
-  /* Construct command */\r
-  char command[MAX_PATH];\r
-  int runlen = strlen(NSSM_RUN);\r
-  int pathlen = strlen(path);\r
-  if (pathlen + runlen + 2 >= MAX_PATH) {\r
-    MessageBox(0, "Path too long!\nThe full path to " NSSM " is too long.\nPlease install " NSSM " somewhere else...\n", NSSM, MB_OK);\r
-    return 3;\r
-  }\r
-  if (snprintf(command, sizeof(command), "%s %s", path, NSSM_RUN) < 0) {\r
-     MessageBox(0, "Error constructing ImagePath!\nThis really shouldn't happen.  You could be out of memory\nor the world may be about to end or something equally bad.", NSSM, MB_OK);\r
-     return 4;\r
-  }\r
 \r
-  /* Create the service */\r
-  SC_HANDLE service = CreateService(services, name, name, SC_MANAGER_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, command, 0, 0, 0, 0, 0);\r
-  if (! service) {\r
-    MessageBox(0, "Couldn't create service!\nPerhaps it is already installed...", NSSM, MB_OK);\r
-    CloseServiceHandle(services);\r
-    return 5;\r
-  }\r
+    case 5:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED);\r
+      cleanup_nssm_service(service);\r
+      return 5;\r
 \r
-  /* Now we need to put the parameters into the registry */\r
-  if (create_parameters(name, exe, flags, dir)) {\r
-    MessageBox(0, "Couldn't set startup parameters for the service!\nDeleting the service...", NSSM, MB_OK);\r
-    DeleteService(service);\r
-    CloseServiceHandle(services);\r
-    return 6;\r
+    case 6:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED);\r
+      cleanup_nssm_service(service);\r
+      return 6;\r
   }\r
 \r
-  /* Cleanup */\r
-  CloseServiceHandle(service);\r
-  CloseServiceHandle(services);\r
-\r
-  MessageBox(0, "Service successfully installed!", NSSM, MB_OK);\r
+  popup_message(MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, service->name);\r
+  cleanup_nssm_service(service);\r
   return 0;\r
 }\r
 \r
@@ -151,76 +141,94 @@ int install(HWND window) {
 int remove(HWND window) {\r
   if (! window) return 1;\r
 \r
-  /* Check parameters in the window */\r
-  char name[STRING_SIZE];\r
+  /* See if it works */\r
+  nssm_service_t *service = alloc_nssm_service();\r
+  if (service) {\r
+    /* Get service name */\r
+    if (! GetDlgItemText(window, IDC_NAME, service->name, sizeof(service->name))) {\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);\r
+      cleanup_nssm_service(service);\r
+      return 2;\r
+    }\r
 \r
-  /* Get service name */\r
-  if (! GetDlgItemText(window, IDC_NAME, name, sizeof(name))) {\r
-    MessageBox(0, "No valid service name was specified!", NSSM, MB_OK);\r
-    return 2;\r
+    /* Confirm */\r
+    if (popup_message(MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, service->name) != IDYES) {\r
+      cleanup_nssm_service(service);\r
+      return 0;\r
+    }\r
   }\r
 \r
-  /* Confirm */\r
-  char blurb[MAX_PATH];\r
-  if (snprintf(blurb, sizeof(blurb), "Remove the \"%s\" service?", name) < 0) {\r
-    if (MessageBox(0, "Remove the service?", NSSM, MB_YESNO) != IDYES) return 0;\r
-  }\r
-  else if (MessageBox(0, blurb, NSSM, MB_YESNO) != IDYES) return 0;\r
+  switch (remove_service(service)) {\r
+    case 1:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "service", "remove()");\r
+      cleanup_nssm_service(service);\r
+      return 1;\r
 \r
-  /* Open service manager */\r
-  SC_HANDLE services = open_service_manager();\r
-  if (! services) {\r
-    MessageBox(0, "Can't open service manager!\nPerhaps you need to be an administrator...", NSSM, MB_OK);\r
-    return 2;\r
-  }\r
-  \r
-  /* Try to open the service */\r
-  SC_HANDLE service = OpenService(services, name, SC_MANAGER_ALL_ACCESS);\r
-  if (! service) {\r
-    MessageBox(0, "Can't open service!\nPerhaps it isn't installed...", NSSM, MB_OK);\r
-    CloseServiceHandle(services);\r
-    return 3;\r
-  }\r
+    case 2:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);\r
+      cleanup_nssm_service(service);\r
+      return 2;\r
 \r
-  /* Try to delete the service */\r
-  if (! DeleteService(service)) {\r
-    MessageBox(0, "Can't delete service!  Make sure the service is stopped and try again.\nIf this error persists, you may need to set the service NOT to start\nautomatically, reboot your computer and try removing it again.", NSSM, MB_OK);\r
-    CloseServiceHandle(service);\r
-    CloseServiceHandle(services);\r
-    return 4;\r
-  }\r
+    case 3:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED);\r
+      return 3;\r
+      cleanup_nssm_service(service);\r
 \r
-  /* Cleanup */\r
-  CloseServiceHandle(service);\r
-  CloseServiceHandle(services);\r
+    case 4:\r
+      popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED);\r
+      cleanup_nssm_service(service);\r
+      return 4;\r
+  }\r
 \r
-  MessageBox(0, "Service successfully removed!", NSSM, MB_OK);\r
+  popup_message(MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, service->name);\r
+  cleanup_nssm_service(service);\r
   return 0;\r
 }\r
 \r
-/* Browse for game */\r
+/* Browse for application */\r
 void browse(HWND window) {\r
   if (! window) return;\r
 \r
+  size_t bufsize = 256;\r
+  size_t len = bufsize;\r
   OPENFILENAME ofn;\r
   ZeroMemory(&ofn, sizeof(ofn));\r
   ofn.lStructSize = sizeof(ofn);\r
-  ofn.lpstrFilter = "Applications\0*.exe\0All files\0*.*\0\0";\r
+  ofn.lpstrFilter = (char *) HeapAlloc(GetProcessHeap(), 0, bufsize);\r
+  /* XXX: Escaping nulls with FormatMessage is tricky */\r
+  if (ofn.lpstrFilter) {\r
+    ZeroMemory((void *) ofn.lpstrFilter, bufsize);\r
+    char *localised = message_string(NSSM_GUI_BROWSE_FILTER_APPLICATIONS);\r
+    _snprintf_s((char *) ofn.lpstrFilter, bufsize, _TRUNCATE, localised);\r
+    /* "Applications" + NULL + "*.exe" + NULL */\r
+    len = strlen(localised) + 1;\r
+    LocalFree(localised);\r
+    _snprintf_s((char *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, "*.exe");\r
+    /* "All files" + NULL + "*.*" + NULL */\r
+    len += 6;\r
+    localised = message_string(NSSM_GUI_BROWSE_FILTER_ALL_FILES);\r
+    _snprintf_s((char *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, localised);\r
+    len += strlen(localised) + 1;\r
+    LocalFree(localised);\r
+    _snprintf_s((char *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, "*.*");\r
+    /* Remainder of the buffer is already zeroed */\r
+  }\r
   ofn.lpstrFile = new char[MAX_PATH];\r
   ofn.lpstrFile[0] = '\0';\r
-  ofn.lpstrTitle = "Locate application file";\r
+  ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);\r
   ofn.nMaxFile = MAX_PATH;\r
   ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;\r
 \r
   if (GetOpenFileName(&ofn)) {\r
     SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile);\r
   }\r
+  if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter);\r
 \r
   delete[] ofn.lpstrFile;\r
 }\r
 \r
 /* Install/remove dialogue callback */\r
-int CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {\r
+INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {\r
   switch (message) {\r
     /* Creating the dialogue */\r
     case WM_INITDIALOG:\r
@@ -231,11 +239,11 @@ int CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
       switch (LOWORD(w)) {\r
         /* OK button */\r
         case IDC_OK:\r
-          PostQuitMessage(install(window));\r
+          if (! install(window)) PostQuitMessage(0);\r
           break;\r
 \r
         /* Cancel button */\r
-        case IDC_CANCEL:\r
+        case IDCANCEL:\r
           DestroyWindow(window);\r
           break;\r
 \r
@@ -246,7 +254,7 @@ int CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
 \r
         /* Remove button */\r
         case IDC_REMOVE:\r
-          PostQuitMessage(remove(window));\r
+          if (! remove(window)) PostQuitMessage(0);\r
           break;\r
       }\r
       return 1;\r