Services für Win9x
« | 01 Jul 2023 | »Während der Windows 98 und ME Support im Jahr 2003 ablief, hatte ich noch 2008 den Auftrag, Software so zu schreiben, dass sie unter Windows 9x ausführbar ist.
Dabei ging es “nur” um normale UIs.
Dienste wie unter NT gab es nicht … oder vielleicht doch …?
Es ist schon ein bisschen ironisch, dass sich die damals junge
Linux Community zu Recht über
“das schlechte Windows” aufregte, und dabei fast ausschließlich Probleme mit
Windows 95 und 98 nannte.
NT4 und 2000 konnte man dann nur als zu aufgebläht bezeichnen.
Die strukturierte Verwaltung von “Diensten” (Daemons unter Linux) hatte aber nur NT wirklich drauf, während sich das junge Linux mit init-Scripten plagte und interessanterweise nicht viel mehr hinbekam, als eben Windows 9x.
Kein Service Manager
Der Service Control Manager (SCM) definiert unter NT die Infrastruktur eines Dienstes. Eine EXE startet und registriert sich selbst per API als Dienst inklusive Callbacks für diverse Statusänderungen und die Service-Runtime führt diese Callbacks als RPCs dann “kontrolliert” aus.
Win9X kannte einen solchen Dienst nicht, hatte aber einen für damals typischen billigen Trick, um so etwas Ähnliches wie Hintergrunddienste anzustarten.
Registry + Registration = Service
Viele Leute kennen den Registry-Key
HKEY_LOCAL_MACHINE\Software\Microsoft\CurrentVersion\Run
, dessen Einträge
beim Login durchgelaufen werden und die String-Values einfach als Prozesse
gestartet werden.
Für Dienste gab es HKEY_LOCAL_MACHINE\Software\Microsoft\CurrentVersion\RunServices
,
dessen Einträge schon beim Start des Windows-UI abgearbeitet wurden.
So konnte man per Key-Namen jedem Dienst einen Namen zuordnen und der
String-Wert war einfach die Kommandozeile, die den Dienst starten sollte.
Da bei der Abmeldung eines Benutzers auch alle laufenden Prozesse gekillt
wurden, musste man noch einen Möglichkeit schaffen, die Dienst-Prozesse als
ebensolche zu markieren. Und das geschah mit folgender kernel32
API:
1DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType);
Diese Funktion existierte nur in Windows 9x und nicht NT, doch man konnte sie
per GetProcAddress()
laden um zu beiden OS-Typen kompatibel zu bleiben.
Ein Aufruf von RegisterServiceProcess(GetCurrentProcessId(), 1)
registrierte
einen Prozess als Dienst, und schon wurde er nicht mehr beim Logout beendet.
Anwendung
Manche Netzwerkserver für Windows wie FTP, HTTP oder NTP nutzten diese
Methode um im Hintergrund ihre Dienste durchzuführen.
Doch da Windows 9x selten für solche “Dienste” genutzt wurde, ging diese
Methode wieder in Vergessenheit.
Man findet sie noch in sehr alten Code-Repositories in Softwareständen vor
2003, doch danach wurde der Win9x-Service Support systematisch überall
entfernt.
Die Funktion RegisterServiceProcess
selbst findet man “leider” in
zahlreichen alten Foren als “Hacker-Funktion” um das eigene Programm
vor dem Task-Manager zu verstecken.
Wer also Böses vor hatte und nicht wollte, dass das eigene Programm
leicht gekillt werden konnte, registrierte es fälschlich als Dienst.
Fazit
Auch diese Technik wandert nun ins GATE Projekt und tut dort seinen Dienst, wenn die NT-APIs nicht geladen werden können … sprich, wenn ein Prozess unter Windows 9x gestartet wird.
Da diese Funktion aber nur in ANSI-Kompilaten Sinn macht, ist dieser Teil
in Unicode- oder x64- Varianten generell per #ifdef
deaktiviert.