В следующем примере, программа конфигурации службы использует функции ChangeServiceConfig и ChangeServiceConfig2, чтобы изменить параметры конфигурации установленной службы. Программа сначала делает попытку блокировать базу данных, воспрепятствовать Диспетчеру управления службами (SCM) запустить службу, в то время когда она переконфигурируется. Если она успешно блокирует базу данных, программа открывает дескриптор объекта службы, модифицирует его конфигурацию, открывает базу данных, а затем закрывает дескриптор объекта службы. Если программе не удается заблокировать базу данных, она использует функцию QueryServiceLockStatus, чтобы извлечь информацию о блокировке.
#include <windows.h> #include <stdio.h> BOOL ReconfigureSampleService(BOOL fDisable, LPSTR lpDesc) { SC_LOCK sclLock; LPQUERY_SERVICE_LOCK_STATUS lpqslsBuf; SERVICE_DESCRIPTION sdBuf; DWORD dwBytesNeeded, dwStartType; BOOL bSuccess=TRUE; // Нужно собрать данные о блокировке базы данных перед реконфигурированием. sclLock = LockServiceDatabase(schSCManager); // Если база данных не может быть блокирована, то подробный отчет. if (sclLock == NULL) { // Выход, если база данных не блокируется другими процессами. if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED) { printf("LockServiceDatabase failed (%d)\n", GetLastError()); return FALSE; } // Назначаем буфер для получения деталей о блокировке. lpqslsBuf = (LPQUERY_SERVICE_LOCK_STATUS) LocalAlloc( LPTR, sizeof(QUERY_SERVICE_LOCK_STATUS)+256); if (lpqslsBuf == NULL) { printf("LocalAlloc failed (%d)\n", GetLastError()); return FALSE; } // Получаем и печатаем информацию о состоянии блокировки. if (!QueryServiceLockStatus( schSCManager, lpqslsBuf, sizeof(QUERY_SERVICE_LOCK_STATUS)+256, &dwBytesNeeded) ) { printf("QueryServiceLockStatus failed (%d)", GetLastError()); return FALSE; } if (lpqslsBuf->fIsLocked) printf("Locked by: %s, duration: %d seconds\n", lpqslsBuf->lpLockOwner, lpqslsBuf->dwLockDuration); else printf("No longer locked\n"); LocalFree(lpqslsBuf); } // База данных блокирована, таким образом, что она сохранит сделанные изменения. // Откроем дескриптор службы. schService = OpenService( schSCManager, // база данных SCManager "Sample_Srv", // имя службы SERVICE_CHANGE_CONFIG); // требуемый уровень доступа - CHANGE if (schService == NULL) { printf("OpenService failed (%d)\n", GetLastError()); return FALSE; } dwStartType = (fDisable) ? SERVICE_DISABLED : SERVICE_DEMAND_START; // Делаем изменения. if (! ChangeServiceConfig( schService, // дескриптор службы SERVICE_NO_CHANGE, // тип службы: не изменяется dwStartType, // тип запущенной службы, который изменяется SERVICE_NO_CHANGE, // контроль за ошибками: не изменяется NULL, // путь к двоичному коду: не изменяется NULL, // загрузка очередности групп: не изменяется NULL, // ID признака: не изменяется NULL, // зависимость от других служб: не изменяется NULL, // имя учетной записи: не изменяется NULL, // пароль: не изменяется NULL) ) // показываемое имя: не изменяется { printf("ChangeServiceConfig failed (%d)\n", GetLastError()); bSuccess = FALSE; } else printf("ChangeServiceConfig succeeded.\n"); sdBuf.lpDescription = lpDesc; if( !ChangeServiceConfig2( schService, // дескриптор службы SERVICE_CONFIG_DESCRIPTION, // изменение: описание &sdBuf) ) // значение: новое описание { printf("ChangeServiceConfig2 failed\n"); bSuccess = FALSE; } else printf("ChangeServiceConfig2 succeeded\n"); // Отменим блокировку базы данных. UnlockServiceDatabase(sclLock); // Закроем дескриптор службы. CloseServiceHandle(schService); return bSuccess; } |