8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 06:43:03 +01:00

Merged recent FB 1.5 instsvc / instreg changes to head branch.

This commit is contained in:
epocman 2003-08-29 17:25:36 +00:00
parent fb1d765bee
commit c2e97bdd1c
6 changed files with 544 additions and 435 deletions

View File

@ -24,17 +24,17 @@
#ifndef _UTILITIES_INSTALL_NT_H_ #ifndef _UTILITIES_INSTALL_NT_H_
#define _UTILITIES_INSTALL_NT_H_ #define _UTILITIES_INSTALL_NT_H_
#define REMOTE_SERVICE "FirebirdServer" #define REMOTE_SERVICE "FirebirdServer"
#define REMOTE_DISPLAY_NAME "Firebird Server" #define REMOTE_DISPLAY_NAME "Firebird Server"
#define REMOTE_SS_EXECUTABLE "bin\\fbserver" #define REMOTE_SS_EXECUTABLE "bin\\fbserver"
#define REMOTE_CS_EXECUTABLE "bin\\fb_inet_server" #define REMOTE_CS_EXECUTABLE "bin\\fb_inet_server"
#define ISCGUARD_SERVICE "FirebirdGuardian" #define ISCGUARD_SERVICE "FirebirdGuardian"
#define ISCGUARD_DISPLAY_NAME "Firebird Guardian" #define ISCGUARD_DISPLAY_NAME "Firebird Guardian"
#define ISCGUARD_EXECUTABLE "bin\\fbguard" #define ISCGUARD_EXECUTABLE "bin\\fbguard"
#define GUARDIAN_MUTEX "FirebirdGuardianMutex" #define GUARDIAN_MUTEX "FirebirdGuardianMutex"
/* Starting with 128 the service prams are user defined */ /* Starting with 128 the service prams are user defined */
#define SERVICE_CREATE_GUARDIAN_MUTEX 128 #define SERVICE_CREATE_GUARDIAN_MUTEX 128
#define REMOTE_DEPENDENCIES "Tcpip\0\0" #define REMOTE_DEPENDENCIES "Tcpip\0\0"
#define COMMAND_NONE 0 #define COMMAND_NONE 0
#define COMMAND_INSTALL 1 #define COMMAND_INSTALL 1
@ -42,6 +42,7 @@
#define COMMAND_START 3 #define COMMAND_START 3
#define COMMAND_STOP 4 #define COMMAND_STOP 4
#define COMMAND_CONFIG 5 #define COMMAND_CONFIG 5
#define COMMAND_QUERY 6
#define STARTUP_DEMAND 0 #define STARTUP_DEMAND 0
#define STARTUP_AUTO 1 #define STARTUP_AUTO 1
@ -49,7 +50,7 @@
#define NO_GUARDIAN 0 #define NO_GUARDIAN 0
#define USE_GUARDIAN 1 #define USE_GUARDIAN 1
#define DEFAULT_CLIENT 0 #define DEFAULT_PRIORITY 0
#define NORMAL_PRIORITY 1 #define NORMAL_PRIORITY 1
#define HIGH_PRIORITY 2 #define HIGH_PRIORITY 2
@ -57,9 +58,9 @@
#define ARCH_CS 1 #define ARCH_CS 1
#define IB_SERVICE_ALREADY_DEFINED 100 #define IB_SERVICE_ALREADY_DEFINED 100
#define IB_SERVICE_RUNNING 101 #define IB_SERVICE_RUNNING 101
#define IB_GUARDIAN_ALREADY_DEFINED 102 #define IB_GUARDIAN_ALREADY_DEFINED 102
#define IB_GUARDIAN_RUNNING 103 #define IB_GUARDIAN_RUNNING 103
#endif /* _UTILITIES_INSTALL_NT_H_ */ #endif /* _UTILITIES_INSTALL_NT_H_ */

View File

@ -1,6 +1,6 @@
/* /*
* PROGRAM: Windows NT registry installation program * PROGRAM: Windows NT registry installation program
* MODULE: install_reg.cpp * MODULE: install_reg.cpp
* DESCRIPTION: Registry installation program * DESCRIPTION: Registry installation program
* *
* The contents of this file are subject to the Interbase Public * The contents of this file are subject to the Interbase Public
@ -33,15 +33,17 @@
static USHORT reg_error(SLONG, TEXT *, HKEY); static USHORT reg_error(SLONG, TEXT *, HKEY);
static void usage(void); static void usage(void);
static struct { static struct
{
TEXT *name; TEXT *name;
USHORT abbrev; USHORT abbrev;
USHORT code; USHORT code;
} commands[] = { } commands[] =
{
{"INSTALL", 1, COMMAND_INSTALL}, {"INSTALL", 1, COMMAND_INSTALL},
{"REMOVE", 1, COMMAND_REMOVE}, {"REMOVE", 1, COMMAND_REMOVE},
{NULL, 0, 0} {NULL, 0, 0}
}; };
int CLIB_ROUTINE main( int argc, char **argv) int CLIB_ROUTINE main( int argc, char **argv)
@ -56,73 +58,91 @@ int CLIB_ROUTINE main( int argc, char **argv)
* Install or remove InterBase. * Install or remove InterBase.
* *
**************************************/ **************************************/
TEXT **end, *p, *q, *cmd, *directory; TEXT **end, *p, *q, *cmd;
TEXT directory[MAXPATHLEN];
USHORT sw_command; USHORT sw_command;
bool sw_version; bool sw_version;
USHORT i, ret; USHORT i, ret, len;
HKEY hkey_node; HKEY hkey_node;
directory = NULL;
sw_command = COMMAND_NONE; sw_command = COMMAND_NONE;
sw_version = false; sw_version = false;
// Let's get the root directory from the instance path of this program.
// argv[0] is only _mostly_ guaranteed to give this info,
// so we GetModuleFileName()
len = GetModuleFileName(NULL, directory, sizeof(directory));
if (len == 0)
return reg_error(GetLastError(), "GetModuleFileName", NULL);
// Get to the last '\' (this one precedes the filename part). There is
// always one after a call to GetModuleFileName().
p = directory + len;
do {--p;} while (*p != '\\');
// Get to the previous '\' (this one should precede the supposed 'bin\\' part).
// There is always an additional '\' OR a ':'.
do {--p;} while (*p != '\\' && *p != ':');
*p = '\0';
end = argv + argc; end = argv + argc;
while (++argv < end) while (++argv < end)
{
if (**argv != '-') { if (**argv != '-') {
for (i = 0; cmd = commands[i].name; i++) { for (i = 0; cmd = commands[i].name; i++)
{
for (p = *argv, q = cmd; *p && UPPER(*p) == *q; p++, q++); for (p = *argv, q = cmd; *p && UPPER(*p) == *q; p++, q++);
if (!*p && commands[i].abbrev <= (USHORT) (q - cmd)) if (!*p && commands[i].abbrev <= (USHORT) (q - cmd))
break; break;
} }
if (!cmd) { if (!cmd)
{
ib_printf("Unknown command \"%s\"\n", *argv); ib_printf("Unknown command \"%s\"\n", *argv);
usage(); usage();
} }
sw_command = commands[i].code; sw_command = commands[i].code;
if (sw_command == COMMAND_INSTALL && ++argv < end)
directory = *argv;
} }
else { else
{
p = *argv + 1; p = *argv + 1;
switch (UPPER(*p)) { switch (UPPER(*p))
case 'Z': {
case 'Z':
sw_version = true; sw_version = true;
break; break;
default: default:
ib_printf("Unknown switch \"%s\"\n", p); ib_printf("Unknown switch \"%s\"\n", p);
usage(); usage();
} }
} }
}
if (sw_version) if (sw_version)
ib_printf("install version %s\n", GDS_VERSION); ib_printf("install version %s\n", GDS_VERSION);
if (sw_command == COMMAND_NONE || if (sw_command == COMMAND_NONE)
(!directory && sw_command == COMMAND_INSTALL) ||
(directory && sw_command != COMMAND_INSTALL))
usage(); usage();
hkey_node = HKEY_LOCAL_MACHINE; hkey_node = HKEY_LOCAL_MACHINE;
switch (sw_command) { switch (sw_command)
case COMMAND_INSTALL: {
ret = REGISTRY_install(hkey_node, directory, reg_error); case COMMAND_INSTALL:
if (ret != FB_SUCCESS) ret = REGISTRY_install(hkey_node, directory, reg_error);
ib_printf ("Firebird has not been installed in the registry.\n"); if (ret != FB_SUCCESS)
else ib_printf ("Firebird has not been installed in the registry.\n");
ib_printf else
("Firebird has been successfully installed in the registry.\n"); ib_printf("Firebird has been successfully installed in the registry.\n");
break; break;
case COMMAND_REMOVE: case COMMAND_REMOVE:
ret = REGISTRY_remove(hkey_node, false, reg_error); ret = REGISTRY_remove(hkey_node, false, reg_error);
if (ret != FB_SUCCESS) if (ret != FB_SUCCESS)
ib_printf("Firebird has not been deleted from the registry.\n"); ib_printf("Firebird has not been deleted from the registry.\n");
else else
ib_printf ib_printf("Firebird has been successfully deleted from the registry.\n");
("Firebird has been successfully deleted from the registry.\n"); break;
break;
} }
if (hkey_node != HKEY_LOCAL_MACHINE) if (hkey_node != HKEY_LOCAL_MACHINE)
@ -131,7 +151,6 @@ int CLIB_ROUTINE main( int argc, char **argv)
return (ret == FB_SUCCESS) ? FINI_OK : FINI_ERROR; return (ret == FB_SUCCESS) ? FINI_OK : FINI_ERROR;
} }
static USHORT reg_error( SLONG status, TEXT * string, HKEY hkey) static USHORT reg_error( SLONG status, TEXT * string, HKEY hkey)
{ {
/************************************** /**************************************
@ -150,23 +169,32 @@ static USHORT reg_error( SLONG status, TEXT * string, HKEY hkey)
if (hkey != NULL && hkey != HKEY_LOCAL_MACHINE) if (hkey != NULL && hkey != HKEY_LOCAL_MACHINE)
RegCloseKey(hkey); RegCloseKey(hkey);
ib_printf("Error occurred during \"%s\"\n", string); if (status == 0)
{
if (!(l = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, // Allows to report non System errors
NULL, ib_printf("%s\n", string);
status, }
GetUserDefaultLangID(),
buffer,
sizeof(buffer),
NULL)))
ib_printf("Windows NT error %"SLONGFORMAT"\n", status);
else else
ib_printf("%s\n", buffer); {
ib_printf("Error occurred during \"%s\"\n", string);
if (!(l = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
status,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buffer,
sizeof(buffer),
NULL)))
{
ib_printf("Windows NT error %"SLONGFORMAT"\n", status);
}
else
ib_printf("%s\n", buffer);
}
return FB_FAILURE; return FB_FAILURE;
} }
static void usage(void) static void usage(void)
{ {
/************************************** /**************************************
@ -179,9 +207,13 @@ static void usage(void)
* *
**************************************/ **************************************/
ib_printf("Usage:\n"); ib_printf("\nUsage:\n");
ib_printf(" instreg {install Firebird_directory} [-z]\n"); ib_printf(" instreg install\n");
ib_printf(" {remove }\n"); ib_printf(" remove\n\n");
ib_printf(" This utility should be located and run from the 'bin' directory\n");
ib_printf(" of your Firebird installation.\n\n");
ib_printf(" '*' denotes the default values\n");
ib_printf(" '-z' can be used with any other option, prints version\n");
exit(FINI_OK); exit(FINI_OK);
} }

View File

@ -1,6 +1,6 @@
/* /*
* PROGRAM: Windows NT service control panel installation program * PROGRAM: Windows NT service control panel installation program
* MODULE: install_svc.c * MODULE: install_svc.cpp
* DESCRIPTION: Service control panel installation program * DESCRIPTION: Service control panel installation program
* *
* The contents of this file are subject to the Interbase Public * The contents of this file are subject to the Interbase Public
@ -35,23 +35,25 @@
#define REMOTE_EXECUTABLE \ #define REMOTE_EXECUTABLE \
((sw_arch == ARCH_SS) ? REMOTE_SS_EXECUTABLE : REMOTE_CS_EXECUTABLE) ((sw_arch == ARCH_SS) ? REMOTE_SS_EXECUTABLE : REMOTE_CS_EXECUTABLE)
static void svc_query(TEXT*, TEXT*, SC_HANDLE manager);
static USHORT svc_error(SLONG, TEXT *, SC_HANDLE); static USHORT svc_error(SLONG, TEXT *, SC_HANDLE);
static void usage(void); static void usage(void);
static struct { static struct
{
TEXT *name; TEXT *name;
USHORT abbrev; USHORT abbrev;
USHORT code; USHORT code;
} commands[] = { } commands[] =
{"CONFIGURE", 1, COMMAND_CONFIG}, {
{"INSTALL", 1, COMMAND_INSTALL}, {"INSTALL", 1, COMMAND_INSTALL},
{"REMOVE", 1, COMMAND_REMOVE}, {"REMOVE", 1, COMMAND_REMOVE},
{"START", 3, COMMAND_START}, {"START", 3, COMMAND_START},
{"STOP", 3, COMMAND_STOP}, {"STOP", 3, COMMAND_STOP},
{"QUERY", 1, COMMAND_QUERY},
{NULL, 0, 0} {NULL, 0, 0}
}; };
int CLIB_ROUTINE main( int argc, char **argv) int CLIB_ROUTINE main( int argc, char **argv)
{ {
/************************************** /**************************************
@ -64,263 +66,237 @@ int CLIB_ROUTINE main( int argc, char **argv)
* Install or remove a Firebird service. * Install or remove a Firebird service.
* *
**************************************/ **************************************/
TEXT **end, *p, *q, *cmd, *directory; TEXT **end, *p, *q, *cmd;
TEXT directory[MAXPATHLEN];
USHORT sw_command, sw_startup, sw_mode, sw_guardian, sw_arch; USHORT sw_command, sw_startup, sw_mode, sw_guardian, sw_arch;
bool sw_version; bool sw_version;
USHORT i, status; USHORT i, status, len;
SC_HANDLE manager, service; SC_HANDLE manager, service;
directory = NULL;
sw_command = COMMAND_NONE; sw_command = COMMAND_NONE;
sw_version = false; sw_version = false;
sw_startup = STARTUP_DEMAND; sw_startup = STARTUP_AUTO;
sw_mode = DEFAULT_CLIENT; sw_mode = DEFAULT_PRIORITY;
sw_guardian = NO_GUARDIAN; sw_guardian = NO_GUARDIAN;
sw_arch = ARCH_SS; sw_arch = ARCH_SS;
TEXT *username = 0; TEXT *username = 0;
TEXT *password = 0; TEXT *password = 0;
// Let's get the root directory from the instance path of this program.
// argv[0] is only _mostly_ guaranteed to give this info,
// so we GetModuleFileName()
len = GetModuleFileName(NULL, directory, sizeof(directory));
if (len == 0)
return svc_error(GetLastError(), "GetModuleFileName", NULL);
// Get to the last '\' (this one precedes the filename part). There is
// always one after a call to GetModuleFileName().
p = directory + len;
do {--p;} while (*p != '\\');
// Get to the previous '\' (this one should precede the supposed 'bin\\' part).
// There is always an additional '\' OR a ':'.
do {--p;} while (*p != '\\' && *p != ':');
*p = '\0';
end = argv + argc; end = argv + argc;
while (++argv < end) while (++argv < end)
if (**argv != '-') { {
for (i = 0; cmd = commands[i].name; i++) { if (**argv != '-')
{
for (i = 0; cmd = commands[i].name; i++)
{
for (p = *argv, q = cmd; *p && UPPER(*p) == *q; p++, q++); for (p = *argv, q = cmd; *p && UPPER(*p) == *q; p++, q++);
if (!*p && commands[i].abbrev <= (USHORT) (q - cmd)) if (!*p && commands[i].abbrev <= (USHORT) (q - cmd))
break; break;
} }
if (!cmd) { if (!cmd)
{
ib_printf("Unknown command \"%s\"\n", *argv); ib_printf("Unknown command \"%s\"\n", *argv);
usage(); usage();
} }
sw_command = commands[i].code; sw_command = commands[i].code;
if (sw_command == COMMAND_INSTALL && ++argv < end)
directory = *argv;
} }
else { else
{
p = *argv + 1; p = *argv + 1;
switch (UPPER(*p)) { switch (UPPER(*p))
case 'A': {
sw_startup = STARTUP_AUTO; case 'A':
break; sw_startup = STARTUP_AUTO;
break;
case 'D': case 'D':
sw_startup = STARTUP_DEMAND; sw_startup = STARTUP_DEMAND;
break; break;
/* Disable server sw_mode service options /*
case 'R':
case 'M': sw_mode = NORMAL_PRIORITY;
sw_mode = MULTI_CLIENT; break;
break; */
case 'B':
sw_mode = HIGH_PRIORITY;
break;
case 'S': case 'Z':
sw_mode = SINGLE_CLIENT; sw_version = true;
break; break;
*/
case 'R':
sw_mode = NORMAL_PRIORITY;
break;
case 'B': case 'G':
sw_mode = HIGH_PRIORITY; sw_guardian = USE_GUARDIAN;
break; break;
case 'Z': case 'S':
sw_version = true; sw_arch = ARCH_SS;
break; break;
case 'G': case 'C':
sw_guardian = USE_GUARDIAN; sw_arch = ARCH_CS;
break; break;
case 'S': case 'L':
sw_arch = ARCH_SS; if (++argv < end)
break; username = *argv;
if (++argv < end)
case 'C': {
sw_arch = ARCH_CS; if (**argv == '-') // Next switch
break; --argv;
else
case 'L': password = *argv;
if (++argv < end) {
username = *argv;
}
if (++argv < end) {
if (**argv == '-') { // Next switch
--argv;
} }
else { break;
password = *argv;
}
}
break;
default: default:
ib_printf("Unknown switch \"%s\"\n", p); ib_printf("Unknown switch \"%s\"\n", p);
usage(); usage();
} }
} }
}
if (sw_version) if (sw_version)
ib_printf("install_svc version %s\n", GDS_VERSION); ib_printf("install_svc version %s\n", GDS_VERSION);
if (sw_command == COMMAND_NONE || if (sw_command == COMMAND_NONE ||
(!directory && sw_command == COMMAND_INSTALL) ||
(directory && sw_command != COMMAND_INSTALL) ||
(username && sw_command != COMMAND_INSTALL)) (username && sw_command != COMMAND_INSTALL))
{
usage(); usage();
}
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (manager == NULL) { if (manager == NULL)
{
svc_error(GetLastError(), "OpenSCManager", NULL); svc_error(GetLastError(), "OpenSCManager", NULL);
exit(FINI_ERROR); exit(FINI_ERROR);
} }
switch (sw_command) { switch (sw_command)
case COMMAND_CONFIG: {
status = SERVICES_config(manager, REMOTE_SERVICE, REMOTE_DISPLAY_NAME, case COMMAND_INSTALL:
sw_mode, svc_error); /* First, lets do the guardian, if it has been specified */
if (status == FB_SUCCESS) if (sw_guardian)
ib_printf("Service \"%s\" successfully configured.\n", {
REMOTE_DISPLAY_NAME); status = SERVICES_install(manager, ISCGUARD_SERVICE,
else ISCGUARD_DISPLAY_NAME, ISCGUARD_EXECUTABLE, directory,
ib_printf("Service \"%s\" not configured.\n", NULL, sw_startup, 0, 0, svc_error);
REMOTE_DISPLAY_NAME); if (status == FB_SUCCESS)
break; ib_printf("Service \"%s\" successfully created.\n", ISCGUARD_DISPLAY_NAME);
case COMMAND_INSTALL: /* Set sw_startup to manual in preparation for install the service */
/* First, lets do the guardian, if it has been specified */ sw_startup = STARTUP_DEMAND;
if (sw_guardian) { }
status =
SERVICES_install(manager, ISCGUARD_SERVICE, ISCGUARD_DISPLAY_NAME, /* do the install of the server */
ISCGUARD_EXECUTABLE, directory, NULL, sw_startup, status = SERVICES_install(manager, REMOTE_SERVICE,
username, password, svc_error); REMOTE_DISPLAY_NAME, const_cast<char*>REMOTE_EXECUTABLE,
directory, NULL, sw_startup, username, password, svc_error);
if (status == FB_SUCCESS) if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully created.\n", ib_printf("Service \"%s\" successfully created.\n", REMOTE_DISPLAY_NAME);
ISCGUARD_DISPLAY_NAME); break;
else if (status == IB_SERVICE_ALREADY_DEFINED)
svc_error(GetLastError(), "CreateService", NULL);
else
ib_printf("Service \"%s\" not created.\n", ISCGUARD_DISPLAY_NAME);
/* Set sw_startup to manual in preparation for install the service */ case COMMAND_REMOVE:
sw_startup = STARTUP_DEMAND; service = OpenService(manager, ISCGUARD_SERVICE, SERVICE_ALL_ACCESS);
} if (service)
{
CloseServiceHandle(service);
status = SERVICES_remove(manager, ISCGUARD_SERVICE,
ISCGUARD_DISPLAY_NAME, svc_error);
if (status == FB_SUCCESS)
{
ib_printf("Service \"%s\" successfully deleted.\n", ISCGUARD_DISPLAY_NAME);
}
else if (status == IB_SERVICE_RUNNING)
{
ib_printf("Service \"%s\" not deleted.\n", ISCGUARD_DISPLAY_NAME);
ib_printf("You must stop it before attempting to delete it.\n\n");
}
}
/* do the install of the server */ service = OpenService(manager, REMOTE_SERVICE, SERVICE_ALL_ACCESS);
status = if (service)
SERVICES_install(manager, REMOTE_SERVICE, REMOTE_DISPLAY_NAME, {
const_cast<char*>REMOTE_EXECUTABLE, directory, NULL, sw_startup, CloseServiceHandle(service);
username, password, svc_error); status = SERVICES_remove(manager, REMOTE_SERVICE, REMOTE_DISPLAY_NAME,
if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully created.\n",
REMOTE_DISPLAY_NAME);
else if (status == IB_SERVICE_ALREADY_DEFINED)
svc_error(GetLastError(), "CreateService", NULL);
else
ib_printf("Service \"%s\" not created.\n", REMOTE_DISPLAY_NAME);
break;
case COMMAND_REMOVE:
if (sw_guardian) {
status = SERVICES_remove(manager, ISCGUARD_SERVICE, ISCGUARD_DISPLAY_NAME,
svc_error);
if (status == FB_SUCCESS) {
ib_printf("Service \"%s\" successfully deleted.\n", ISCGUARD_DISPLAY_NAME);
status = SERVICES_delete(manager, ISCGUARD_SERVICE, ISCGUARD_DISPLAY_NAME,
svc_error); svc_error);
if (status == FB_SUCCESS) if (status == FB_SUCCESS)
ib_printf("Service configuration for \"%s\" successfully re-initialized.\n", {
ISCGUARD_DISPLAY_NAME); ib_printf("Service \"%s\" successfully deleted.\n", REMOTE_DISPLAY_NAME);
else }
ib_printf("Service configuration for \"%s\" not re-initialized.\n", else if (status == IB_SERVICE_RUNNING)
ISCGUARD_DISPLAY_NAME); {
} ib_printf("Service \"%s\" not deleted.\n", REMOTE_DISPLAY_NAME);
else if (status == IB_SERVICE_RUNNING) { ib_printf("You must stop it before attempting to delete it.\n\n");
ib_printf("Service \"%s\" not deleted. You must stop it before\n", }
ISCGUARD_DISPLAY_NAME); }
ib_printf("attempting to delete it.\n"); break;
}
else
ib_printf ("Service \"%s\" not deleted.\n", ISCGUARD_DISPLAY_NAME);
}
status = SERVICES_remove(manager, REMOTE_SERVICE, REMOTE_DISPLAY_NAME, case COMMAND_START:
svc_error); /* Test for use of the guardian. If so, start the guardian else start the server */
if (status == FB_SUCCESS) { service = OpenService(manager, ISCGUARD_SERVICE, SERVICE_ALL_ACCESS);
ib_printf("Service \"%s\" successfully deleted.\n", REMOTE_DISPLAY_NAME); if (service)
status = SERVICES_delete(manager, REMOTE_SERVICE, REMOTE_DISPLAY_NAME, {
svc_error); CloseServiceHandle(service);
status = SERVICES_start(manager, ISCGUARD_SERVICE, ISCGUARD_DISPLAY_NAME,
sw_mode, svc_error);
if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully started.\n", ISCGUARD_DISPLAY_NAME);
}
else
{
CloseServiceHandle(service);
status = SERVICES_start(manager, REMOTE_SERVICE, REMOTE_DISPLAY_NAME,
sw_mode, svc_error);
if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully started.\n", REMOTE_DISPLAY_NAME);
}
break;
if (status == FB_SUCCESS) case COMMAND_STOP:
ib_printf("Service configuration for \"%s\" successfully re-initialized.\n", /* Test for use of the guardian. If so, stop the guardian else stop the server */
REMOTE_DISPLAY_NAME); service = OpenService(manager, ISCGUARD_SERVICE, SERVICE_ALL_ACCESS);
if (service)
{
CloseServiceHandle(service);
status = SERVICES_stop(manager, ISCGUARD_SERVICE,
ISCGUARD_DISPLAY_NAME, svc_error);
if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully stopped.\n", ISCGUARD_DISPLAY_NAME);
}
else else
ib_printf("Service configuration for \"%s\" not re-initialized.\n", {
REMOTE_DISPLAY_NAME); CloseServiceHandle(service);
} status = SERVICES_stop(manager, REMOTE_SERVICE,
else if (status == IB_SERVICE_RUNNING) { REMOTE_DISPLAY_NAME, svc_error);
ib_printf("Service \"%s\" not deleted. You must stop it before\n", if (status == FB_SUCCESS)
REMOTE_DISPLAY_NAME); ib_printf("Service \"%s\" successfully stopped.\n", REMOTE_DISPLAY_NAME);
ib_printf("attempting to delete it.\n"); }
} break;
else
ib_printf("Service \"%s\" not deleted.\n", REMOTE_DISPLAY_NAME);
break;
case COMMAND_START: case COMMAND_QUERY:
/* Test for use of the guardian. If so, start the guardian else start the server */ svc_query(ISCGUARD_SERVICE, ISCGUARD_DISPLAY_NAME, manager);
// dimitr: this line says nothing about whether the guardian is installed or not svc_query(REMOTE_SERVICE, REMOTE_DISPLAY_NAME, manager);
// if (Config::getGuardianOption() == 1) { break;
service = OpenService(manager, ISCGUARD_SERVICE, SERVICE_ALL_ACCESS);
if (service) {
CloseServiceHandle(service);
status = SERVICES_start(manager, ISCGUARD_SERVICE, ISCGUARD_DISPLAY_NAME,
sw_mode, svc_error);
if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully started.\n",
ISCGUARD_DISPLAY_NAME);
else
ib_printf("Service \"%s\" not started.\n", ISCGUARD_DISPLAY_NAME);
}
else {
status = SERVICES_start(manager, REMOTE_SERVICE, REMOTE_DISPLAY_NAME,
sw_mode, svc_error);
if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully started.\n",
REMOTE_DISPLAY_NAME);
else
ib_printf("Service \"%s\" not started.\n", REMOTE_DISPLAY_NAME);
}
break;
case COMMAND_STOP:
/* Test for use of the guardian. If so, stop the guardian else stop the server */
// dimitr: this line says nothing about whether the guardian is installed or not
// if (Config::getGuardianOption() == 1) {
service = OpenService(manager, ISCGUARD_SERVICE, SERVICE_ALL_ACCESS);
if (service) {
CloseServiceHandle(service);
status = SERVICES_stop(manager, ISCGUARD_SERVICE, ISCGUARD_DISPLAY_NAME,
svc_error);
if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully stopped.\n",
ISCGUARD_DISPLAY_NAME);
else
ib_printf("Service \"%s\" not stopped.\n", ISCGUARD_DISPLAY_NAME);
}
else {
status = SERVICES_stop(manager, REMOTE_SERVICE, REMOTE_DISPLAY_NAME,
svc_error);
if (status == FB_SUCCESS)
ib_printf("Service \"%s\" successfully stopped.\n",
REMOTE_DISPLAY_NAME);
else
ib_printf("Service \"%s\" not stopped.\n", REMOTE_DISPLAY_NAME);
}
break;
} }
CloseServiceHandle(manager); CloseServiceHandle(manager);
@ -328,6 +304,79 @@ int CLIB_ROUTINE main( int argc, char **argv)
return (status == FB_SUCCESS) ? FINI_OK : FINI_ERROR; return (status == FB_SUCCESS) ? FINI_OK : FINI_ERROR;
} }
static void svc_query(TEXT* name, TEXT* display_name, SC_HANDLE manager)
{
/**************************************
*
* s v c _ q u e r y
*
**************************************
*
* Functional description
* Report (print) the status and configuration of a service.
*
**************************************/
SC_HANDLE service;
SERVICE_STATUS service_status;
QUERY_SERVICE_CONFIG* qsc;
ULONG uSize;
if (manager == NULL) return;
service = OpenService(manager, name, SERVICE_ALL_ACCESS);
if (service)
{
ib_printf("\n%s IS installed.\n", display_name);
if (QueryServiceStatus(service, &service_status))
{
ib_printf(" Status : ");
switch (service_status.dwCurrentState)
{
case SERVICE_STOPPED : ib_printf("stopped\n"); break;
case SERVICE_START_PENDING : ib_printf("starting\n"); break;
case SERVICE_STOP_PENDING : ib_printf("stopping\n"); break;
case SERVICE_RUNNING : ib_printf("running\n"); break;
default: ib_printf("unknown state\n");
}
}
else
svc_error(GetLastError(), "QueryServiceStatus", NULL);
QueryServiceConfig(service, NULL, 0, &uSize);
qsc = (QUERY_SERVICE_CONFIG*) new UCHAR[uSize];
if (qsc && QueryServiceConfig(service, qsc, uSize, &uSize))
{
ib_printf(" Path : %s\n", qsc->lpBinaryPathName);
ib_printf(" Startup : ");
switch (qsc->dwStartType)
{
case SERVICE_AUTO_START : ib_printf("automatic\n"); break;
case SERVICE_DEMAND_START : ib_printf("manual\n"); break;
case SERVICE_DISABLED : ib_printf("disabled\n"); break;
default : ib_printf("invalid setting\n");
}
if (! qsc->lpServiceStartName)
ib_printf(" Run as : LocalSystem");
else
ib_printf(" Run as : %s", qsc->lpServiceStartName);
if (qsc->dwServiceType & SERVICE_INTERACTIVE_PROCESS)
ib_printf(" (Interactive)\n");
else
ib_printf("\n");
}
else
svc_error(GetLastError(), "QueryServiceConfig", NULL);
if (qsc)
delete [] (UCHAR*)qsc;
CloseServiceHandle(service);
}
else
ib_printf("\n%s is NOT installed.\n", display_name);
return;
}
static USHORT svc_error( SLONG status, TEXT * string, SC_HANDLE service) static USHORT svc_error( SLONG status, TEXT * string, SC_HANDLE service)
{ {
@ -347,23 +396,31 @@ static USHORT svc_error( SLONG status, TEXT * string, SC_HANDLE service)
if (service != NULL) if (service != NULL)
CloseServiceHandle(service); CloseServiceHandle(service);
ib_printf("Error occurred during \"%s\"\n", string); if (status == 0)
{
if (!(l = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, // Allows to report non System errors
NULL, ib_printf("%s\n", string);
status, }
GetUserDefaultLangID(),
buffer,
sizeof(buffer),
NULL)))
ib_printf("Windows NT error %"SLONGFORMAT"\n", status);
else else
ib_printf("%s\n", buffer); {
ib_printf("Error occurred during \"%s\".\n", string);
if (!(l = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
status,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buffer,
sizeof(buffer),
NULL)))
{
ib_printf("Windows NT error %"SLONGFORMAT"\n", status);
}
else
ib_printf("%s", buffer); // '\n' is included in system messages
}
return FB_FAILURE; return FB_FAILURE;
} }
static void usage(void) static void usage(void)
{ {
/************************************** /**************************************
@ -375,18 +432,19 @@ static void usage(void)
* Functional description * Functional description
* *
**************************************/ **************************************/
ib_printf("\nUsage:\n");
ib_printf("Usage:\n"); ib_printf(" instsvc install [ -superserver* | -classic ]\n");
ib_printf ib_printf(" [ -auto* | -demand ]\n");
(" instsvc {install Firebird_directory [-auto | -demand] [-superserver | -classic] } [-guardian] [-login username password] [-z]\n"); ib_printf(" [ -guardian ]\n");
ib_printf ib_printf(" [ -login username password ]\n\n");
(" {remove } [-guardian] \n"); ib_printf(" start [ -boostpriority ]\n");
ib_printf ib_printf(" stop\n");
(" {configure [-boostpriority | -regularpriority] }\n"); ib_printf(" query\n");
ib_printf ib_printf(" remove\n\n");
(" {start [-boostpriority | -regularpriority] }\n"); ib_printf(" This utility should be located and run from the 'bin' directory\n");
ib_printf ib_printf(" of your Firebird installation.\n\n");
(" {stop }\n"); ib_printf(" '*' denotes the default values\n");
ib_printf(" '-z' can be used with any other option, prints version\n");
exit(FINI_OK); exit(FINI_OK);
} }

View File

@ -52,7 +52,7 @@ USHORT REGISTRY_install(HKEY hkey_node,
**************************************/ **************************************/
HKEY hkey_kit; HKEY hkey_kit;
DWORD disp; DWORD disp;
TEXT path_name[260], *p; TEXT path_name[MAXPATHLEN], *p;
USHORT len; USHORT len;
SLONG status; SLONG status;
@ -176,7 +176,7 @@ static USHORT remove_subkeys(
* Remove all sub-keys of an InterBase key from the registry. * Remove all sub-keys of an InterBase key from the registry.
* *
**************************************/ **************************************/
TEXT *sub_key, buffer[260], *p; TEXT *sub_key, buffer[MAXPATHLEN], *p;
DWORD n_sub_keys, max_sub_key, sub_key_len, buf_len, i, status; DWORD n_sub_keys, max_sub_key, sub_key_len, buf_len, i, status;
FILETIME last_write_time; FILETIME last_write_time;
HKEY hkey_sub; HKEY hkey_sub;

View File

@ -24,15 +24,6 @@
#ifndef _UTILITIES_SERVI_PROTO_H_ #ifndef _UTILITIES_SERVI_PROTO_H_
#define _UTILITIES_SERVI_PROTO_H_ #define _UTILITIES_SERVI_PROTO_H_
extern USHORT SERVICES_config (SC_HANDLE,
TEXT *,
TEXT *,
USHORT,
USHORT (*)(SLONG, TEXT *, SC_HANDLE));
extern USHORT SERVICES_delete (SC_HANDLE,
TEXT *,
TEXT *,
USHORT (*)(SLONG, TEXT *, SC_HANDLE));
extern USHORT SERVICES_install (SC_HANDLE manager, extern USHORT SERVICES_install (SC_HANDLE manager,
TEXT *service_name, TEXT *service_name,
TEXT *display_name, TEXT *display_name,

View File

@ -27,6 +27,7 @@
#include "firebird.h" #include "firebird.h"
#include "../jrd/ib_stdio.h" #include "../jrd/ib_stdio.h"
#include <windows.h> #include <windows.h>
#include <ntsecapi.h>
#include "../jrd/common.h" #include "../jrd/common.h"
#include "../jrd/license.h" #include "../jrd/license.h"
#include "../utilities/install/install_nt.h" #include "../utilities/install/install_nt.h"
@ -36,99 +37,7 @@
/* Defines */ /* Defines */
#define RUNAS_SERVICE " -s" #define RUNAS_SERVICE " -s"
static void grant_logon_right(TEXT* account);
USHORT SERVICES_config(SC_HANDLE manager,
TEXT * service_name,
TEXT * display_name,
USHORT sw_mode,
USHORT(*err_handler)(SLONG, TEXT *, SC_HANDLE))
{
/**************************************
*
* S E R V I C E S _ c o n f i g
*
**************************************
*
* Functional description
* Configure an installed service.
*
**************************************/
HKEY hkey;
SLONG status;
TEXT *mode;
if ((status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
REG_KEY_ROOT_CUR_VER,
0, KEY_WRITE, &hkey)) != ERROR_SUCCESS) {
return (*err_handler) (status, "RegOpenKeyEx", NULL);
}
switch (sw_mode) {
case DEFAULT_CLIENT:
mode = "";
break;
case NORMAL_PRIORITY:
mode = "-r";
break;
case HIGH_PRIORITY:
mode = "-b";
break;
}
if ((status = RegSetValueEx(hkey, "DefaultClientMode", 0,
REG_SZ, reinterpret_cast<UCHAR*>(mode),
(DWORD) (strlen(mode) + 1))) !=
ERROR_SUCCESS) {
RegCloseKey(hkey);
return (*err_handler) (status, "RegSetValueEx", NULL);
}
RegCloseKey(hkey);
return FB_SUCCESS;
}
USHORT SERVICES_delete(SC_HANDLE manager,
TEXT * service_name,
TEXT * display_name,
USHORT(*err_handler)(SLONG, TEXT *, SC_HANDLE))
{
/**************************************
*
* S E R V I C E S _ d e l e t e
*
**************************************
*
* Functional description
* delete installed service param from registry.
*
**************************************/
HKEY hkey;
SLONG status;
TEXT *mode;
mode = "";
if ((status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
REG_KEY_ROOT_CUR_VER,
0, KEY_WRITE, &hkey)) != ERROR_SUCCESS) {
return (*err_handler) (status, "RegOpenKeyEx", NULL);
}
if ((status = RegSetValueEx(hkey, "DefaultClientMode", 0,
REG_SZ, reinterpret_cast<UCHAR*>(mode),
(DWORD) (strlen(mode) + 1))) !=
ERROR_SUCCESS) {
RegCloseKey(hkey);
return (*err_handler) (status, "RegSetValueEx", NULL);
}
RegCloseKey(hkey);
return FB_SUCCESS;
}
USHORT SERVICES_install(SC_HANDLE manager, USHORT SERVICES_install(SC_HANDLE manager,
TEXT * service_name, TEXT * service_name,
@ -152,28 +61,48 @@ USHORT SERVICES_install(SC_HANDLE manager,
* *
**************************************/ **************************************/
SC_HANDLE service; SC_HANDLE service;
TEXT path_name[260]; TEXT path_name[MAXPATHLEN];
TEXT full_user_name[128];
USHORT len; USHORT len;
DWORD errnum; DWORD errnum;
DWORD dwServiceType; DWORD dwServiceType;
strcpy(path_name, directory); strcpy(path_name, directory);
len = strlen(path_name); len = strlen(path_name);
if (len && path_name[len - 1] != '/' && path_name[len - 1] != '\\') { if (len && path_name[len - 1] != '/' && path_name[len - 1] != '\\')
{
path_name[len++] = '\\'; path_name[len++] = '\\';
path_name[len] = 0; path_name[len] = 0;
} }
strcpy(path_name + len, executable); strcpy(path_name + len, executable);
strcat(path_name, ".exe");
strcat(path_name, RUNAS_SERVICE); strcat(path_name, RUNAS_SERVICE);
dwServiceType = SERVICE_WIN32_OWN_PROCESS; dwServiceType = SERVICE_WIN32_OWN_PROCESS;
if (nt_user_name) { if (nt_user_name != 0)
if (! nt_user_password) {
TEXT *p = nt_user_name;
while (*p != '\0' && *p != '\\') ++p;
if (*p == '\0')
{
DWORD cnlen = sizeof(full_user_name);
GetComputerName(full_user_name, &cnlen);
strcat(full_user_name, "\\");
strncat(full_user_name, nt_user_name, sizeof(full_user_name) - (cnlen + 1));
}
else
strncpy(full_user_name, nt_user_name, sizeof(full_user_name));
full_user_name[sizeof(full_user_name) -1] = '\0';
if (nt_user_password == 0)
nt_user_password = ""; nt_user_password = "";
nt_user_name = full_user_name;
// Let's grant "Logon as a Service" right to the -login user
grant_logon_right(nt_user_name);
} }
else { else
dwServiceType |= SERVICE_INTERACTIVE_PROCESS; dwServiceType |= SERVICE_INTERACTIVE_PROCESS;
}
service = CreateService(manager, service = CreateService(manager,
service_name, service_name,
@ -186,7 +115,8 @@ USHORT SERVICES_install(SC_HANDLE manager,
path_name, NULL, NULL, dependencies, path_name, NULL, NULL, dependencies,
nt_user_name, nt_user_password); nt_user_name, nt_user_password);
if (service == NULL) { if (service == NULL)
{
errnum = GetLastError(); errnum = GetLastError();
if (errnum == ERROR_DUP_NAME || errnum == ERROR_SERVICE_EXISTS) if (errnum == ERROR_DUP_NAME || errnum == ERROR_SERVICE_EXISTS)
return IB_SERVICE_ALREADY_DEFINED; return IB_SERVICE_ALREADY_DEFINED;
@ -222,20 +152,17 @@ USHORT SERVICES_remove(SC_HANDLE manager,
if (service == NULL) if (service == NULL)
return (*err_handler) (GetLastError(), "OpenService", NULL); return (*err_handler) (GetLastError(), "OpenService", NULL);
if (!QueryServiceStatus(service, &service_status)) { if (!QueryServiceStatus(service, &service_status))
CloseServiceHandle(service);
return (*err_handler) (GetLastError(), "QueryServiceStatus", service); return (*err_handler) (GetLastError(), "QueryServiceStatus", service);
}
if (service_status.dwCurrentState != SERVICE_STOPPED) { if (service_status.dwCurrentState != SERVICE_STOPPED)
{
CloseServiceHandle(service); CloseServiceHandle(service);
return IB_SERVICE_RUNNING; return IB_SERVICE_RUNNING;
} }
if (!DeleteService(service)) { if (!DeleteService(service))
CloseServiceHandle(service);
return (*err_handler) (GetLastError(), "DeleteService", service); return (*err_handler) (GetLastError(), "DeleteService", service);
}
CloseServiceHandle(service); CloseServiceHandle(service);
@ -260,28 +187,49 @@ USHORT SERVICES_start(SC_HANDLE manager,
* *
**************************************/ **************************************/
SC_HANDLE service; SC_HANDLE service;
SERVICE_STATUS service_status;
const TEXT *mode; const TEXT *mode;
DWORD errnum;
service = OpenService(manager, service_name, SERVICE_ALL_ACCESS); service = OpenService(manager, service_name, SERVICE_ALL_ACCESS);
if (service == NULL) if (service == NULL)
return (*err_handler) (GetLastError(), "OpenService", NULL); return (*err_handler) (GetLastError(), "OpenService", NULL);
switch (sw_mode) { switch (sw_mode)
case DEFAULT_CLIENT: {
mode = NULL; case DEFAULT_PRIORITY:
break; mode = NULL;
case NORMAL_PRIORITY: break;
mode = "-r"; case NORMAL_PRIORITY:
break; mode = "-r";
case HIGH_PRIORITY: break;
mode = "-b"; case HIGH_PRIORITY:
break; mode = "-b";
break;
} }
if (!StartService(service, (mode) ? 1 : 0, &mode)) {
if (!StartService(service, (mode) ? 1 : 0, &mode))
{
errnum = GetLastError();
CloseServiceHandle(service); CloseServiceHandle(service);
return (*err_handler) (GetLastError(), "StartService", service); if (errnum == ERROR_SERVICE_ALREADY_RUNNING)
return FB_SUCCESS;
else
return (*err_handler) (errnum, "StartService", NULL);
} }
/* Wait for the service to actually start before returning. */
do
{
if (!QueryServiceStatus(service, &service_status))
return (*err_handler) (GetLastError(), "QueryServiceStatus", service);
Sleep(100); // Don't loop too quickly (would be useless)
}
while (service_status.dwCurrentState == SERVICE_START_PENDING);
if (service_status.dwCurrentState != SERVICE_RUNNING)
return (*err_handler) (0, "Service failed to complete its startup sequence.", service);
CloseServiceHandle(service); CloseServiceHandle(service);
return FB_SUCCESS; return FB_SUCCESS;
@ -311,27 +259,106 @@ USHORT SERVICES_stop(SC_HANDLE manager,
if (service == NULL) if (service == NULL)
return (*err_handler) (GetLastError(), "OpenService", NULL); return (*err_handler) (GetLastError(), "OpenService", NULL);
if (!ControlService(service, SERVICE_CONTROL_STOP, &service_status)) { if (!ControlService(service, SERVICE_CONTROL_STOP, &service_status))
CloseServiceHandle(service); {
errnum = GetLastError(); errnum = GetLastError();
CloseServiceHandle(service);
if (errnum == ERROR_SERVICE_NOT_ACTIVE) if (errnum == ERROR_SERVICE_NOT_ACTIVE)
return FB_SUCCESS; return FB_SUCCESS;
else else
return (*err_handler) (errnum, "ControlService", service); return (*err_handler) (errnum, "ControlService", NULL);
} }
/* Wait for the service to actually stop before returning. */ /* Wait for the service to actually stop before returning. */
do
do { {
if (!QueryServiceStatus(service, &service_status)) { if (!QueryServiceStatus(service, &service_status))
CloseServiceHandle(service); return (*err_handler) (GetLastError(), "QueryServiceStatus", service);
return (*err_handler) (GetLastError(), "QueryServiceStatus", Sleep(100); // Don't loop too quickly (would be useless)
service);
}
} }
while (service_status.dwCurrentState == SERVICE_STOP_PENDING); while (service_status.dwCurrentState == SERVICE_STOP_PENDING);
if (service_status.dwCurrentState != SERVICE_STOPPED)
return (*err_handler) (0, "Service failed to complete its stop sequence", service);
CloseServiceHandle(service); CloseServiceHandle(service);
return FB_SUCCESS; return FB_SUCCESS;
} }
static void grant_logon_right(TEXT* account)
{
/**************************************
*
* g r a n t _ l o g o n _ r i g h t
*
**************************************
*
* Functional description
* Grants the "Log on as a service" right to account.
* This is a Windows NT, 2000, XP, 2003 security thing.
* To run a service under an account other than LocalSystem, the account
* must have this right. To succeed granting the right, the current user
* must be an Administrator.
* This function does not report errors, which will happen if the right
* as been granted already.
* OM - August 2003
*
**************************************/
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
LSA_HANDLE PolicyHandle;
PSID pSid;
DWORD cbSid;
TEXT *pDomain;
DWORD cchDomain;
SID_NAME_USE peUse;
LSA_UNICODE_STRING PrivilegeString;
// Open the policy on the local machine.
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
if (LsaOpenPolicy(NULL, &ObjectAttributes,
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &PolicyHandle)
!= (NTSTATUS)0)
{
return;
}
// Obtain the SID of the user/group. First get required buffer sizes.
cbSid = cchDomain = 0;
LookupAccountName(NULL, account, NULL, &cbSid, NULL, &cchDomain, &peUse);
pSid = (PSID)LocalAlloc(LMEM_ZEROINIT, cbSid);
if (pSid == 0)
{
LsaClose(PolicyHandle);
return;
}
pDomain = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, cchDomain);
if (pDomain == 0)
{
LsaClose(PolicyHandle);
LocalFree(pSid);
return;
}
// Now, really obtain the SID of the user/group.
if (LookupAccountName(NULL, account, pSid, &cbSid,
pDomain, &cchDomain, &peUse) != 0)
{
// Grant the SeServiceLogonRight to users represented by pSid.
PrivilegeString.Buffer = L"SeServiceLogonRight";
PrivilegeString.Length = (USHORT) 19 * sizeof(WCHAR); // 19 : char len of Buffer
PrivilegeString.MaximumLength=(USHORT)(19 + 1) * sizeof(WCHAR);
// No need to check the result.
LsaAddAccountRights(PolicyHandle, pSid, &PrivilegeString, 1);
}
LsaClose(PolicyHandle);
LocalFree(pSid);
LocalFree(pDomain);
return;
}
//
// EOF
//