Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1019 lines
29 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
services.c
Abstract:
Routines to deal with the Windows NT service controller
and service entries in the registry,
Externally exposed routines:
MyCreateService
MyChangeServiceStart
MyChangeServiceConfig
Author:
Ted Miller (tedm) 5-Apr-1995
adapted from legacy\dll\sc.c
Revision History:
Dan Elliott (dane) 14-Aug-2000 Added WaitForScmInitialization().
--*/
#include "setupp.h"
#pragma hdrstop
//
// Constants used in logging specific to this module.
//
PCWSTR szOpenSCManager = L"OpenSCManager";
PCWSTR szCreateService = L"CreateService";
PCWSTR szChangeServiceConfig = L"ChangeServiceConfig";
PCWSTR szOpenService = L"OpenService";
PCWSTR szStartService = L"StartService";
PCWSTR szEnumDependentService= L"EnumDependentService";
PCWSTR szServicesKeyPath = L"SYSTEM\\CurrentControlSet\\Services";
PCWSTR szDependOnService = L"DependOnService";
PCWSTR szServicesToRename = L"ServicesToRename";
BOOL
pSetupWaitForScmInitialization()
/*++
Routine Description:
Wait for services.exe to signal that the Services Control Manager is
running and autostart services have been started.
Arguments:
None.
Return value:
Boolean indicating whether the the SCM was started successfully.
--*/
{
HANDLE hEventHandle;
DWORD WaitStatus;
hEventHandle = OpenEvent( SYNCHRONIZE, FALSE, SC_AUTOSTART_EVENT_NAME );
if( hEventHandle != NULL ) {
SetupDebugPrint1(L"SETUP: Waiting on event %ls \n", SC_AUTOSTART_EVENT_NAME );
WaitStatus = WaitForSingleObject( hEventHandle, INFINITE );
if( WaitStatus != WAIT_FAILED ) {
if( WaitStatus == WAIT_OBJECT_0 ) {
SetupDebugPrint1(L"SETUP: Wait on event %ls completed successfully \n", SC_AUTOSTART_EVENT_NAME );
} else {
SetupDebugPrint2(L"SETUP: Wait on event %ls failed. WaitStatus = %d \n", SC_AUTOSTART_EVENT_NAME, WaitStatus );
}
} else {
DWORD Error;
Error = GetLastError();
SetupDebugPrint2(L"SETUP: Wait on event %ls failed. Error = %d \n", SC_AUTOSTART_EVENT_NAME, Error );
}
CloseHandle( hEventHandle );
}
else {
return FALSE;
}
return (WAIT_OBJECT_0 == WaitStatus);
}
BOOL
MyCreateService(
IN PCWSTR ServiceName,
IN PCWSTR DisplayName, OPTIONAL
IN DWORD ServiceType,
IN DWORD StartType,
IN DWORD ErrorControl,
IN PCWSTR BinaryPathName,
IN PCWSTR LoadOrderGroup, OPTIONAL
IN PWCHAR DependencyList,
IN PCWSTR ServiceStartName, OPTIONAL
IN PCWSTR Password OPTIONAL
)
/*++
Routine Description:
Stub for calling CreateService. If CreateService fails with
the error code indicating that the service already exists, this routine
calls the routine for ChangeServiceConfig to ensure that the
parameters passed in are reflected in the services database.
Arguments:
ServiceName - Name of service
DisplayName - Localizable name of Service or ""
ServiceType - Service type, e.g. SERVICE_KERNEL_DRIVER
StartType - Service Start value, e.g. SERVICE_BOOT_START
ErrorControl - Error control value, e.g. SERVICE_ERROR_NORMAL
BinaryPathName - Full Path of the binary image containing service
LoadOrderGroup - Group name for load ordering or ""
Dependencies - MultiSz list of dependencies for this service. Any dependency
component having + as the first character is a group dependency.
The others are service dependencies.
ServiceStartName - Service Start name (account name in which this service is run).
Password - Password used for starting the service.
Return value:
Boolean value indicating outcome.
--*/
{
SC_HANDLE hSC;
SC_HANDLE hSCService;
DWORD dwTag,dw;
BOOL b;
//
// Open a handle to the service controller manager
//
hSC = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSC == NULL) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_CREATESVC_FAIL,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szOpenSCManager,
GetLastError(),
NULL,NULL);
return(FALSE);
}
//
// Process the optional "" parameters passed in and make them NULL.
//
if(DisplayName && !DisplayName[0]) {
DisplayName = NULL;
}
if(LoadOrderGroup && !LoadOrderGroup[0]) {
LoadOrderGroup = NULL;
}
if(ServiceStartName && !ServiceStartName[0]) {
ServiceStartName = NULL;
}
if(Password && !Password[0]) {
Password = NULL;
}
//
// Create the service.
//
hSCService = CreateService(
hSC,
ServiceName,
DisplayName,
0,
ServiceType,
StartType,
ErrorControl,
BinaryPathName,
LoadOrderGroup,
LoadOrderGroup ? &dwTag : NULL,
DependencyList,
ServiceStartName,
Password
);
//
// If we were unable to create the service, check if the service already
// exists in which case all we need to do is change the configuration
// parameters in the service.
//
if(hSCService) {
//
// Note that we won't do anything with the tag.
//
CloseServiceHandle(hSCService);
b = TRUE;
} else {
if((dw = GetLastError()) == ERROR_SERVICE_EXISTS) {
b = MyChangeServiceConfig(
ServiceName,
ServiceType,
StartType,
ErrorControl,
BinaryPathName,
LoadOrderGroup,
DependencyList,
ServiceStartName,
Password,
DisplayName
);
} else {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_CREATESVC_FAIL,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szCreateService,
dw,
NULL,NULL);
b = FALSE;
}
}
CloseServiceHandle(hSC);
return(b);
}
BOOL
MyChangeServiceConfig(
IN PCWSTR ServiceName,
IN DWORD ServiceType,
IN DWORD StartType,
IN DWORD ErrorControl,
IN PCWSTR BinaryPathName, OPTIONAL
IN PCWSTR LoadOrderGroup, OPTIONAL
IN PWCHAR DependencyList,
IN PCWSTR ServiceStartName, OPTIONAL
IN PCWSTR Password, OPTIONAL
IN PCWSTR DisplayName OPTIONAL
)
/*++
Routine Description:
Wrapper for ChangeServiceConfig.
Arguments:
ServiceName - Name of service
ServiceType - Service type, e.g. SERVICE_KERNEL_DRIVER
StartType - Service Start value, e.g. SERVICE_BOOT_START
ErrorControl - Error control value, e.g. SERVICE_ERROR_NORMAL
BinaryPathName - Full Path of the binary image containing service
LoadOrderGroup - Group name for load ordering
DependencyList - Multisz string having dependencies. Any dependency
component having + as the first character is a
group dependency. The others are service dependencies.
ServiceStartName - Service Start name (account name in which this
service is run).
Password - Password used for starting the service.
DisplayName - Localizable name of Service.
Return value:
Boolean value indicating outcome.
--*/
{
SC_LOCK sclLock;
SC_HANDLE hSC;
SC_HANDLE hSCService;
DWORD dw;
BOOL b;
//
// Open a handle to the service controller manager
//
hSC = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSC == NULL) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_CHANGESVC_FAIL,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szOpenSCManager,
GetLastError(),
NULL,NULL);
return(FALSE);
}
//
// Try to lock the database, if possible. If we are not able to lock
// the database we will still modify the services entry. This is because
// we are just modifying a single service and chances are very low that
// anybody else is manipulating the same entry at the same time.
//
SetupDebugPrint1(L"MyChangeServiceConfig: LockingServiceDatabase for service %s", ServiceName);
sclLock = LockServiceDatabase(hSC);
//
// Process optional parameters
//
if(BinaryPathName && !BinaryPathName[0]) {
BinaryPathName = NULL;
}
if(LoadOrderGroup && !LoadOrderGroup[0]) {
LoadOrderGroup = NULL;
}
if(ServiceStartName && !ServiceStartName[0]) {
ServiceStartName = NULL;
}
if(Password && !Password[0]) {
Password = NULL;
}
if(DisplayName && !DisplayName[0]) {
DisplayName = NULL;
}
//
// Open the service with SERVICE_CHANGE_CONFIG access
//
if(hSCService = OpenService(hSC,ServiceName,SERVICE_CHANGE_CONFIG)) {
b = ChangeServiceConfig(
hSCService,
ServiceType,
StartType,
ErrorControl,
BinaryPathName,
LoadOrderGroup,
NULL,
DependencyList,
ServiceStartName,
Password,
DisplayName
);
if(!b) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_CHANGESVC_FAIL,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szChangeServiceConfig,
GetLastError(),
NULL,NULL);
}
CloseServiceHandle(hSCService);
} else {
b = FALSE;
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_CHANGESVC_FAIL,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szOpenService,
GetLastError(),
NULL,NULL);
}
//
// Unlock the database if locked and then close the service controller
// handle
//
if(sclLock) {
UnlockServiceDatabase(sclLock);
SetupDebugPrint1(L"MyChangeServiceConfig: Unlocked ServiceDatabase for service %s", ServiceName);
}
CloseServiceHandle(hSC);
return(b);
}
BOOL
MyChangeServiceStart(
IN PCWSTR ServiceName,
IN DWORD StartType
)
/*++
Routine Description:
Routine to change the start value of a service. This turns
around and calls the stub to ChangeServiceConfig.
Arguments:
ServiceName - Name of service
StartType - Service Start value, e.g. SERVICE_BOOT_START
Return value:
Boolean value indicating outcome.
--*/
{
BOOL b;
b = MyChangeServiceConfig(
ServiceName,
SERVICE_NO_CHANGE,
StartType,
SERVICE_NO_CHANGE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
);
return(b);
}
BOOL
SetupStartService(
IN PCWSTR ServiceName,
IN BOOLEAN Wait // if TRUE, try to wait until it is started.
)
{
SC_HANDLE hSC,hSCService;
BOOL b;
DWORD d;
DWORD dwDesiredAccess;
b = FALSE;
//
// Open a handle to the service controller manager
//
hSC = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSC == NULL) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_STARTSVC_FAIL,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szOpenSCManager,
GetLastError(),
NULL,NULL);
return(FALSE);
}
if (Wait) {
dwDesiredAccess = SERVICE_START | SERVICE_QUERY_STATUS;
} else {
dwDesiredAccess = SERVICE_START;
}
if(hSCService = OpenService(hSC,ServiceName,dwDesiredAccess)) {
SetupDebugPrint1(L"SetupStartService: Sending StartService to <%ws>\n", ServiceName);
b = StartService(hSCService,0,NULL);
SetupDebugPrint1(L"SetupStartService: Sent StartService to <%ws>\n", ServiceName);
if(!b && ((d = GetLastError()) == ERROR_SERVICE_ALREADY_RUNNING)) {
//
// Service is already running.
//
b = TRUE;
}
if(!b) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_STARTSVC_FAIL,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_PARAM_RETURNED_WINERR,
szStartService,
d,
ServiceName,
NULL,NULL);
}
if (b && Wait) {
#define SLEEP_TIME 4000
#define LOOP_COUNT 30
SERVICE_STATUS ssStatus;
DWORD loopCount = 0;
//SetupDebugPrint(L" )) Looping waiting for start\n");
do {
b = QueryServiceStatus( hSCService, &ssStatus);
if ( !b ) {
//SetupDebugPrint(L"FAILED %d\n", GetLastError());
break;
}
if (ssStatus.dwCurrentState == SERVICE_START_PENDING) {
//SetupDebugPrint(L"PENDING\n");
if ( loopCount++ == LOOP_COUNT ) {
//SetupDebugPrint2(L"SYSSETUP: STILL PENDING after %d times: <%ws> service\n", loopCount, ServiceName);
break;
}
Sleep( SLEEP_TIME );
} else {
//SetupDebugPrint3(L"SYSSETUP: WAITED %d times: <%ws> service, status %d\n", loopCount, ServiceName, ssStatus.dwCurrentState);
break;
}
} while ( TRUE );
}
CloseServiceHandle(hSCService);
} else {
b = FALSE;
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_STARTSVC_FAIL,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_PARAM_RETURNED_WINERR,
szOpenService,
GetLastError(),
ServiceName,
NULL,NULL);
}
CloseServiceHandle(hSC);
return(b);
}
BOOL
FixServiceDependency(
IN PCWSTR ServiceName,
IN PCWSTR OldDependencyName,
IN PCWSTR NewDependencyName
)
{
ULONG Error;
HKEY hKey;
WCHAR ServicePath[ MAX_PATH + 1 ];
PBYTE OldValueData;
PBYTE NewValueData;
ULONG OldValueSize;
ULONG NewValueSize;
DWORD Type;
PBYTE p,q;
BOOL ChangeDependencyList;
//
// Open the key that describes the service
//
lstrcpy( ServicePath, szServicesKeyPath );
pSetupConcatenatePaths(ServicePath,ServiceName,sizeof( ServicePath )/sizeof( WCHAR ),NULL);
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
ServicePath,
0,
KEY_READ | KEY_WRITE,
&hKey );
if( Error != ERROR_SUCCESS ) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_FIX_SERVICE_FAILED,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_PARAM_RETURNED_WINERR,
szRegOpenKeyEx,
Error,
ServicePath,
NULL,NULL);
return( FALSE );
}
//
// Allocate a buffer for the old value data
//
OldValueSize = 0;
Error = RegQueryValueEx(hKey,
szDependOnService,
NULL,
&Type,
NULL,
&OldValueSize);
if( ( Error != ERROR_SUCCESS ) && ( Error != ERROR_MORE_DATA ) ) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_FIX_SERVICE_FAILED,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_PARAM_RETURNED_WINERR,
szRegQueryValueEx,
Error,
szDependOnService,
NULL,NULL);
RegCloseKey( hKey );
return( FALSE );
}
OldValueData = MyMalloc( OldValueSize );
if( OldValueData == NULL ) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_FIX_SERVICE_FAILED,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_OUTOFMEMORY,
NULL,NULL);
RegCloseKey( hKey );
return( FALSE );
}
//
// Read the value entry that lists the dependencies
//
Error = RegQueryValueEx(hKey,
szDependOnService,
NULL,
&Type,
OldValueData,
&OldValueSize);
if( Error != ERROR_SUCCESS ) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_FIX_SERVICE_FAILED,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_PARAM_RETURNED_WINERR,
szRegQueryValueEx,
Error,
szDependOnService,
NULL,NULL);
MyFree( OldValueData );
RegCloseKey( hKey );
return( FALSE );
}
//
// Find out if the OldValueData, explicitly list OldDependencyName.
// If not, then the service depends on another service that depends
// on OlDependencyName, and in this case there is no need to change
// the dependency list.
//
p = OldValueData;
ChangeDependencyList = FALSE;
while( (ULONG)(p - OldValueData) < OldValueSize ) {
if( ( lstrcmpi( (PWSTR)p, OldDependencyName ) == 0 ) ) {
ChangeDependencyList = TRUE;
break;
}
p += (lstrlen( (PWSTR)p ) + 1)*sizeof(WCHAR);
}
if( !ChangeDependencyList ) {
MyFree( OldValueData );
RegCloseKey( hKey );
//
// Let the caller think that the dependency list was fixed
//
return( TRUE );
}
//
// Allocate a buffer for the new value data
//
NewValueSize = OldValueSize -
( lstrlen( OldDependencyName ) - lstrlen( NewDependencyName ) )*sizeof(WCHAR);
NewValueData = MyMalloc( NewValueSize );
if( NewValueData == NULL ) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_FIX_SERVICE_FAILED,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_OUTOFMEMORY,
NULL,NULL);
MyFree( OldValueData );
RegCloseKey( hKey );
return( FALSE );
}
//
// Replace the old dependency name with the new one
//
p = OldValueData;
q = NewValueData;
lstrcpy( (PWSTR)q, NewDependencyName );
q += (lstrlen( (PWSTR)q ) + 1)*sizeof(WCHAR);
while( (ULONG)(p - OldValueData) < OldValueSize ) {
if( ( lstrcmpi( (PWSTR)p, OldDependencyName ) != 0 ) &&
( lstrcmpi( (PWSTR)p, NewDependencyName ) != 0 )
) {
lstrcpy( (PWSTR)q, (PWSTR)p );
q += (lstrlen( (PWSTR)q ) + 1)*sizeof(WCHAR);
}
p += (lstrlen( (PWSTR)p ) + 1)*sizeof(WCHAR);
}
//
// Save the value entry with the new dependency name
//
Error = RegSetValueEx( hKey,
szDependOnService,
0,
REG_MULTI_SZ,
NewValueData,
(DWORD)(q-NewValueData) // NewValueSize
);
if( Error != ERROR_SUCCESS ) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_FIX_SERVICE_FAILED,
ServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_PARAM_RETURNED_WINERR,
szRegSetValueEx,
Error,
szDependOnService,
NULL,NULL);
MyFree( OldValueData );
MyFree( NewValueData );
RegCloseKey( hKey );
return( FALSE );
}
//
// Free the allocated buffers
//
MyFree( OldValueData );
MyFree( NewValueData );
//
// Close the key
//
RegCloseKey( hKey );
return( TRUE );
}
BOOL
UpdateServicesDependencies(
IN HINF InfHandle
)
{
INFCONTEXT InfContext;
PCWSTR OldServiceName,NewServiceName;
BOOL b;
SC_HANDLE hSC, hSCService;
LPENUM_SERVICE_STATUS DependentsList;
DWORD BytesNeeded;
DWORD ServicesReturned;
HKEY hKey;
ULONG Error;
ULONG i;
//
// Iterate the [ServicesToRename] section in the inf.
// Each line is the name of a dependecy service that needs to be renamed.
//
if(SetupFindFirstLine(InfHandle,szServicesToRename,NULL,&InfContext)) {
b = TRUE;
} else {
SetuplogError( LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_UPDATE_SERVICES_FAILED, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_NO_SECTION,
szServicesToRename,NULL,NULL);
return(FALSE);
}
//
// Open a handle to the service controller manager
//
hSC = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSC == NULL) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_UPDATE_SERVICES_FAILED, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szOpenSCManager,
GetLastError(),
NULL,NULL);
return(FALSE);
}
do {
//
// Fetch the name of a service that got renamed
//
if((OldServiceName = pSetupGetField(&InfContext,0))
&& (NewServiceName = pSetupGetField(&InfContext,1))) {
//
// Create a dummy service that has the same name as the old service
// This is necessarey so that we can get a handle to this service,
// and pass it to EnumDependentServices to find out the services that
// depend on this one.
//
if( !MyCreateService( OldServiceName,
NULL,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_DISABLED,
SERVICE_ERROR_NORMAL,
L"%SystemRoot%\\System32\\dummy.exe",
NULL,
L"",
NULL,
NULL ) ) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_UPDATE_SERVICES_FAILED, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_CANT_CREATE_DUMMY_SERVICE,
OldServiceName,
NULL,NULL);
b = FALSE;
continue;
}
//
// Open the service that was just created
//
hSCService = OpenService(hSC,OldServiceName,SERVICE_ENUMERATE_DEPENDENTS | DELETE);
if( hSCService == NULL) {
Error = GetLastError();
SetupDebugPrint2( L"SYSSETUP: Unable to open service = %ls. Error = %d \n", OldServiceName, Error );
SetuplogError( LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_UPDATE_SERVICES_FAILED, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_PARAM_RETURNED_WINERR,
szOpenService,
Error,
OldServiceName,
NULL,NULL);
//
// Force deletion of the service cretated
//
b = FALSE;
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
szServicesKeyPath,
0,
MAXIMUM_ALLOWED,
&hKey );
if( Error == ERROR_SUCCESS ) {
pSetupRegistryDelnode( hKey, OldServiceName );
RegCloseKey( hKey );
}
continue;
}
//
// Determine all services that depend on the service that was renamed
//
BytesNeeded = 0;
ServicesReturned = 0;
DependentsList = NULL;
if( !EnumDependentServices( hSCService,
SERVICE_ACTIVE | SERVICE_INACTIVE,
DependentsList,
0,
&BytesNeeded,
&ServicesReturned ) &&
( Error = GetLastError()) != ERROR_MORE_DATA ) {
SetuplogError( LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_UPDATE_SERVICES_PARAM_FAILED,
OldServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szEnumDependentService,
Error,
NULL,NULL);
b = FALSE;
goto delete_dummy_service;
}
DependentsList = MyMalloc( BytesNeeded );
if( DependentsList == NULL ) {
SetuplogError(
LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_UPDATE_SERVICES_PARAM_FAILED,
OldServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_OUTOFMEMORY,
NULL,NULL);
b = FALSE;
goto delete_dummy_service;
}
if( !EnumDependentServices( hSCService,
SERVICE_ACTIVE | SERVICE_INACTIVE,
DependentsList,
BytesNeeded,
&BytesNeeded,
&ServicesReturned ) ) {
SetuplogError( LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_UPDATE_SERVICES_PARAM_FAILED,
OldServiceName, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_X_RETURNED_WINERR,
szEnumDependentService,
GetLastError(),
NULL,NULL);
MyFree( DependentsList );
b = FALSE;
goto delete_dummy_service;
}
for( i = 0; i < ServicesReturned; i++ ) {
//
// Fix the dependency for this service
//
b = b && FixServiceDependency( DependentsList[i].lpServiceName,
OldServiceName,
NewServiceName );
}
MyFree( DependentsList );
delete_dummy_service:
if( !DeleteService(hSCService) &&
((Error = GetLastError()) != ERROR_SERVICE_MARKED_FOR_DELETE)
) {
SetupDebugPrint2( L"SYSSETUP: Unable to delete service %ls. Error = %d \n", OldServiceName, Error );
#if 0
//
// Force deletion of the dummy service
//
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
szServicesKeyPath,
0,
MAXIMUM_ALLOWED,
&hKey );
if( Error == ERROR_SUCCESS ) {
pSetupRegistryDelnode( hKey, OldServiceName );
RegCloseKey( hKey );
}
#endif
}
CloseServiceHandle(hSCService);
} else {
SetuplogError( LogSevWarning,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_UPDATE_SERVICES_FAILED, NULL,
SETUPLOG_USE_MESSAGEID,
MSG_LOG_NO_SECTION,
szServicesToRename,NULL,NULL);
}
} while(SetupFindNextLine(&InfContext,&InfContext));
CloseServiceHandle(hSC);
return(b);
}