Changing Windows service configuration C program example
// For WinXp as a target
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
// lpDescription - string description of the service
// fDisable - service start type
void ReconfigureMySampleService(BOOL, LPSTR);
int main(void)
{
BOOL fDisable = FALSE;
// The new description for the service...
LPWSTR lpDesc = L"This is an added description for MySampleSrv";
// Call the function...
ReconfigureMySampleService(fDisable, (LPSTR)lpDesc);
return 0;
}
void ReconfigureMySampleService(BOOL fDisable, LPSTR lpDesc)
{
// This fictitious service has been created in the previous example. It is a Telnet service, though not a usable one...
LPCTSTR lpszServiceName = L"MyTelnetSrv";
SC_HANDLE schSCManager, schService;
SC_LOCK sclLock;
LPQUERY_SERVICE_LOCK_STATUS lpqslsBuf;
SERVICE_DESCRIPTION sdBuf;
DWORD dwBytesNeeded, dwStartType;
// Open a handle to the SC Manager database...
schSCManager = OpenSCManager(
NULL, // local machine
NULL, // SERVICES_ACTIVE_DATABASE database is opened by default
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
printf("OpenSCManager() failed, error: %d.\n", GetLastError());
else
printf("OpenSCManager() looks OK.\n");
// Need to acquire database lock before reconfiguring.
sclLock = LockServiceDatabase(schSCManager);
// If the database cannot be locked, report the details.
if (sclLock == NULL)
{
// Exit if the database is not locked by another process.
if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED)
printf("LockServiceDatabase() failed, error: %d.\n", GetLastError());
else
printf("LockServiceDatabase() is OK.\n");
// Allocate a buffer to get details about the lock.
lpqslsBuf = (LPQUERY_SERVICE_LOCK_STATUS) LocalAlloc(LPTR, sizeof(QUERY_SERVICE_LOCK_STATUS)+256);
if (lpqslsBuf == NULL)
printf("LocalAlloc() failed, error: %d.\n", GetLastError());
else
printf("LocalAlloc() is OK.\n");
// Get and print the lock status information.
if (!QueryServiceLockStatus(schSCManager, lpqslsBuf, sizeof(QUERY_SERVICE_LOCK_STATUS)+256, &dwBytesNeeded))
printf("QueryServiceLockStatus() failed, error: %d.\n", GetLastError());
else
printf("QueryServiceLockStatus() looks OK.\n");
if (lpqslsBuf->fIsLocked)
printf("Locked by: %s, duration: %d seconds\n", lpqslsBuf->lpLockOwner, lpqslsBuf->dwLockDuration);
else
printf("No longer locked.\n");
LocalFree(lpqslsBuf);
printf("Could not lock the database.\n");
}
// The database is locked, so it is safe to make changes. Open a handle to the service.
schService = OpenService(
schSCManager, // SCManager database
lpszServiceName, // name of service
SERVICE_CHANGE_CONFIG); // need CHANGE access
if (schService == NULL)
printf("OpenService() failed, error: %d.\n", GetLastError());
else
printf("OpenService() looks OK.\n");
dwStartType = (fDisable) ? SERVICE_DISABLED : SERVICE_DEMAND_START;
// Make the changes.
if (! ChangeServiceConfig(
schService, // handle of service
SERVICE_NO_CHANGE, // service type: no change
0x00000002, // dwStartType, change service startup type to auto
SERVICE_NO_CHANGE, // error control: no change
NULL, // binary path: no change
NULL, // load order group: no change
NULL, // tag ID: no change
NULL, // dependencies: no change
NULL, // account name: no change
NULL, // password: no change
NULL)) // display name: no change
{
printf("ChangeServiceConfig() failed, error: %d.\n", GetLastError());
}
else
printf("ChangeServiceConfig() looks OK, service config changed.\n");
sdBuf.lpDescription = (LPWSTR)lpDesc;
if(!ChangeServiceConfig2(
schService, // handle to service
SERVICE_CONFIG_DESCRIPTION, // change: description
&sdBuf)) // value: new description
{
printf("ChangeServiceConfig2() failed, error: %d.\n", GetLastError());
}
else
printf("ChangeServiceConfig2() looks OK, service description changed.\n");
// Release the database lock.
if (UnlockServiceDatabase(sclLock) == 0)
printf("UnlockServiceDatabase() failed, error: %d.\n", GetLastError());
else
printf("UnlockServiceDatabase() looks OK.\n");
// Close the handle to the service.
if (CloseServiceHandle(schService) == 0)
printf("CloseServiceHandle() failed, error: %d.\n", GetLastError());
else
printf("CloseServiceHandle() looks OK.\n");
return;
}
Output example:
OpenSCManager() looks OK.
OpenService() looks OK.
ChangeServiceConfig() looks OK, service config changed.
ChangeServiceConfig2() looks OK, service description changed.
UnlockServiceDatabase() looks OK.
CloseServiceHandle() looks OK.
Press any key to continue . . .
Verify the service Description: and Startup type: changes. Click Start->Programs->Administrative Tools->Services->Try finding "MyOwnTelnetService" service->Select and right click the service->Select Properties context menu->Verify that the Description: and Startup type: have been changed. Don't forget to delete your fictitious Telnet service by using the previous program example.
Compiler: Visual C++ Express Edition 2005
Compiled on Platform: Windows XP Pro SP2
Target platform: none, just for learning and fun
Header file: Standard and Windows
Additional library: Windows Platform SDK
Additional project setting: Set project to be compiled as C. Click Project menu->your_project_name Properties->Configuration Properties->C/C++->Advanced->Compiled As: Compiled as C Code (/TC)
Other info: non-CLR or unmanaged. Need to add Advapi32.lib (Advapi32.dll) to the project. Click the Project menu->Select the your_project_name Properties... sub menu->Expand the Configuration Properties folder on the left pane->Expand the Linker subfolder->Select the Input subfolder->Select the Additional Dependencies field on the right pane->Click the ... at the end of the field->Type in 'Advapi32.lib' in the empty pane->Click the OK button->Click the OK button second time to close the project Properties dialog.
To do: Changing Windows service configuration
To show: The Windows processes and services programming