home *** CD-ROM | disk | FTP | other *** search
- Anleitung zu SETENV/SETDRIVE (c) 1/1996 by dOnut hOle
- SetEnv.com hat den Sinn, eine Environment-Variable zu erzeugen, die den
- Pfad enthält, in dem SetEnv gestartet wurde.
- Nehmen wir an, SetEnv.com befindet sich im Pfad C:\GAME\SPIEL und wir
- starten es mit SETENV SPIELDIR. Jetzt enthält die Umgebungsvariable SPIELDIR
- den Pfad von SetEnv (also C:\GAME\SPIEL).
-
- SetDrive.com funktioniert genauso, gibt aber das Laufwerk, in dem
- SetDrive gestartet wurde, zurück.
- Also SetDrive sei in C:\GAME\SPIEL und wir starten es mit SETDRIVE SPIELDIR.
- Dann enthält die Umgebungsvariable SPIELDIR den Laufwerkbuchstaben,
- also "C:".
-
- Wozu braucht man das ?
- Angenommen, man besitzt ein Programm, daß seine Daten immer in einem
- Verzeichnis im Hauptverzeichnis speichert ('\GAMEDATA'). Wir wollen es
- mittels SUBST davon überzeugen, dieses Verzeichnis im Programmverzeichnis
- anzulegen (SUBST A: C:\GAME\SPIEL). Wenn wir Setenv in das Programmverzeich-
- nis kopieren, können wir das Programm jetzt mit folgendem Batchfile
- austricksen (wegen Kommentaren so nicht lauffähig).
- @ECHO OFF Meldungen ausschalten
- SETENV PROGDIR PROGDIR den Pfad von Setenv (des Progr.) zuweisen
- SUBST A: %PROGDIR% Daten nach A: umleiten
- A: Auf Pseudolaufwerk A: wechseln
- PROG.EXE Programm ausführen
- C: Zurück auf Festplatte wechseln
- SUBST A: /D Substitution rückgängig machen
- SET PROGDIR= Umgebungsvariable löschen
-
- Bemerkungen:
- Zunächst mal: ja, man könnte meistens auch "." verwenden. Aber halt nicht
- immer. Jedenfalls ist SETENV die saubere Lösung. Und für SETDRIVE kenne
- ich überhaupt keinen Ersatz.
- SetEnv/SetDrive prüfen nicht, ob eine Variable gleichen Namens bereits
- existiert.
- Falls doch, exisiert diese zweifach im Environment.
- Man kann also noch eine Sicherheitsabfrage in das Batchfile einbauen:
- IF NOT %PROGDIR%!==! GOTO ERROR1
- SETENV PROGDIR
- Außerdem ist es möglich, daß kein Speicherplatz mehr im Environment frei
- ist. In diesem Fall sollte Setenv eine Fehlermeldung ausgeben. In jedem Fall
- sollte aber die Variable nicht gesetzt sein:
- SETENV PROGDIR
- IF %PROGDIR%!==! GOTO ERROR2
- Also nochmal die perfekte Lösung:
- @ECHO OFF
- IF NOT %PROGDIR%!==! GOTO ERROR1
- SETENV PROGDIR
- IF %PROGDIR%!==! GOTO ERROR2
- SUBST A: %PROGDIR%
- A:
- PROG.EXE
- C:
- SUBST A: /D
- SET PROGDIR=
- GOTO ENDE
- :ERROR1
- ECHO Umgebungsvariable doppelt, Batchfile muß editiert werden !
- GOTO ENDE
- :ERROR2
- ECHO Umgebungsspeicher zu knapp. Bitte erhöhen !
- :ENDE
-
- Den Umgebungsspeicher kann man übrigens in der CONFIG.SYS mit dem Befehl
- SHELL=C:\COMMAND.COM /P /E:512
- z.B. auf 512 Byte festsetzen.
-
-
- Programmierung:
- Den Pfad des laufenden Programmes zu bekommen ist leicht. Der Programmname
- inklusive Pfad steht im zugehörigen Environment-Block nach den Environment-
- Variablen. Diese sind durch je eine 0 getrennt. Den Programmpfad trennt eine
- weitere 0 von den Variablen. Die Adresse des Environments erfährt man aus
- dem PSP des Programms, der bei einem COM-Programm am Anfang des Code-Segments
- liegt. Bei einem Exe-Programm kann man ihn mit einem Interrupt aufspüren
- (21h, AH=62h, denke ich).
- Schwierig ist alleine das Verändern des Umgebungsspeichers (bzw. das Finden).
- Im PSP (Program Segment Prefix) kann man leicht den Environment-Block des
- laufenden Programms abfragen. Der PSP und das Environment sind aber bloß
- Kopien des PSPs und Environments von Command.com.
-
- PSP
- 00h Aufruf des Interrupt 20h (2 Bytes)
- 02h Endadresse des durch Programm belegten Speichers (nur Segment) (1 Word)
- 04h reserviert (1 Byte)
- 05h FAR-CALL zum Interrupt 21h (5 Bytes)
- 0Ah Kopie von Interrupt 22h (2 Word)
- 0Eh Kopie von Interrupt 23h (2 Word)
- 12h Kopie von Interrupt 24h (2 Word)
- 16h Vorheriger PSP: Segment (1 Word)
- 18h Reserviert (20 Bytes)
- 2Ch Segmentadresse des Environment Blocks (1 Word)
- 2Eh Reserviert (46 Bytes)
- 5Ch FCB #1 (16 Bytes)
- 6CH FCB #2 (16 Bytes)
- 80h Anzahl Zeichen in Kommandozeile (ohne CR) (1 Byte)
- 81h Kommandozeile (127 Bytes)
-
- Allerdings ist das Byte 16h im PSP ein Verweis auf den vorherigen PSP
- (undokumentiert!!!). Man kann sich also rückwärts durch die PSPs hangeln,
- bis ein PSP als nächsten PSP sich selbst angibt. Das ist der PSP von
- Command.com.
- Nun könnten wir also bereits im Environment von Command.com rumwerkeln,
- wissen aber nicht, wie groß es ist, was eine Beschädigung von command.com
- und damit einen Systemabsturz zur Folge haben könnte.
- Dazu muß man sich durch eine Liste von MCB (Memory Control Blocks) hangeln,
- deren erster im DOS-Info-Block an der Adresse -4 steht.
- Den Dos-Info-Block erhalten wir übrigens mit dem Interrupt 21h, AH=52h
- -> Zeiger auf DIB in es:bx
- -> Zeiger auf ersten MCB in es-1:bx+12 (entspricht -4, aber sicherer)
-
- MCB
- 00h ID ('Z': keiner folgt, 'M': es folgen weitere) (1 Byte)
- 01h Segmentadresse des zugehörigen PSP (1 Word)
- 03h Anzahl Paragraphen (16 Bytes) in allokiertem Speicherbereich (1 Word)
- 05h ungenutzt (11 Byte)
- 10h Allokierter Bereich (x Paragraphen)
-
- Jetzt können wir uns durch die Liste hangeln: das erste Byte eines MCB
- entscheidet darüber, ob die Liste weitergeht ('M') oder aufhört ('Z').
- Über die Länge des verwalteten Bereichs (Word an 3. Byte-Stelle) können
- wir die Lage des nächsten Blockes errechnen. Daß der MCB das Environment
- enthält, kann man durch den Vergleich des MCB-Segments+1 (hier beginnen
- die Daten) mit dem Segment des Command.com-Environments feststellen (das
- wir vorher bestimmt haben).
- Jetzt kennen wir über das Wort an der 3.Byte-Stelle dieses MCBs die Länge
- des Environments in Paragraphen (=16Byte), wodurch ein Überschreiben
- anderer MCBs oder Programme verhindert werden kann.
- Einen Haken gibt es immer noch: benutzt man UMBs (Upper Memory Blocks),
- gibt es auch MCBs für UMBs. Der Environment-Block von Command.com kann
- also auch in einem UMB liegen. Standardmäßig steht aber im Dos-Info-Block
- der erste MCB im normalen Speicher -> man bekommt die MCBs der UMBs erst
- gar nicht. Man muß also der DOS-Speicherverwaltung erst explizit mitteilen,
- daß UMBs in die Speicherverwaltung einbezogen werden sollen. Das geschieht
- mit INT 21H, AH=58, AL=03, BX=1. Vorher sollte man noch den augenblicklichen
- Status speichern (AL=02, Ergebnis in AL), um ihn am Programmende zurücksetzen
- zu können.
-
- email: vOlkerOth@aol.com
- hOmepage: members.aol.com/vOlkerOth
-