mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

jvergara
16.10.2007 ba928b801598f6651897e07f8e4ed8a4eeea68bd
Fix for issue 1382 (Provide a way to cleanup the registry/service information for Windows).

Provide a new option in the windowsservice.bat command line to do a cleanup of
a service.

The option usage is:
-c {serviceName} or --cleanupService {serviceName}
Allows to disable the OpendS service and to clean up the windows registry
information associated with the provided service name.o
5 files modified
378 ■■■■■ changed files
opendj-sdk/opends/build-tools/src/windows/service.c 216 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/build-tools/src/windows/service.h 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/lib/opends_service.exe patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java 60 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/tools/ConfigureWindowsService.java 100 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/build-tools/src/windows/service.c
@@ -1373,8 +1373,8 @@
// ---------------------------------------------------------------
// Build a service name for OpenDS and make sure
// the service name is unique on the system. To achieve this requirement
// the service name looks like OpenDS for the first OpenDS and
// OpenDS-n if there are more than one.
// the service name looks like <baseName> for the first OpenDS and
// <baseName>-n if there are more than one.
//
// The functions returns SERVICE_RETURN_OK if we could create a service
// name and SERVICE_RETURN_ERROR otherwise.
@@ -1382,7 +1382,7 @@
// minimum size must be of 256 (the maximum string length of a Service Name).
// ---------------------------------------------------------------
ServiceReturnCode createServiceName(char* serviceName)
ServiceReturnCode createServiceName(char* serviceName, char* baseName)
{
  ServiceReturnCode returnValue = SERVICE_RETURN_OK;
  int i = 1;
@@ -1392,11 +1392,11 @@
  {
    if (i == 1)
    {
      sprintf(serviceName, "OpenDS");
      sprintf(serviceName, baseName);
    }
    else
    {
      sprintf(serviceName, "OpenDS-%d", i);
      sprintf(serviceName, "%s-%d", baseName, i);
    }
    nameInUseResult = serviceNameInUse(serviceName);
@@ -1445,8 +1445,8 @@
  // - serviceName is the service name
  char* serviceName = (char*) calloc(1, MAX_SERVICE_NAME);
  // elaborate the service name
  returnValue = createServiceName(serviceName);
  // elaborate the service name based on the displayName provided
  returnValue = createServiceName(serviceName, displayName);
  // create the service
  if (returnValue == SERVICE_RETURN_OK)
@@ -1468,7 +1468,7 @@
    myService = CreateService(
    scm,
    serviceName,                // name of service
    displayName,                // service name to display
    serviceName,                // service name to display
    SERVICE_ALL_ACCESS,         // desired access
    SERVICE_WIN32_OWN_PROCESS,  // service type
    SERVICE_AUTO_START,         // start service during
@@ -1753,7 +1753,45 @@
  return returnCode;
} // serviceState
// ---------------------------------------------------------------
// Function called to remove the service associated with a given
// service name.
// Returns 0 if the service was successfully removed.
// Returns 1 if the service does not exist.
// Returns 2 if the service was marked for deletion but is still in
// use.
// Returns 3 if an error occurred.
// ---------------------------------------------------------------
int removeServiceWithServiceName(char *serviceName)
{
  int returnCode = 0;
  ServiceReturnCode code = serviceNameInUse(serviceName);
  if (code != SERVICE_IN_USE)
  {
    returnCode = 1;
  }
  else
  {
    code = removeServiceFromScm(serviceName);
    switch (code)
    {
      case SERVICE_RETURN_OK:
      removeRegistryKey(serviceName);
      returnCode = 0;
      break;
      case SERVICE_MARKED_FOR_DELETION:
      removeRegistryKey(serviceName);
      returnCode = 2;
      break;
      default:
      returnCode = 3;
    }
  }
  return returnCode;
} // removeServiceWithServiceName
// ---------------------------------------------------------------
// Function called to remove the service for the OpenDS instance
@@ -1778,21 +1816,7 @@
    code = getServiceName(cmdToRun, serviceName);
    if (code == SERVICE_RETURN_OK)
    {
      code = removeServiceFromScm(serviceName);
      switch (code)
      {
        case SERVICE_RETURN_OK:
        removeRegistryKey(serviceName);
        returnCode = 0;
        break;
        case SERVICE_MARKED_FOR_DELETION:
        removeRegistryKey(serviceName);
        returnCode = 2;
        break;
        default:
        returnCode = 3;
      }
      returnCode = removeServiceWithServiceName(serviceName);
    }
    else
    {
@@ -1808,6 +1832,7 @@
} // removeService
// ---------------------------------------------------------------
// Function called to start the service where this executable is installed.
// Returns 0 if the service runs.
@@ -1916,105 +1941,6 @@
  }
}
void formatMessage(DWORD msgId, int count, ...)
{
  char buf[2048];
  int result;
  va_list args;
  char execName [MAX_PATH];
  GetModuleFileName (
  NULL,
  execName,
  MAX_PATH
  );
  if (count > 0)
  {
    va_start(args, count);
    // Retrieve the English message string.
    result = FormatMessage(
    FORMAT_MESSAGE_FROM_HMODULE,
    (LPBYTE)execName,
    WIN_EVENT_ID_SERVER_STARTED, //msgId,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (LPTSTR) &buf,
    2048,
    &args);
  }
  else
  {
    result = FormatMessage(
    FORMAT_MESSAGE_FROM_HMODULE,
    (LPBYTE)execName,
    msgId,
    LANG_NEUTRAL,
    (LPTSTR) &buf,
    2048,
    NULL);
  }
  if (execName != NULL)
  {
    fprintf(stderr, "The module is [%s]\n", execName);
  }
  else
  {
    fprintf(stderr, "The module is NULL\n");
  }
  if (result > 0)
  {
    fprintf(stderr, "formatMessage worked: [%s]\n", buf);
  }
  else
  {
    fprintf(stderr, "formatMessage failed, error is: %d\n",
    GetLastError());
  }
}
void logMsgTest(char *serviceName)
{
  DWORD ids[] = {WIN_EVENT_ID_SERVER_STARTED, WIN_EVENT_ID_SERVER_STOP,
    WIN_EVENT_ID_SERVER_START_FAILED, WIN_EVENT_ID_SERVER_STOP_FAILED,
  WIN_EVENT_ID_DEBUG};
  const char* args[] = {"c:\\temp\\OpenDS tarara"};
  int evCount = 5;
  int i;
  _eventLog = registerEventLog(serviceName);
  for (i = 0; i<evCount; i++)
  {
    if (i != 5)
    {
      formatMessage(ids[i], 1, args[0]);
      if(reportLogEvent(EVENTLOG_SUCCESS, ids[i], 1, args))
      {
        fprintf(stderr, "reportLogEvent successful.\n");
      }
      else
      {
        fprintf(stderr, "reportLogEvent failed: %d.\n", GetLastError());
      }
    }
    else
    {
      formatMessage(ids[i], 0);
      if (reportLogEvent(EVENTLOG_SUCCESS, ids[i], 1, args))
      {
        fprintf(stderr, "reportLogEvent successful.\n");
      }
      else
      {
        fprintf(stderr, "reportLogEvent failed: %d.\n", GetLastError());
      }
    }
  }
  deregisterEventLog();
}
int main(int argc, char* argv[])
{
  char* subcommand;
@@ -2022,7 +1948,8 @@
  if (argc <= 1)
  {
    fprintf(stderr, "Subcommand required: create, state, remove or start\n");
    fprintf(stderr,
    "Subcommand required: create, state, remove, start or cleanup.\n");
    returnCode = -1;
  }
  else
@@ -2033,7 +1960,7 @@
      if (argc <= 4)
      {
        fprintf(stderr,
        "Subcommand create requires instance dir, service name and description.\n");
    "Subcommand create requires instance dir, service name and description.\n");
        returnCode = -1;
      }
      else
@@ -2049,7 +1976,7 @@
      if (argc <= 2)
      {
        fprintf(stderr,
        "Subcommand state requires instance dir\n");
        "Subcommand state requires instance dir.\n");
        returnCode = -1;
      }
      else
@@ -2065,7 +1992,7 @@
      if (argc <= 2)
      {
        fprintf(stderr,
        "Subcommand remove requires instance dir\n");
        "Subcommand remove requires instance dir.\n");
        returnCode = -1;
      }
      else
@@ -2081,7 +2008,7 @@
      if (argc <= 2)
      {
        fprintf(stderr,
        "Subcommand start requires instancedir.\n");
        "Subcommand start requires instance dir.\n");
        returnCode = -1;
      }
      else
@@ -2097,7 +2024,7 @@
      if (argc <= 2)
      {
        fprintf(stderr,
        "Subcommand isrunning requires instancedir.\n");
        "Subcommand isrunning requires instance dir.\n");
        returnCode = -1;
      }
      else
@@ -2119,42 +2046,23 @@
      }
    }
    else if (strcmp(subcommand, "logevents") == 0)
    else if (strcmp(subcommand, "cleanup") == 0)
    {
      if (argc <= 2)
      {
        fprintf(stderr,
        "Subcommand logevents requires instancedir.\n");
        "Subcommand cleanup requires service name.\n");
        returnCode = -1;
      }
      else
      {
        ServiceReturnCode code;
        char cmdToRun[MAX_PATH];
        char serviceName[MAX_SERVICE_NAME];
        _instanceDir = strdup(argv[2]);
        code = createServiceBinPath(cmdToRun);
        if (code == SERVICE_RETURN_OK)
        {
          code = getServiceName(cmdToRun, serviceName);
        }
        if (code == SERVICE_RETURN_OK)
        {
          logMsgTest(serviceName);
          returnCode = 0;
        }
        else
        {
          returnCode = -1;
        }
        free(_instanceDir);
        char* serviceName = strdup(argv[2]);
        updateDebugFlag(argv, argc, 3);
        returnCode = removeServiceWithServiceName(serviceName);
        free(serviceName);
      }
    }
    else
    {
      fprintf(stderr, "Unknown subcommand: [%s]\n", subcommand);
opendj-sdk/opends/build-tools/src/windows/service.h
@@ -92,7 +92,7 @@
ServiceReturnCode registerServiceHandler (char* serviceName,
LPHANDLER_FUNCTION serviceHandler, SERVICE_STATUS_HANDLE* serviceStatusHandle);
ServiceReturnCode serviceNameInUse(char* serviceName);
ServiceReturnCode createServiceName(char* serviceName);
ServiceReturnCode createServiceName(char* serviceName, char* baseName);
ServiceReturnCode getServiceList(ServiceDescriptor** serviceList,
int *nbServices);
ServiceReturnCode createServiceBinPath(char* serviceBinPath);
opendj-sdk/opends/lib/opends_service.exe
Binary files differ
opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -7940,6 +7940,43 @@
  /**
   * The message ID for the message for the description of cleanup Windows
   * service.  This does not take any argument.
   */
  public static final int MSGID_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_CLEANUP =
    CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 844;
  /**
   * The message ID to inform that the cleanup of the Windows service was
   * successful.  This takes the service name as argument.
   */
  public static final int MSGID_WINDOWS_SERVICE_CLEANUP_SUCCESS =
    CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 845;
  /**
   * The message ID to inform that the service during the cleanup could not be
   * found.  This takes the service name as argument.
   */
  public static final int MSGID_WINDOWS_SERVICE_CLEANUP_NOT_FOUND =
    CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 846;
  /**
   * The message ID to inform that the service has been marked for deletion.
   * This takes the service name as argument.
   */
  public static final int MSGID_WINDOWS_SERVICE_CLEANUP_MARKED_FOR_DELETION =
    CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_WARNING | 847;
  /**
   * The message ID to inform that an error occurred during the service clean
   * up.  This takes the service name as argument.
   */
  public static final int MSGID_WINDOWS_SERVICE_CLEANUP_ERROR =
    CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 848;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
   */
@@ -10354,6 +10391,11 @@
                    "Provides information about the state of OpenDS as a "+
                    "Windows service.");
    registerMessage(MSGID_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_CLEANUP,
                    "Allows to disable the OpenDS service and to clean up the "+
                    "windows registry information associated with the "+
                    "provided service name.");
    registerMessage(MSGID_CONFIGURE_WINDOWS_SERVICE_CANNOT_INITIALIZE_ARGS,
                    "An unexpected error occurred while attempting to " +
                    "initialize the command-line arguments:  %s.");
@@ -10364,11 +10406,13 @@
    registerMessage(MSGID_CONFIGURE_WINDOWS_SERVICE_TOO_MANY_ARGS,
                    "You can only provide one of the following arguments:"+
                    EOL+"enableService, disableService or serviceState.");
                    EOL+"enableService, disableService, serviceState or "+
                    "cleanupService.");
    registerMessage(MSGID_CONFIGURE_WINDOWS_SERVICE_TOO_FEW_ARGS,
                    "You must provide at least one of the following arguments:"+
                    EOL+"enableService, disableService or serviceState.");
                    EOL+"enableService, disableService or serviceState or "+
                    "cleanupService.");
    registerMessage(MSGID_WINDOWS_SERVICE_NAME,
                    "OpenDS");
@@ -10415,6 +10459,18 @@
    registerMessage(MSGID_WINDOWS_SERVICE_STATE_ERROR,
                    "An unexpected error occurred trying to retrieve the "+
                    "state of OpenDS as a Windows service.");
    registerMessage(MSGID_WINDOWS_SERVICE_CLEANUP_SUCCESS,
                    "Clean up of service %s was successful.");
    registerMessage(MSGID_WINDOWS_SERVICE_CLEANUP_NOT_FOUND,
                    "Could not find the service with name %s.");
    registerMessage(MSGID_WINDOWS_SERVICE_CLEANUP_ERROR,
                    "An unexpected error occurred cleaning up the service %s.");
    registerMessage(MSGID_WINDOWS_SERVICE_CLEANUP_MARKED_FOR_DELETION,
                    "Service %s has been marked for deletion.");
  }
}
opendj-sdk/opends/src/server/org/opends/server/tools/ConfigureWindowsService.java
@@ -39,6 +39,7 @@
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.ArgumentParser;
import org.opends.server.util.args.BooleanArgument;
import org.opends.server.util.args.StringArgument;
import static org.opends.server.messages.MessageHandler.getMessage;
import static org.opends.server.messages.ToolMessages.*;
@@ -118,6 +119,27 @@
  public static final int SERVICE_STATE_ERROR = 2;
  /**
   * Return codes for the method cleanupService.
   */
  /**
   * The service cleanup worked.
   */
  public static final int SERVICE_CLEANUP_SUCCESS = 0;
  /**
   * The service could not be found.
   */
  public static final int SERVICE_NOT_FOUND = 1;
  /**
   * An error occurred cleaning up the service.
   */
  public static final int SERVICE_CLEANUP_ERROR = 2;
  /**
   * The service is marked for deletion.
   */
  public static final int SERVICE_CLEANUP_MARKED_FOR_DELETION = 3;
  /**
   * Configures the Windows service for this instance on this machine.
   * This tool allows to enable and disable OpenDS to run as a Windows service
   * and allows to know if OpenDS is running as a Windows service or not.
@@ -174,6 +196,7 @@
    BooleanArgument enableService = null;
    BooleanArgument disableService = null;
    BooleanArgument serviceState = null;
    StringArgument cleanupService = null;
    BooleanArgument showUsage = null;
    try
@@ -192,6 +215,11 @@
          MSGID_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_STATE);
      argParser.addArgument(serviceState);
      cleanupService = new StringArgument("cleanupservice", 'c',
          "cleanupService", false, false, true, "{serviceName}", null, null,
          MSGID_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_CLEANUP);
      argParser.addArgument(cleanupService);
      showUsage = new BooleanArgument("showusage", 'H', "help",
          MSGID_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_SHOWUSAGE);
      argParser.addArgument(showUsage);
@@ -241,6 +269,10 @@
      {
        nArgs++;
      }
      if (cleanupService.isPresent())
      {
        nArgs++;
      }
      if (nArgs > 1)
      {
        int msgID = MSGID_CONFIGURE_WINDOWS_SERVICE_TOO_MANY_ARGS;
@@ -269,10 +301,14 @@
      {
        returnValue = disableService(out, err);
      }
      else
      else if (serviceState.isPresent())
      {
        returnValue = serviceState(out, err);
      }
      else
      {
        returnValue = cleanupService(cleanupService.getValue(), out, err);
      }
    }
    return returnValue;
@@ -464,6 +500,68 @@
  }
  /**
   * Cleans up a service for a given service name.
   * @param serviceName the service name to be cleaned up.
   * @param out the stream used to write the standard output.
   * @param err the stream used to write the error output.
   * @return <CODE>SERVICE_CLEANUP_SUCCESS</CODE>,
   * <CODE>SERVICE_NOT_FOUND</CODE>,
   * <CODE>SERVICE_MARKED_FOR_DELETION</CODE> or
   * <CODE>SERVICE_CLEANUP_ERROR</CODE> depending on whether the service
   * could be found or not.
   */
  public static int cleanupService(String serviceName, PrintStream out,
      PrintStream err)
  {
    int returnValue;
    String msg;
    String[] cmd = {
        getBinaryFullPath(),
        "cleanup",
        serviceName
        };
    try
    {
      int resultCode = Runtime.getRuntime().exec(cmd).waitFor();
      switch (resultCode)
      {
      case 0:
        returnValue = SERVICE_CLEANUP_SUCCESS;
        msg = getMessage(MSGID_WINDOWS_SERVICE_CLEANUP_SUCCESS, serviceName);
        out.println(msg);
        break;
      case 1:
        returnValue = SERVICE_NOT_FOUND;
        msg = getMessage(MSGID_WINDOWS_SERVICE_CLEANUP_NOT_FOUND, serviceName);
        err.println(msg);
        break;
      case 2:
        returnValue = SERVICE_CLEANUP_MARKED_FOR_DELETION;
        msg = getMessage(MSGID_WINDOWS_SERVICE_CLEANUP_MARKED_FOR_DELETION,
            serviceName);
        out.println(msg);
        break;
      case 3:
        returnValue = SERVICE_CLEANUP_ERROR;
        msg = getMessage(MSGID_WINDOWS_SERVICE_CLEANUP_ERROR, serviceName);
        err.println(msg);
        break;
      default:
        returnValue = SERVICE_CLEANUP_ERROR;
        msg = getMessage(MSGID_WINDOWS_SERVICE_CLEANUP_ERROR, serviceName);
        err.println(msg);
      }
    }
    catch (Throwable t)
    {
      returnValue = SERVICE_CLEANUP_ERROR;
      msg = getMessage(MSGID_WINDOWS_SERVICE_CLEANUP_ERROR, serviceName);
      err.println(msg);
    }
    return returnValue;
  }
  /**
    * Checks if OpenDS is enabled as a windows service and if it is
    * write the serviceName in the output stream (if it is not null).
    * @param out the stream used to write the standard output.