DWORD LwSmSrvAcquireServiceHandle( PCWSTR pwszName, PLW_SERVICE_HANDLE phHandle ) { DWORD dwError = 0; PSM_TABLE_ENTRY pEntry = NULL; LW_SERVICE_HANDLE hHandle = NULL; dwError = LwSmTableGetEntry(pwszName, &pEntry); BAIL_ON_ERROR(dwError); dwError = LwAllocateMemory(sizeof(*hHandle), OUT_PPVOID(&hHandle)); BAIL_ON_ERROR(dwError); hHandle->pEntry = pEntry; *phHandle = hHandle; cleanup: return dwError; error: *phHandle = NULL; if (pEntry) { LwSmTableReleaseEntry(pEntry); } goto cleanup; }
static VOID LwSmTableWatchdog( PVOID pContext ) { DWORD error = 0; PSM_TABLE_ENTRY pEntry = pContext; PSM_TABLE_ENTRY pOtherEntry = NULL; LW_SERVICE_STATUS status = {0}; PWSTR* ppServices = NULL; DWORD index = 0; error = LwSmTableStartRecursive(pEntry); BAIL_ON_ERROR(error); /* See if any reverse dependencies changed state without announcing it */ error = LwSmTableGetEntryReverseDependencyClosure(pEntry, &ppServices); BAIL_ON_ERROR(error); for (index = 0; ppServices[index]; index++) { error = LwSmTableGetEntry(ppServices[index], &pOtherEntry); BAIL_ON_ERROR(error); error = LwSmTableGetEntryStatus(pOtherEntry, &status); BAIL_ON_ERROR(error); if (status.state == LW_SERVICE_STATE_DEAD) { (void) LwSmTableStartRecursive(pOtherEntry); } LwSmTableReleaseEntry(pOtherEntry); pOtherEntry = NULL; } error: if (ppServices) { LwSmFreeStringList(ppServices); } if (pOtherEntry) { LwSmTableReleaseEntry(pOtherEntry); } LwSmTableReleaseEntry(pEntry); return; }
static DWORD LwSmShutdownServices( VOID ) { DWORD dwError = 0; PWSTR* ppwszServiceNames = NULL; size_t i = 0; PSM_TABLE_ENTRY pEntry = NULL; SM_LOG_INFO("Shutting down running services"); dwError = LwSmTableEnumerateEntries(&ppwszServiceNames); BAIL_ON_ERROR(dwError); for (i = 0; ppwszServiceNames[i]; i++) { dwError = LwSmTableGetEntry(ppwszServiceNames[i], &pEntry); BAIL_ON_ERROR(dwError); dwError = LwSmShutdownService(pEntry); if (dwError) { /* Ignore errors and try to shut down everything we can */ SM_LOG_WARNING("Could not shut down service: %u\n", (unsigned int) dwError); dwError = 0; } LwSmTableReleaseEntry(pEntry); pEntry = NULL; } cleanup: if (ppwszServiceNames) { LwSmFreeStringList(ppwszServiceNames); } if (pEntry) { LwSmTableReleaseEntry(pEntry); } return dwError; error: goto cleanup; }
static DWORD LwSmShutdownService( PSM_TABLE_ENTRY pEntry ) { DWORD dwError = 0; PSM_TABLE_ENTRY pDep = NULL; PWSTR* ppwszDeps = NULL; size_t i = 0; dwError = LwSmTableGetEntryReverseDependencyClosure(pEntry, &ppwszDeps); BAIL_ON_ERROR(dwError); for (i = 0; ppwszDeps[i]; i++) { dwError = LwSmTableGetEntry(ppwszDeps[i], &pDep); BAIL_ON_ERROR(dwError); dwError = LwSmTableStopEntry(pDep); BAIL_ON_ERROR(dwError); LwSmTableReleaseEntry(pDep); pDep = NULL; } dwError = LwSmTableStopEntry(pEntry); BAIL_ON_ERROR(dwError); cleanup: if (pDep) { LwSmTableReleaseEntry(pDep); } if (ppwszDeps) { LwSmFreeStringList(ppwszDeps); } return dwError; error: goto cleanup; }
static DWORD LwSmTableStartRecursive( PSM_TABLE_ENTRY pEntry ) { DWORD error = 0; PSM_TABLE_ENTRY pOtherEntry = NULL; PWSTR* ppServices = NULL; DWORD index = 0; /* Start all dependencies */ error = LwSmTableGetEntryDependencyClosure(pEntry, &ppServices); BAIL_ON_ERROR(error); for (index = 0; ppServices[index]; index++) { error = LwSmTableGetEntry(ppServices[index], &pOtherEntry); BAIL_ON_ERROR(error); error = LwSmTableStartEntry(pOtherEntry); BAIL_ON_ERROR(error); LwSmTableReleaseEntry(pOtherEntry); pOtherEntry = NULL; } error = LwSmTableStartEntry(pEntry); BAIL_ON_ERROR(error); error: if (ppServices) { LwSmFreeStringList(ppServices); } if (pOtherEntry) { LwSmTableReleaseEntry(pOtherEntry); } return error; }
static DWORD LwSmTableGetEntryReverseDependencyClosureHelper( PSM_TABLE_ENTRY pEntry, PWSTR* ppwszAllServices, PWSTR** pppwszServiceList ) { DWORD dwError = 0; PLW_SERVICE_INFO pInfo = NULL; PLW_SERVICE_INFO pDepInfo = NULL; size_t i = 0; PSM_TABLE_ENTRY pDepEntry = NULL; PWSTR pwszDepName = NULL; BOOLEAN bLocked = FALSE; LOCK(bLocked, pEntry->pLock); dwError = LwSmCopyServiceInfo(pEntry->pInfo, &pInfo); UNLOCK(bLocked, pEntry->pLock); BAIL_ON_ERROR(dwError); for (i = 0; ppwszAllServices[i]; i++) { dwError = LwSmTableGetEntry(ppwszAllServices[i], &pDepEntry); BAIL_ON_ERROR(dwError); LOCK(bLocked, pEntry->pLock); dwError = LwSmCopyServiceInfo(pDepEntry->pInfo, &pDepInfo); UNLOCK(bLocked, pEntry->pLock); BAIL_ON_ERROR(dwError); if (LwSmStringListContains(pDepInfo->ppwszDependencies, pInfo->pwszName)) { dwError = LwSmTableGetEntryReverseDependencyClosureHelper( pDepEntry, ppwszAllServices, pppwszServiceList); BAIL_ON_ERROR(dwError); dwError = LwAllocateWc16String(&pwszDepName, pDepInfo->pwszName); BAIL_ON_ERROR(dwError); dwError = LwSmStringListAppend(pppwszServiceList, pwszDepName); BAIL_ON_ERROR(dwError); pwszDepName = NULL; } LwSmCommonFreeServiceInfo(pDepInfo); pDepInfo = NULL; LwSmTableReleaseEntry(pDepEntry); pDepEntry = NULL; } cleanup: LW_SAFE_FREE_MEMORY(pwszDepName); if (pInfo) { LwSmCommonFreeServiceInfo(pInfo); } if (pDepInfo) { LwSmCommonFreeServiceInfo(pDepInfo); } if (pDepEntry) { LwSmTableReleaseEntry(pDepEntry); } return dwError; error: goto cleanup; }
DWORD LwSmPopulateTable( VOID ) { DWORD dwError = 0; HANDLE hReg = NULL; PWSTR* ppwszNames = NULL; PWSTR pwszName = NULL; PLW_SERVICE_INFO pInfo = NULL; PSM_TABLE_ENTRY pEntry = NULL; size_t i = 0; SM_LOG_VERBOSE("Populating service table"); dwError = RegOpenServer(&hReg); BAIL_ON_ERROR(dwError); dwError = LwSmRegistryEnumServices(hReg, &ppwszNames); switch (dwError) { case LWREG_ERROR_NO_SUCH_KEY_OR_VALUE: /* No services in registry */ dwError = 0; goto cleanup; } BAIL_ON_ERROR(dwError); for (i = 0; ppwszNames[i]; i++) { pwszName = ppwszNames[i]; LwSmCommonFreeServiceInfo(pInfo); pInfo = NULL; dwError = LwSmRegistryReadServiceInfo(hReg, pwszName, &pInfo); switch (dwError) { case LWREG_ERROR_NO_SUCH_KEY_OR_VALUE: dwError = 0; continue; default: break; } BAIL_ON_ERROR(dwError); dwError = LwSmTableGetEntry(pwszName, &pEntry); if (!dwError) { dwError = LwSmTableUpdateEntry(pEntry, pInfo, LW_SERVICE_INFO_MASK_ALL); BAIL_ON_ERROR(dwError); } else if (dwError == LW_ERROR_NO_SUCH_SERVICE) { dwError = LwSmTableAddEntry(pInfo, &pEntry); BAIL_ON_ERROR(dwError); } else { BAIL_ON_ERROR(dwError); } LwSmTableReleaseEntry(pEntry); pEntry = NULL; } cleanup: LwSmFreeStringList(ppwszNames); LwSmCommonFreeServiceInfo(pInfo); if (hReg) { RegCloseServer(hReg); } return dwError; error: goto cleanup; }