Думаю, в основном - всё идёт от иной THREAD-модели в C6 по сравнению с C5. И поэтому - некоторые процедуры (см.ниже) завершаются, а система продолжает работать с их переменными, которые уже выгружены из памяти.
Вероятно основной код программы состоит из вызова (или после обработки параметров заканчивается вызовом) StartServiceMain
Объяви переменные глобально и попробуй:
ServiceTable GROUP из процедуры StartServiceMain
LOC:SERVICE_STATUS LIKE(SERVICE_STATUS) из функции SendStatusToSCM
ежели не будет изменений -
не завершай процедуру ServiceMain после запуска нового потока, а отправь его в спячку до возникновения какого-то события.
То есть после строк
IF ~CreateThread(0,0,ADDRESS(Main),0,0,LOC_ThreadID)
DO ServiceStop
.
допиши типа:
Код: Выделить всё
!Создаём системное событие для сигнализации необходимости останова
ghSvcStopEvent = CreateEvent(0, | ! default security attributes
TRUE, | ! manual reset event
FALSE, | ! not signaled
0) ! no name
If ghSvcStopEvent Then ! успешно создан объект "событие"
SendStatustoSCM( SERVICE_RUNNING, NO_ERROR, 0, 1, 1000 ) ! Отметить для SCM: "сервис в работе"
Loop
! Вместо работы - просто ожидаем, когда нам скажут "STOP" - ждём возникновения события <ghSvcStopEvent>
WaitForSingleObject(ghSvcStopEvent, INFINITE)
Break
End
End
SendStatustoSCM( SERVICE_STOPPED, NO_ERROR, 0, 1, 1000 ) ! Отметить для SCM: "сервис остановлен"
а в обработке controlCode = SERVICE_CONTROL_STOP в процедуре ServiceHandler укажи (взамен твоего), а также - если нужно при ином условии завершения, например, перед оператором RETURN процедуры MAIN:
Код: Выделить всё
SendStatustoSCM( SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 1000) ! изменить состояние на "начат процесс останова"
SetEvent(ghSvcStopEvent) ! взвести(активировать) событие <ghSvcStopEvent> (будет принято в ServiceMain)
где ghSvcStopEvent - глобально объявлено, как:
ghSvcStopEvent HANDLE ! Handle события StopEvent
---------------------------------------------------
И ещё, для подключения к Service Control Manager
MSDN ПИШЕТ:
The OpenSCManager function establishes a connection to the service control manager on the specified computer and opens the specified service control manager database.
SC_HANDLE OpenSCManager(
LPCTSTR lpMachineName,
LPCTSTR lpDatabaseName,
DWORD dwDesiredAccess
);
Parameters
lpMachineName [in] Pointer to a null-terminated string that specifies the name of the target computer. If the pointer is NULL or points to an empty string, the function connects to the service control manager on the local computer.
lpDatabaseName [in] Pointer to a null-terminated string that specifies the name of the service control manager database to open. This parameter should be set to SERVICES_ACTIVE_DATABASE. If it is NULL, the SERVICES_ACTIVE_DATABASE database is opened by default.
dwDesiredAccess [in] Access to the service control manager. For a list of access rights, see Service Security and Access Rights.
Before granting the requested access rights, the system checks the access token of the calling process against the discretionary access-control list of the security descriptor associated with the service control manager.
The SC_MANAGER_CONNECT access right is implicitly specified by calling this function.
ПРИ ЭТОМ, СОДЕРЖИТСЯ в advapi32.dll В ДВУХ ВАРИАНТАХ: OpenSCManagerA, OpenSCManagerW
-----------------------------------
ПОЭТОМУ МОЁ ОБЪЯВЛЕНИЕ:
OpenSCManager( <*CString lpMachineName>, <*CString lpDatabaseName>, DWORD dwDesiredAccess ), SC_HANDLE, Pascal, Raw, Dll, Name('OpenSCManagerA')
И МОИ ВЫЗОВЫ:
hSCM = OpenSCManager( , , STANDARD_RIGHTS_WRITE + SC_MANAGER_CONNECT + SC_MANAGER_CREATE_SERVICE ) ! для инсталляции сервиса
hSCM = OpenSCManager( , , STANDARD_RIGHTS_READ + SC_MANAGER_CONNECT + SC_MANAGER_ENUMERATE_SERVICE ) ! для перечисления сервисов
hSCM = OpenSCManager( , , STANDARD_RIGHTS_READ + SC_MANAGER_CONNECT ) ! для подключения
Последнее поможет на случай, если ServicesDatabaseName='ServicesActive' для SCM непонятно.