From 08d62ab30082bc0feb209c8de443b8ec9a419dd6 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Wed, 18 Jul 2007 21:28:42 +0000
Subject: [PATCH] Fix for issue 1603 (quickInstall fails to register service on vista)
---
opendj-sdk/opends/resource/uninstall.bat | 2
opendj-sdk/opends/src/build-tools/windows/common.c | 12
opendj-sdk/opends/src/build-tools/windows/launcher_administrator.exe.manifest | 16 +
opendj-sdk/opends/resource/bin/start-ds.bat | 4
opendj-sdk/opends/resource/bin/status-panel.bat | 2
opendj-sdk/opends/src/build-tools/windows/Makefile | 20 +
opendj-sdk/opends/lib/launcher_administrator.exe | 0
opendj-sdk/opends/src/build-tools/windows/README | 12 +
opendj-sdk/opends/resource/setup.bat | 2
opendj-sdk/opends/src/server/org/opends/server/tools/StartWindowsService.java | 27 ++
opendj-sdk/opends/src/server/org/opends/server/tools/ConfigureWindowsService.java | 153 +++++++++++++-
opendj-sdk/opends/src/build-tools/windows/winlauncher.c | 130 +++++++++----
opendj-sdk/opends/resource/bin/_client-script.bat | 2
opendj-sdk/opends/src/build-tools/windows/opends_service.exe.manifest | 16 +
opendj-sdk/opends/src/server/org/opends/server/util/SetupUtils.java | 20 ++
opendj-sdk/opends/lib/opends_service.exe | 0
opendj-sdk/opends/src/build-tools/windows/service.c | 135 ++++++++-----
opendj-sdk/opends/lib/winlauncher.exe | 0
opendj-sdk/opends/src/server/org/opends/server/tools/StopWindowsService.java | 27 ++
19 files changed, 444 insertions(+), 136 deletions(-)
diff --git a/opendj-sdk/opends/lib/launcher_administrator.exe b/opendj-sdk/opends/lib/launcher_administrator.exe
new file mode 100644
index 0000000..7b1ba12
--- /dev/null
+++ b/opendj-sdk/opends/lib/launcher_administrator.exe
Binary files differ
diff --git a/opendj-sdk/opends/lib/opends_service.exe b/opendj-sdk/opends/lib/opends_service.exe
index 63cccd9..546161b 100755
--- a/opendj-sdk/opends/lib/opends_service.exe
+++ b/opendj-sdk/opends/lib/opends_service.exe
Binary files differ
diff --git a/opendj-sdk/opends/lib/winlauncher.exe b/opendj-sdk/opends/lib/winlauncher.exe
index 7e0fd52..5c836f0 100755
--- a/opendj-sdk/opends/lib/winlauncher.exe
+++ b/opendj-sdk/opends/lib/winlauncher.exe
Binary files differ
diff --git a/opendj-sdk/opends/resource/bin/_client-script.bat b/opendj-sdk/opends/resource/bin/_client-script.bat
index 88fe198..343eaeb 100644
--- a/opendj-sdk/opends/resource/bin/_client-script.bat
+++ b/opendj-sdk/opends/resource/bin/_client-script.bat
@@ -25,7 +25,7 @@
rem
rem Portions Copyright 2006-2007 Sun Microsystems, Inc.
-rem This script is used to invoke various server-side processes. It should not
+rem This script is used to invoke various client-side processes. It should not
rem be invoked directly by end users.
setlocal
diff --git a/opendj-sdk/opends/resource/bin/start-ds.bat b/opendj-sdk/opends/resource/bin/start-ds.bat
index cf2becc..c4e2efb 100644
--- a/opendj-sdk/opends/resource/bin/start-ds.bat
+++ b/opendj-sdk/opends/resource/bin/start-ds.bat
@@ -111,7 +111,7 @@
goto end
:runDetachCalledByWinService
-rem We write the output of the start command to the winwervice.out file.
+rem We write the output of the start command to the winservice.out file.
echo %SCRIPT%: Run detach called by windows service >> %LOG%
if not exist "%DIR_HOME%\logs\server.out" echo. > "%DIR_HOME%\logs\server.out"
if not exist "%DIR_HOME%\logs\server.starting" echo. > "%DIR_HOME%\logs\server.starting"
@@ -133,4 +133,4 @@
if exist "%DIR_HOME%\logs\winservice.out" erase "%DIR_HOME%\logs\winservice.out"
:end
-echo %SCRIPT%: finished >> %LOG%
\ No newline at end of file
+echo %SCRIPT%: finished >> %LOG%
diff --git a/opendj-sdk/opends/resource/bin/status-panel.bat b/opendj-sdk/opends/resource/bin/status-panel.bat
index a82ba38..952481d 100644
--- a/opendj-sdk/opends/resource/bin/status-panel.bat
+++ b/opendj-sdk/opends/resource/bin/status-panel.bat
@@ -57,7 +57,7 @@
set PATH=%SystemRoot%
-"%DIR_HOME%\lib\winlauncher.exe" launch "%DIR_HOME%" "%JAVA_BIN%" %JAVA_ARGS% org.opends.statuspanel.StatusPanelLauncher %*
+"%DIR_HOME%\lib\winlauncher.exe" launch "%JAVA_BIN%" %JAVA_ARGS% org.opends.statuspanel.StatusPanelLauncher %*
goto end
diff --git a/opendj-sdk/opends/resource/setup.bat b/opendj-sdk/opends/resource/setup.bat
index b5f48c9..1dec017 100644
--- a/opendj-sdk/opends/resource/setup.bat
+++ b/opendj-sdk/opends/resource/setup.bat
@@ -72,7 +72,7 @@
goto callJava
:callLaunch
-"%DIR_HOME%\lib\winlauncher.exe" launch "%DIR_HOME%" "%JAVA_BIN%" %JAVA_ARGS% org.opends.quicksetup.installer.InstallLauncher -P setup.bat
+"%DIR_HOME%\lib\winlauncher.exe" launch "%JAVA_BIN%" %JAVA_ARGS% org.opends.quicksetup.installer.InstallLauncher -P setup.bat
goto end
:callJava
diff --git a/opendj-sdk/opends/resource/uninstall.bat b/opendj-sdk/opends/resource/uninstall.bat
index 3429073..f7b2991 100644
--- a/opendj-sdk/opends/resource/uninstall.bat
+++ b/opendj-sdk/opends/resource/uninstall.bat
@@ -72,7 +72,7 @@
goto callJava
:callLaunch
-"%DIR_HOME%\lib\winlauncher.exe" launch "%DIR_HOME%" "%JAVA_BIN%" %JAVA_ARGS% org.opends.quicksetup.uninstaller.UninstallLauncher
+"%DIR_HOME%\lib\winlauncher.exe" launch "%JAVA_BIN%" %JAVA_ARGS% org.opends.quicksetup.uninstaller.UninstallLauncher
goto end
:callJava
diff --git a/opendj-sdk/opends/src/build-tools/windows/Makefile b/opendj-sdk/opends/src/build-tools/windows/Makefile
index 93fd9fa..caa92e1 100644
--- a/opendj-sdk/opends/src/build-tools/windows/Makefile
+++ b/opendj-sdk/opends/src/build-tools/windows/Makefile
@@ -44,13 +44,15 @@
CC=cl
SERVICE_PROGNAME=opends_service.exe
+LAUNCHER_ADMINISTRATOR_PROGNAME=launcher_administrator.exe
WINLAUNCHER_PROGNAME=winlauncher.exe
-LINKER=link -nologo
+LINKER=link -nologo /machine:x86
LIBS=advapi32.lib
-CFLAGS= -D_WINDOWS -nologo -MD -W3 -O2 -G6
+CFLAGS= -D_WINDOWS -nologo -W3 -O2
RC=rc
MC=mc
+MT=mt
SRCS = common.c winlauncher.c service.c
@@ -65,6 +67,9 @@
RES_FILE = EventLogMsg.res
+SERVICE_MANIFEST_FILE = opends_service.exe.manifest
+LAUNCHER_ADMINISTRATOR_MANIFEST_FILE = launcher_administrator.exe.manifest
+
.c.obj:
$(CC) $(CFLAGS) -c $< -Fo$@
@@ -73,14 +78,19 @@
$(RC) /fo $(RES_FILE) $(RC_FILE)
-all: $(SERVICE_PROGNAME) $(WINLAUNCHER_PROGNAME)
+all: $(SERVICE_PROGNAME) $(WINLAUNCHER_PROGNAME) $(LAUNCHER_ADMINISTRATOR_PROGNAME)
$(SERVICE_PROGNAME) : $(RES_FILE) $(SERVICE_OBJS)
$(LINKER) /OUT:$(SERVICE_PROGNAME) $(RES_FILE) $(SERVICE_OBJS) $(LIBS)
-
+ $(MT) -manifest "$(SERVICE_MANIFEST_FILE)" -outputresource:"$(SERVICE_PROGNAME)";#1
+
$(WINLAUNCHER_PROGNAME) : $(WINLAUNCHER_OBJS)
$(LINKER) $(WINLAUNCHER_OBJS) /OUT:$(WINLAUNCHER_PROGNAME)
+$(LAUNCHER_ADMINISTRATOR_PROGNAME) : $(WINLAUNCHER_OBJS)
+ $(LINKER) $(WINLAUNCHER_OBJS) /OUT:$(LAUNCHER_ADMINISTRATOR_PROGNAME)
+ $(MT) -manifest "$(LAUNCHER_ADMINISTRATOR_MANIFEST_FILE)" -outputresource:"$(LAUNCHER_ADMINISTRATOR_PROGNAME)";#1
+
clean:
- del $(SERVICE_OBJS) $(EVENTLOG_H) $(WINLAUNCHER_OBJS) $(RC_FILE) $(RES_FILE) $(SERVICE_PROGNAME) $(WINLAUNCHER_PROGNAME) core
+ del $(SERVICE_OBJS) $(EVENTLOG_H) $(WINLAUNCHER_OBJS) $(RC_FILE) $(RES_FILE) $(SERVICE_PROGNAME) $(WINLAUNCHER_PROGNAME) $(LAUNCHER_ADMINISTRATOR_PROGNAME) core
diff --git a/opendj-sdk/opends/src/build-tools/windows/README b/opendj-sdk/opends/src/build-tools/windows/README
index 6a19ec2..e90f3a4 100644
--- a/opendj-sdk/opends/src/build-tools/windows/README
+++ b/opendj-sdk/opends/src/build-tools/windows/README
@@ -44,6 +44,16 @@
See the comments in service.c file and common.c for more information.
+ WHAT is launcher_administrator.exe
+ ========================
+launcher_administrator.exe is a small windows executable that is intended to
+be used by the command line files to launch operations that require
+administrator privileges on Vista. Basically is a wrapper containing a
+manifest that specifies to require administrator privileges to be run. This
+is required if UAC is enabled on Vista so that we have a prompt for the user
+asking for confirmation.
+
+See the comments in winlauncher.c file and common.c for more information.
INSTRUCTIONS TO COMPILE winlauncher.exe
========================
@@ -90,7 +100,7 @@
This will generate the binary winlauncher.exe.
- INSTRUCTIONS TO COMPILE opends_service.exe
+ INSTRUCTIONS TO COMPILE opends_service.exe and administrator_launcher.exe
========================
service.c (the main code file for opends_service.exe) uses windows resources and
so
diff --git a/opendj-sdk/opends/src/build-tools/windows/common.c b/opendj-sdk/opends/src/build-tools/windows/common.c
index daabef4..088360e 100644
--- a/opendj-sdk/opends/src/build-tools/windows/common.c
+++ b/opendj-sdk/opends/src/build-tools/windows/common.c
@@ -53,7 +53,8 @@
STARTUPINFO startInfo; // info to pass to the new process
DWORD processFlag; // background process flag
- debug("Attempting to create child process '%s' background=%d.", command, background);
+ debug("Attempting to create child process '%s' background=%d.", command,
+ background);
// reset process info first
ZeroMemory(procInfo, sizeof(PROCESS_INFORMATION));
@@ -84,7 +85,8 @@
}
else
{
- debugError("Failed to create child process '%s'. Last error = %d.", command, GetLastError());
+ debugError("Failed to create child process '%s'. Last error = %d.",
+ command, GetLastError());
}
return createOk;
@@ -156,7 +158,8 @@
{
currentProcessPid = GetCurrentProcessId();
noMessageLogged = FALSE;
- debug("--------------- FIRST LOG MESSAGE FROM '%s' ---------------", _pgmptr);
+ debug("--------------- FIRST LOG MESSAGE FROM '%s' ---------------",
+ _pgmptr);
}
// Time-stamp
@@ -211,7 +214,8 @@
MAX_PATH
);
- // Cut everything after the last slash, twice. This will take us back to the instance root.
+ // Cut everything after the last slash, twice. This will take us back to the
+ // instance root.
// This logic assumes that we are in a directory above the instance root.
lastSlash = strrchr(execName, '\\');
lastSlash[0] = '\0';
diff --git a/opendj-sdk/opends/src/build-tools/windows/launcher_administrator.exe.manifest b/opendj-sdk/opends/src/build-tools/windows/launcher_administrator.exe.manifest
new file mode 100644
index 0000000..f0c7d11
--- /dev/null
+++ b/opendj-sdk/opends/src/build-tools/windows/launcher_administrator.exe.manifest
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity version="1.0.0.0"
+ processorArchitecture="X86" name="launcher_administrator" type="win32"/>
+ <description>Executable used to run code that requires administrator privileges</description>
+ <!-- Identify the application security requirements. -->
+ <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
+ <ms_asmv2:security>
+ <ms_asmv2:requestedPrivileges>
+ <ms_asmv2:requestedExecutionLevel
+ level="requireAdministrator"
+ uiAccess="false"/>
+ </ms_asmv2:requestedPrivileges>
+ </ms_asmv2:security>
+ </ms_asmv2:trustInfo>
+</assembly>
diff --git a/opendj-sdk/opends/src/build-tools/windows/opends_service.exe.manifest b/opendj-sdk/opends/src/build-tools/windows/opends_service.exe.manifest
new file mode 100644
index 0000000..7db0633
--- /dev/null
+++ b/opendj-sdk/opends/src/build-tools/windows/opends_service.exe.manifest
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity version="1.0.0.0"
+ processorArchitecture="X86" name="opends_service" type="win32"/>
+ <description>Executable used to run OpenDS as a Windows Service</description>
+ <!-- Identify the application security requirements. -->
+ <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
+ <ms_asmv2:security>
+ <ms_asmv2:requestedPrivileges>
+ <ms_asmv2:requestedExecutionLevel
+ level="asInvoker"
+ uiAccess="false"/>
+ </ms_asmv2:requestedPrivileges>
+ </ms_asmv2:security>
+ </ms_asmv2:trustInfo>
+</assembly>
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/build-tools/windows/service.c b/opendj-sdk/opends/src/build-tools/windows/service.c
index 5152900..1e70851 100644
--- a/opendj-sdk/opends/src/build-tools/windows/service.c
+++ b/opendj-sdk/opends/src/build-tools/windows/service.c
@@ -72,7 +72,7 @@
}
debug("registerServiceHandler returning '%d'", returnValue);
-
+
return returnValue;
} // registerServiceHandler
@@ -147,7 +147,8 @@
);
if (scm == NULL)
{
- debugError("Failed to open the Service Control Manager. Last error = %d", GetLastError());
+ debugError("Failed to open the Service Control Manager. Last error = %d",
+ GetLastError());
returnValue = SERVICE_RETURN_ERROR;
}
else
@@ -247,7 +248,8 @@
);
if (result != ERROR_SUCCESS)
{
- debugError("RegSetValueEx('EventMessageFile') failed, result=%d.", result);
+ debugError("RegSetValueEx('EventMessageFile') failed, result=%d.",
+ result);
success = FALSE;
}
}
@@ -290,7 +292,8 @@
);
if (result != ERROR_SUCCESS)
{
- debugError("RegSetValueEx('CategoryMessageFile') failed, result=%d.", result);
+ debugError("RegSetValueEx('CategoryMessageFile') failed, result=%d.",
+ result);
success = FALSE;
}
}
@@ -362,7 +365,8 @@
);
if (result != ERROR_SUCCESS)
{
- debug("The registry key for service '%s' does not exist, so we do not need to remove it.", serviceName);
+ debug("The registry key for service '%s' does not exist, so we do not need to remove it.",
+ serviceName);
// Assume that the registry key does not exist.
returnValue = TRUE;
}
@@ -429,14 +433,15 @@
char* relativePath = "\\locks\\server.lock";
char lockFile[MAX_PATH];
debug("Determining if the server is running.");
-
+
if (strlen(relativePath)+strlen(_instanceDir)+1 < MAX_PATH)
{
int fd;
sprintf(lockFile, "%s%s", _instanceDir, relativePath);
- debug("When determining whether the server is running, the lock file name is '%s'.", lockFile);
-
+ debug("When determining whether the server is running, the lock file name is '%s'.",
+ lockFile);
+
fd = _open(lockFile, _O_RDWR);
if (fd != -1)
@@ -469,7 +474,8 @@
}
else
{
- debug("Could not open lock file '%s', which means the server is not running.", lockFile);
+ debug("Could not open lock file '%s', which means the server is not running.",
+ lockFile);
*running = FALSE;
returnValue = SERVICE_RETURN_ERROR;
}
@@ -499,7 +505,7 @@
debug("doStartApplication called.");
-
+
if (strlen(relativePath)+strlen(_instanceDir)+1 < COMMAND_SIZE)
{
sprintf(command, "\"%s%s\" --windowsNetStart", _instanceDir, relativePath);
@@ -511,8 +517,10 @@
// Try to see if server is really running
int nTries = 10;
BOOL running = FALSE;
-
- debug("doStartApplication: the spawn of the process worked. Command: '%s'", command);
+
+ debug(
+ "doStartApplication: the spawn of the process worked. Command: '%s'",
+ command);
// Wait to be able to launch the java process in order it to free the lock
// on the file.
debug("Sleeping for 3 seconds to allow the process to free the lock.");
@@ -526,7 +534,8 @@
}
if (!running)
{
- debug("Sleeping for 2 seconds to allow the process to free the lock. %d tries remaining.", nTries);
+ debug("Sleeping for 2 seconds to allow the process to free the lock. %d tries remaining.",
+ nTries);
Sleep(2000);
}
}
@@ -543,7 +552,7 @@
}
else
{
-
+
returnValue = SERVICE_RETURN_ERROR;
debug("doStartApplication: spawn failed. Sent command: '%s'", command);
}
@@ -577,9 +586,9 @@
// Try to see if server is really stopped
int nTries = 10;
BOOL running = TRUE;
-
+
debug("doStopApplication: the spawn of the process worked.");
-
+
// Wait to be able to launch the java process in order it to free the lock
// on the file.
Sleep(3000);
@@ -625,7 +634,7 @@
// serviceBinPath the path to the service binary.
// instanceDir the instanceDirectory.
// The string stored in serviceBinPath looks like
-// <SERVER_ROOT>/lib/service.exe start <_instanceDir>
+// <SERVER_ROOT>/lib/opends_service.exe start <_instanceDir>
// It is up to the caller of the function to allocate
// at least COMMAND_SIZE bytes in serviceBinPath.
// The function returns SERVICE_RETURN_OK if we could create the binary
@@ -652,7 +661,9 @@
}
else
{
- debug("When determining the service bin path, the module file name is '%s'.", fileName);
+ debug(
+ "When determining the service bin path, the module file name is '%s'.",
+ fileName);
if (result == MAX_PATH)
{
@@ -662,15 +673,16 @@
}
else
{
- if ((strlen(fileName) + strlen(" start ") + strlen(_instanceDir) + 2 * strlen("\"\""))
- < COMMAND_SIZE)
+ if ((strlen(fileName) + strlen(" start ") + strlen(_instanceDir) +
+ 2 * strlen("\"\"")) < COMMAND_SIZE)
{
sprintf(serviceBinPath, "\"%s\" start \"%s\"", fileName,
_instanceDir);
}
else
{
- char * msg = "The name of the resulting windows service command is too long.\n";
+ char * msg =
+ "The name of the resulting windows service command is too long.\n";
debug(msg);
// buffer was too small, executable name is probably not valid
returnValue = SERVICE_RETURN_ERROR;
@@ -704,7 +716,8 @@
strcpy(serviceName, "");
- debug("Attempting to get the service name assuming command to run is '%s'.", cmdToRun);
+ debug("Attempting to get the service name assuming command to run is '%s'.",
+ cmdToRun);
returnValue = getServiceList(&serviceList, &nbServices);
@@ -733,7 +746,8 @@
}
else
{
- debug("The service name found is too long: '%s'", curService.serviceName);
+ debug("The service name found is too long: '%s'",
+ curService.serviceName);
}
break;
}
@@ -748,7 +762,7 @@
}
debug("The service name was found to be '%s'.", serviceName);
-
+
return returnValue;
} // getServiceName
@@ -801,7 +815,7 @@
debug("Updating the service status. statusToSet=%d win32ExitCode=%d serviceExitCode=%d checkPoint=%d waitHint=%d",
statusToSet, win32ExitCode, serviceExitCode,
checkPoint, waitHint);
-
+
if (statusToSet == SERVICE_START_PENDING)
{
debug("Service start pending.");
@@ -835,7 +849,8 @@
if (!success)
{
- debugError("Failed to set the service status. Last error = %d.", GetLastError());
+ debugError("Failed to set the service status. Last error = %d.",
+ GetLastError());
returnValue = SERVICE_RETURN_ERROR;
}
else
@@ -872,7 +887,7 @@
// __debugbreak();
debug("serviceMain called.");
-
+
code = createServiceBinPath(cmdToRun);
if (code == SERVICE_RETURN_OK)
@@ -1170,8 +1185,8 @@
//
// scm is the SCM handler (must not be NULL)
// serviceName the name of the service.
-// It is up to the caller of the function to allocate at least COMMAND_SIZE bytes
-// in binPathName.
+// It is up to the caller of the function to allocate at least COMMAND_SIZE
+// bytes in binPathName.
// The function returns SERVICE_RETURN_OK if we could create the binary
// path name and SERVICE_RETURN_ERROR otherwise.
// ---------------------------------------------------------------
@@ -1232,7 +1247,8 @@
}
else
{
- debug("getBinaryPath: error calling QueryServiceConfig. Code [%d]", errCode);
+ debug("getBinaryPath: error calling QueryServiceConfig. Code [%d]",
+ errCode);
break;
}
}
@@ -1245,7 +1261,8 @@
}
else
{
- debug("getBinaryPath: the length of the binary path name is too big. serviceName='%s', binaryPath='%s'", serviceName, serviceConfig->lpBinaryPathName);
+ debug("getBinaryPath: the length of the binary path name is too big. serviceName='%s', binaryPath='%s'",
+ serviceName, serviceConfig->lpBinaryPathName);
}
}
}
@@ -1330,7 +1347,8 @@
if (lastError != ERROR_MORE_DATA)
{
returnValue = SERVICE_RETURN_ERROR;
- debug("getServiceList: second try generic error. Code [%d]", lastError);
+ debug("getServiceList: second try generic error. Code [%d]",
+ lastError);
}
else
{
@@ -1384,7 +1402,8 @@
}
else
{
- debug("Error getting binary path name of service: %s", l[i].serviceName);
+ debug("Error getting binary path name of service: %s",
+ l[i].serviceName);
}
curService++;
}
@@ -1425,7 +1444,7 @@
int i;
debug("Determining if service name '%s' is in use.", serviceName);
-
+
// go through the list of services and search for the service name
if (getServiceList(&serviceList, &nbServices) == SERVICE_RETURN_OK)
{
@@ -1456,7 +1475,8 @@
}
else
{
- debugError("Could not determine if the service name '%s' is in use because listing the services failed.", serviceName);
+ debugError("Could not determine if the service name '%s' is in use because listing the services failed.",
+ serviceName);
returnValue = SERVICE_RETURN_ERROR;
}
return returnValue;
@@ -1513,7 +1533,7 @@
}
debug("createServiceName returning serviceName='%s' and returnValue=%d",
- serviceName, returnValue);
+ serviceName, returnValue);
return returnValue;
} // createServiceName
@@ -1547,7 +1567,7 @@
// create the service
if (returnValue == SERVICE_RETURN_OK)
{
- if (openScm(GENERIC_WRITE, &scm) != SERVICE_RETURN_OK)
+ if (openScm(SC_MANAGER_ALL_ACCESS, &scm) != SERVICE_RETURN_OK)
{
returnValue = SERVICE_RETURN_ERROR;
debug("createServiceInScm: openScm did not work.");
@@ -1583,7 +1603,8 @@
if ((returnValue == SERVICE_RETURN_OK) && (myService == NULL))
{
DWORD errCode = GetLastError();
- debugError("Failed to create the service '%s'. Last error = %d.", serviceName, errCode);
+ debugError("Failed to create the service '%s'. Last error = %d.",
+ serviceName, errCode);
if (errCode == ERROR_DUPLICATE_SERVICE_NAME)
{
returnValue = DUPLICATED_SERVICE_NAME;
@@ -1594,6 +1615,10 @@
}
else
{
+ if (errCode == ERROR_INVALID_HANDLE)
+ {
+ debugError("The handle seems to be invalid.");
+ }
returnValue = SERVICE_RETURN_ERROR;
}
}
@@ -1612,7 +1637,9 @@
if (!success)
{
- debugError("Failed to add a description to the service '%s'. Last error = %d.", serviceName, GetLastError());
+ debugError(
+ "Failed to add a description to the service '%s'. Last error = %d.",
+ serviceName, GetLastError());
returnValue = SERVICE_RETURN_ERROR;
}
}
@@ -1635,7 +1662,7 @@
}
debug("createServiceInScm returning %d.", returnValue);
-
+
return returnValue;
} // createServiceInScm
@@ -1656,7 +1683,7 @@
SERVICE_STATUS serviceStatus;
debug("Removing service '%s' from the Service Control Manager.", serviceName);
-
+
returnValue = openScm(GENERIC_WRITE, &scm);
// open the service
@@ -1671,7 +1698,8 @@
debug("After opening service myService=%d.", myService);
if (myService == NULL)
{
- debugError("Failed to open the service '%s'. Last error = %d", serviceName, GetLastError());
+ debugError("Failed to open the service '%s'. Last error = %d",
+ serviceName, GetLastError());
returnValue = SERVICE_RETURN_ERROR;
}
}
@@ -1686,7 +1714,8 @@
);
if (!success)
{
- debugError("Failed to query the status for service '%s'. Last error = %d", serviceName, GetLastError());
+ debugError("Failed to query the status for service '%s'. Last error = %d",
+ serviceName, GetLastError());
returnValue = SERVICE_RETURN_ERROR;
}
}
@@ -1707,7 +1736,8 @@
if (!success)
{
DWORD errCode = GetLastError();
- debugError("Failed to stop the service '%s'. Last error = %d.", serviceName, errCode);
+ debugError("Failed to stop the service '%s'. Last error = %d.",
+ serviceName, errCode);
if (errCode == ERROR_SERVICE_MARKED_FOR_DELETE)
{
returnValue = SERVICE_MARKED_FOR_DELETION;
@@ -1733,7 +1763,8 @@
if (!success)
{
DWORD errCode = GetLastError();
- debugError("Failed to delete the service '%s'. Last error = %d.", serviceName, errCode);
+ debugError("Failed to delete the service '%s'. Last error = %d.",
+ serviceName, errCode);
if (errCode == ERROR_SERVICE_MARKED_FOR_DELETE)
{
returnValue = SERVICE_MARKED_FOR_DELETION;
@@ -1778,7 +1809,8 @@
char cmdToRun[COMMAND_SIZE];
ServiceReturnCode code;
- debug("Creating service displayName='%s' description='%s'.", displayName, description);
+ debug("Creating service displayName='%s' description='%s'.", displayName,
+ description);
code = createServiceBinPath(cmdToRun);
if (code == SERVICE_RETURN_OK)
@@ -1858,12 +1890,13 @@
strcpy(serviceName, "");
debug("Getting service state.");
code = createServiceBinPath(cmdToRun);
- debug("Created the service bin path. code=%d. cmdToRun='%s'.", code, cmdToRun);
+ debug("Created the service bin path. code=%d. cmdToRun='%s'.", code,
+ cmdToRun);
if (code == SERVICE_RETURN_OK)
{
code = getServiceName(cmdToRun, serviceName);
-
+
if (code == SERVICE_RETURN_OK)
{
// There is a valid serviceName for the command to run, so
@@ -1875,7 +1908,7 @@
else
{
returnCode = 1;
- debug("Service '%s' is disabled enabled.", serviceName);
+ debug("Service '%s' is disabled.", serviceName);
}
}
else
@@ -2072,7 +2105,7 @@
char* subcommand;
int returnCode = 0;
int i;
-
+
updateDebugFlag(argv, argc);
debug("main called.");
@@ -2201,7 +2234,7 @@
}
debug("main returning %d.", returnCode);
-
+
return returnCode;
} // main
diff --git a/opendj-sdk/opends/src/build-tools/windows/winlauncher.c b/opendj-sdk/opends/src/build-tools/windows/winlauncher.c
index 2f446e7..2fb58a8 100644
--- a/opendj-sdk/opends/src/build-tools/windows/winlauncher.c
+++ b/opendj-sdk/opends/src/build-tools/windows/winlauncher.c
@@ -63,7 +63,7 @@
{
struct stat finfo;
BOOL returnValue = FALSE;
-
+
if(stat(fileName, &finfo) < 0)
{
returnValue = FALSE;
@@ -89,7 +89,7 @@
BOOL returnValue = FALSE;
char pidFile[PATH_SIZE];
int nTries = 10;
-
+
debug("Attempting to delete the PID file from instanceDir='%s'.", instanceDir);
// Sometimes the lock on the system in windows takes time to be released.
if (getPidFile(instanceDir, pidFile, PATH_SIZE))
@@ -110,7 +110,7 @@
}
}
}
-
+
debug("deletePidFile('%s') returning %d.", instanceDir, returnValue);
return returnValue;
} // deletePidFile
@@ -128,7 +128,7 @@
FILE *f;
char buf[BUF_SIZE];
int read;
-
+
debug("Attempting to get the PID for the server rooted at '%s'.", instanceDir);
if (getPidFile(instanceDir, pidFile, PATH_SIZE))
{
@@ -137,7 +137,7 @@
read = fread(buf, 1, sizeof(buf),f);
debug("Read '%s' from the PID file '%s'.", buf, pidFile);
}
-
+
if (f != NULL)
{
fclose(f);
@@ -179,7 +179,7 @@
FALSE, // handle is not inheritable
pid
);
-
+
if (procHandle == NULL)
{
debug("The process with pid=%d has already terminated.", pid);
@@ -201,7 +201,7 @@
debug("Successfully began termination process for (pid=%d).", pid);
// wait for the process to end.
-
+
processDead = FALSE;
while ((nTries > 0) && !processDead)
{
@@ -234,11 +234,11 @@
// otherwise.
// ----------------------------------------------------
BOOL createPidFile(const char* instanceDir, int pid)
-{
+{
BOOL returnValue = FALSE;
char pidFile[PATH_SIZE];
FILE *f;
-
+
debug("createPidFile(instanceDir='%s',pid=%d)", instanceDir, pid);
if (getPidFile(instanceDir, pidFile, PATH_SIZE))
@@ -261,7 +261,7 @@
debugError("Couldn't create the pid file because the pid file name could not be constructed.");
returnValue = FALSE;
}
-
+
return returnValue;
} // createPidFile
@@ -281,11 +281,11 @@
BOOL overflow = FALSE;
debug("Constructing full command line from arguments:");
- for (i = 0; (argv[i] != NULL); i++)
+ for (i = 0; (argv[i] != NULL); i++)
{
debug(" argv[%d]: %s", i, argv[i]);
}
-
+
i = 0;
while ((argv[i] != NULL) && !overflow)
{
@@ -302,11 +302,11 @@
overflow = TRUE;
}
}
-
+
if (curarg[0] != '\0')
{
int argInd = 0;
-
+
if (curarg[0] == '"')
{
// there is a quote: no need to add extra quotes
@@ -346,7 +346,7 @@
overflow = TRUE;
}
}
-
+
} else {
if (curCmdInd + strlen("\"\"") < maxSize)
{
@@ -360,15 +360,15 @@
}
}
- if (overflow)
+ if (overflow)
{
debugError("Failed to construct the full commandline because the buffer wasn't big enough.");
- }
- else
+ }
+ else
{
debug("The full commandline is '%s'.", command);
}
-
+
return !overflow;
} // getCommandLine
@@ -397,13 +397,13 @@
{
int returnValue;
int childPid;
-
+
char command[COMMAND_SIZE];
if (getCommandLine(argv, command, COMMAND_SIZE))
{
childPid = spawn(command, TRUE);
-
+
if (childPid > 0)
{
createPidFile(instanceDir, childPid);
@@ -420,7 +420,7 @@
debugError("Couldn't start the child process because the full command line could not be constructed.");
returnValue = -1;
}
-
+
return returnValue;
} // start
@@ -449,13 +449,13 @@
int stop(const char* instanceDir)
{
int returnCode = -1;
-
+
int childPid;
-
+
debug("Attempting to stop the server running at root '%s'.", instanceDir);
childPid = getPid(instanceDir);
-
+
if (childPid != 0)
{
if (killProcess(childPid))
@@ -464,7 +464,7 @@
deletePidFile(instanceDir);
}
}
- else
+ else
{
debug("Could not stop the server running at root '%s' because the pid could not be located.", instanceDir);
}
@@ -485,7 +485,7 @@
// prompt-window associated with it.
// Launch batch files from the prompt that generate a java process that does not
// block the prompt and that keeps running even if the prompt window is closed.
-//
+//
// This function expects the following parameter to be passed:
// the directory of the server we want to start and the
// command line that we want to execute (basically the java
@@ -495,19 +495,19 @@
// 2. Allow the administrator some flexibility in the way the
// server is started by leaving most of the logic in the command-line.
//
-// Returns the pid of the process associated with the command if it could be
+// Returns the pid of the process associated with the command if it could be
// launched and -1 otherwise.
// ----------------------------------------------------
int launch(char* argv[])
{
int returnValue;
-
+
char command[COMMAND_SIZE];
-
+
if (getCommandLine(argv, command, COMMAND_SIZE))
{
returnValue = spawn(command, TRUE);
- if (returnValue <= 0)
+ if (returnValue <= 0)
{
debugError("Failed to launch the child process '%s'.", command);
}
@@ -521,18 +521,60 @@
debugError("Couldn't launch the child process because the full command line could not be constructed.");
returnValue = -1;
}
-
+
return returnValue;
} // launch
+//----------------------------------------------------
+// Function called when we want to launch a process and it to be run as
+// administrator on Vista (the binary containing this function must have
+// a manifest specifying that).
+// Returns the exit code of the process associated with the command if it
+// could be launched and -1 otherwise.
+//----------------------------------------------------
+int run(char* argv[])
+{
+ PROCESS_INFORMATION procInfo; // info on the new process
+ BOOL createOk;
+ DWORD exitCode;
+ int returnValue = -1;
+ int millisToWait = 30000;
+ int waitedMillis = 0;
+
+ char command[COMMAND_SIZE];
+
+ if (getCommandLine(argv, command, COMMAND_SIZE))
+ {
+ createOk = createChildProcess((char*)command, TRUE, &procInfo);
+
+ if(createOk)
+ {
+ GetExitCodeProcess(procInfo.hProcess, &exitCode);
+ while (exitCode == STILL_ACTIVE)
+ {
+ GetExitCodeProcess(procInfo.hProcess, &exitCode);
+ Sleep(500);
+ waitedMillis += 500;
+ if (waitedMillis > millisToWait)
+ {
+ break;
+ }
+ }
+ returnValue = exitCode;
+ }
+ }
+ return returnValue;
+} // run
+
// ----------------------------------------------------
// main function called by the executable. This code is
// called by the start-ds.bat, stop-ds.bat and statuspanel.bat batch files.
//
// The code assumes that the first passed argument is the subcommand to be
-// executed and the second argument the directory of the server. The rest
-// of the arguments are the arguments specific to each subcommand (see the
-// comments for the functions start, stop and launch).
+// executed and for start and stop the second argument the directory of the
+// server.
+// The rest of the arguments are the arguments specific to each subcommand (see
+// the comments for the functions start, stop and launch).
// ----------------------------------------------------
int main(int argc, char* argv[])
{
@@ -540,36 +582,44 @@
char* subcommand = NULL;
char* instanceDir = NULL;
int i;
-
+
debug("main called.");
for (i = 0; i < argc; i++) {
debug(" argv[%d] = '%s'", i, argv[i]);
}
if (argc < 3) {
- char * msg = "Expected command line args of [subcommand] [server directory], but got %d arguments.\n";
+ char * msg =
+ "Expected command line args of [subcommand], but got %d arguments.\n";
debugError(msg, argc - 1);
fprintf(stderr, msg, argc - 1);
return -1;
}
subcommand = argv[1];
- instanceDir = argv[2];
- argv += 3;
-
if (strcmp(subcommand, "start") == 0)
{
+ instanceDir = argv[2];
+ argv += 3;
returnCode = start(instanceDir, argv);
}
else if (strcmp(subcommand, "stop") == 0)
{
+ instanceDir = argv[2];
+ argv += 3;
returnCode = stop(instanceDir);
}
else if (strcmp(subcommand, "launch") == 0)
{
+ argv += 2;
returnCode = launch(argv);
}
+ else if (strcmp(subcommand, "run") == 0)
+ {
+ argv += 2;
+ returnCode = run(argv);
+ }
else
{
char * msg = "Unknown subcommand: [%s]\n";
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/ConfigureWindowsService.java b/opendj-sdk/opends/src/server/org/opends/server/tools/ConfigureWindowsService.java
index b77c1d5..ef389f6 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/ConfigureWindowsService.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/ConfigureWindowsService.java
@@ -36,6 +36,7 @@
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.NullOutputStream;
+import org.opends.server.util.SetupUtils;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.ArgumentParser;
import org.opends.server.util.args.BooleanArgument;
@@ -52,6 +53,22 @@
* 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.
+ *
+ * Some comments about Vista:
+ * In Vista, when we launch the subcommands that require administrator
+ * privileges (enable, disable and cleanup) we cannot use the administrator
+ * launcher binary directly from Java (see
+ * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6410605) so we use
+ * winlauncher.exe.
+ * When we launch subcommands that required administrator privileges
+ * we must launch a binary containing the manifest that specifies that we
+ * require administrator privileges (requireAdministrator value): if UAC is
+ * enabled, the user will be asked for confirmation.
+ * To minimize the number of confirmation that the user must provide when
+ * launching the state subcommand we will use a binary whose manifest does
+ * not contain the requireAdministrator value.
+ *
+ * See the files under src/build-tools/windows for more details.
*/
public class ConfigureWindowsService
{
@@ -62,6 +79,10 @@
"org.opends.server.tools.ConfigureWindowsService";
private static final String DEBUG_OPTION = "--debug";
+ /**
+ * Option to be used when calling the launchers.
+ */
+ public static final String LAUNCHER_OPTION = "run";
private static int ERROR = 1;
@@ -333,7 +354,7 @@
getBinaryFullPath(),
"state",
serverRoot
- };
+ };
try
{
Process p = Runtime.getRuntime().exec(cmd);
@@ -385,14 +406,35 @@
String msg;
String serverRoot = getServerRoot();
- String[] cmd = {
- getBinaryFullPath(),
- "create",
- serverRoot,
- getMessage(MSGID_WINDOWS_SERVICE_NAME, (Object[]) null),
- getMessage(MSGID_WINDOWS_SERVICE_DESCRIPTION, serverRoot),
- DEBUG_OPTION
- };
+ String[] cmd;
+
+ if (isVista())
+ {
+ cmd = new String[] {
+ getLauncherBinaryFullPath(),
+ LAUNCHER_OPTION,
+ getLauncherAdministratorBinaryFullPath(),
+ LAUNCHER_OPTION,
+ getBinaryFullPath(),
+ "create",
+ serverRoot,
+ getMessage(MSGID_WINDOWS_SERVICE_NAME, (Object[]) null),
+ getMessage(MSGID_WINDOWS_SERVICE_DESCRIPTION, serverRoot),
+ DEBUG_OPTION
+ };
+ }
+ else
+ {
+ cmd = new String[] {
+ getBinaryFullPath(),
+ "create",
+ serverRoot,
+ getMessage(MSGID_WINDOWS_SERVICE_NAME, (Object[]) null),
+ getMessage(MSGID_WINDOWS_SERVICE_DESCRIPTION, serverRoot),
+ DEBUG_OPTION
+ };
+ }
+
try
{
int resultCode = Runtime.getRuntime().exec(cmd).waitFor();
@@ -456,12 +498,29 @@
int returnValue;
String msg;
String serverRoot = getServerRoot();
- String[] cmd = {
+ String[] cmd;
+ if (isVista())
+ {
+ cmd = new String[] {
+ getLauncherBinaryFullPath(),
+ LAUNCHER_OPTION,
+ getLauncherAdministratorBinaryFullPath(),
+ LAUNCHER_OPTION,
+ getBinaryFullPath(),
+ "remove",
+ serverRoot,
+ DEBUG_OPTION
+ };
+ }
+ else
+ {
+ cmd = new String[] {
getBinaryFullPath(),
"remove",
serverRoot,
DEBUG_OPTION
};
+ }
try
{
int resultCode = Runtime.getRuntime().exec(cmd).waitFor();
@@ -525,12 +584,29 @@
{
int returnValue;
String msg;
- String[] cmd = {
- getBinaryFullPath(),
- "cleanup",
- serviceName,
- DEBUG_OPTION
- };
+ String[] cmd;
+ if (isVista())
+ {
+ cmd = new String[] {
+ getLauncherBinaryFullPath(),
+ LAUNCHER_OPTION,
+ getLauncherAdministratorBinaryFullPath(),
+ LAUNCHER_OPTION,
+ getBinaryFullPath(),
+ "cleanup",
+ serviceName,
+ DEBUG_OPTION
+ };
+ }
+ else
+ {
+ cmd = new String[] {
+ getBinaryFullPath(),
+ "cleanup",
+ serviceName,
+ DEBUG_OPTION
+ };
+ }
try
{
int resultCode = Runtime.getRuntime().exec(cmd).waitFor();
@@ -588,12 +664,13 @@
String serviceName = null;
String serverRoot = getServerRoot();
- String[] cmd = {
+ String[] cmd = new String[] {
getBinaryFullPath(),
"state",
serverRoot,
DEBUG_OPTION
- };
+ };
+
try
{
int resultCode = -1;
@@ -711,7 +788,8 @@
/**
* Returns the full path of the executable used by this class to perform
- * operations related to the service.
+ * operations related to the service. This binaries file has the asInvoker
+ * value in its manifest.
* @return the full path of the executable used by this class to perform
* operations related to the service.
*/
@@ -719,4 +797,41 @@
{
return getServerRoot()+"\\lib\\opends_service.exe";
}
+
+ /**
+ * Returns the full path of the executable that has a manifest requiring
+ * administrator privileges used by this class to perform
+ * operations related to the service.
+ * @return the full path of the executable that has a manifest requiring
+ * administrator privileges used by this class to perform
+ * operations related to the service.
+ */
+ public static String getLauncherAdministratorBinaryFullPath()
+ {
+ return getServerRoot()+"\\lib\\launcher_administrator.exe";
+ }
+
+ /**
+ * Returns the full path of the executable that has a manifest requiring
+ * administrator privileges used by this class to perform
+ * operations related to the service.
+ * @return the full path of the executable that has a manifest requiring
+ * administrator privileges used by this class to perform
+ * operations related to the service.
+ */
+ public static String getLauncherBinaryFullPath()
+ {
+ return getServerRoot()+"\\lib\\winlauncher.exe";
+ }
+
+ /**
+ * Indicates whether the underlying operating system is Windows Vista.
+ *
+ * @return {@code true} if the underlying operating system is Windows
+ * Vista, or {@code false} if not.
+ */
+ private static boolean isVista()
+ {
+ return SetupUtils.isVista();
+ }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/StartWindowsService.java b/opendj-sdk/opends/src/server/org/opends/server/tools/StartWindowsService.java
index 1c3d340..cb005eb 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/StartWindowsService.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/StartWindowsService.java
@@ -31,6 +31,7 @@
import java.io.PrintStream;
import org.opends.server.types.NullOutputStream;
+import org.opends.server.util.SetupUtils;
import static org.opends.server.messages.MessageHandler.getMessage;
import static org.opends.server.messages.ToolMessages.*;
@@ -113,11 +114,27 @@
}
else
{
- String[] cmd = {
- "net",
- "start",
- serviceName
- };
+ String[] cmd;
+ if (SetupUtils.isVista())
+ {
+ cmd= new String[] {
+ ConfigureWindowsService.getLauncherBinaryFullPath(),
+ ConfigureWindowsService.LAUNCHER_OPTION,
+ ConfigureWindowsService.getLauncherAdministratorBinaryFullPath(),
+ ConfigureWindowsService.LAUNCHER_OPTION,
+ "net",
+ "start",
+ serviceName
+ };
+ }
+ else
+ {
+ cmd= new String[] {
+ "net",
+ "start",
+ serviceName
+ };
+ }
/* Check if is a running service */
try
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/StopWindowsService.java b/opendj-sdk/opends/src/server/org/opends/server/tools/StopWindowsService.java
index 9a57f90..257722f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/StopWindowsService.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/StopWindowsService.java
@@ -31,6 +31,7 @@
import java.io.PrintStream;
import org.opends.server.types.NullOutputStream;
+import org.opends.server.util.SetupUtils;
import static org.opends.server.messages.MessageHandler.getMessage;
import static org.opends.server.messages.ToolMessages.*;
@@ -117,11 +118,27 @@
}
else
{
- String[] cmd = {
- "net",
- "stop",
- serviceName
- };
+ String[] cmd;
+ if (SetupUtils.isVista())
+ {
+ cmd= new String[] {
+ ConfigureWindowsService.getLauncherBinaryFullPath(),
+ ConfigureWindowsService.LAUNCHER_OPTION,
+ ConfigureWindowsService.getLauncherAdministratorBinaryFullPath(),
+ ConfigureWindowsService.LAUNCHER_OPTION,
+ "net",
+ "stop",
+ serviceName
+ };
+ }
+ else
+ {
+ cmd= new String[] {
+ "net",
+ "stop",
+ serviceName
+ };
+ }
/* Check if is a running service */
try
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/SetupUtils.java b/opendj-sdk/opends/src/server/org/opends/server/util/SetupUtils.java
index 20e779e..544d922 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/SetupUtils.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/SetupUtils.java
@@ -154,6 +154,26 @@
}
/**
+ * Indicates whether the underlying operating system is Windows Vista.
+ *
+ * @return {@code true} if the underlying operating system is Windows
+ * Vista, or {@code false} if not.
+ */
+ public static boolean isVista()
+ {
+ boolean isVista;
+ String os = System.getProperty("os.name");
+ if (os != null)
+ {
+ isVista = isWindows() && (os.toLowerCase().indexOf("vista") != -1);
+ }
+ else
+ {
+ isVista = false;
+ }
+ return isVista;
+ }
+ /**
* Returns a String representation of the OS we are running.
* @return a String representation of the OS we are running.
*/
--
Gitblit v1.10.0