Files
wehub-resource-sync 36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:06 +08:00

86 lines
2.1 KiB
Go

//go:build windows
package source
import (
"os/exec"
"strings"
"github.com/pranshuparmar/witr/pkg/model"
)
func detectWindowsService(ancestry []model.Process) *model.Source {
// 1. Check for explicit service name in process metadata (prioritize target)
for i := len(ancestry) - 1; i >= 0; i-- {
p := ancestry[i]
if p.Service != "" {
registryKey := `HKLM\SYSTEM\CurrentControlSet\Services\` + p.Service
description := resolveWindowsServiceDescription(p.Service)
return &model.Source{
Type: model.SourceWindowsService,
Name: p.Service,
Description: description,
UnitFile: registryKey,
Details: map[string]string{
"manager": "services.exe",
"service": p.Service,
},
}
}
}
// 2. Fallback: Check if services.exe is in ancestry without explicit service name
for _, p := range ancestry {
if strings.ToLower(p.Command) == "services.exe" {
return &model.Source{
Type: model.SourceWindowsService,
Name: "Service Control Manager",
Details: map[string]string{
"manager": "services.exe",
},
}
}
}
// 3. Check for children of services.exe where valid service name wasn't found
if len(ancestry) >= 2 {
parent := ancestry[len(ancestry)-2]
target := ancestry[len(ancestry)-1]
if strings.ToLower(parent.Command) == "services.exe" {
name := strings.TrimSuffix(target.Command, ".exe")
registryKey := `HKLM\SYSTEM\CurrentControlSet\Services\` + name
description := resolveWindowsServiceDescription(name)
return &model.Source{
Type: model.SourceWindowsService,
Name: name,
Description: description,
UnitFile: registryKey,
Details: map[string]string{
"manager": "services.exe",
},
}
}
}
return nil
}
func resolveWindowsServiceDescription(serviceName string) string {
if _, err := exec.LookPath("sc"); err != nil {
return ""
}
cmd := exec.Command("sc", "GetDisplayName", serviceName)
out, _ := cmd.Output()
output := string(out)
if idx := strings.Index(output, "Name = "); idx != -1 {
return strings.TrimSpace(output[idx+7:])
}
return ""
}