{ Subject: Enviro.pas Unit to change Dos Vars permanently Had this floating round, hope it helps someone. It works under Dos 5, NDos 6.01, and should work For any other Dos as well, no guarantees tho' . } Unit Enviro; Interface Var EnvSeg, EnvOfs, EnvSize : Word; Function FindEnv:Boolean; Function IsEnvVar(Variable : String;Var Value : String):Boolean; Procedure ChangeEnvVar(Variable,NewVal : String); Implementation Uses Dos; Type MemoryControlBlock = {MCB -- only needed fields are shown} Record Blocktag : Byte; BlockOwner : Word; BlockSize : Word; misc : Array[1..3] of Byte; ProgramName: Array[1..8] of Char; end; ProgramSegmentPrefix = {PSP -- only needed fields are shown} Record { offset } PSPtag : Word; { $20CD or $27CD if PSP} { 00 $00 } misc : Array[1..21] of Word; { 02 $02 } Environment: Word { 44 $2C } end; Var MCB : ^MemoryControlBlock; r : Registers; Found : Boolean; SegMent : Word; EnvPtr : Word; Startofs : Word; Function FindEnvMCB:Boolean; Var b : Char; BlockType: String[12]; Bytes : LongInt; i : Word; last : Char; MCBenv : ^MemoryControlBlock; MCBowner : ^MemoryControlBlock; psp : ^ProgramSegmentPrefix; begin FindEnvMCB := False; Bytes := LongInt(MCB^.BlockSize) SHL 4; {size of MCB in Bytes} if mcb^.blockowner = 0 then { free space } else begin psp := Ptr(MCB^.BlockOwner,0); {possible PSP} if (psp^.PSPtag = $20CD) or (psp^.PSPtag = $27CD) then begin MCBenv := Ptr(psp^.Environment-1,0); if MCB^.Blockowner <> (segment + 1) then if psp^.Environment = (segment + 1) then if MCB^.BlockOwner = MCBenv^.BlockOwner then begin EnvSize := MCBenv^.BlockSize SHL 4; {multiply by 16} EnvSeg := PSP^.Environment; EnvOfs := 0; FindEnvMCB := True; end end end; end; Function FindEnv:Boolean; begin r.AH := $52; {undocumented Dos Function that returns a Pointer} Intr ($21,r); {to the Dos 'list of lists' } segment := MemW[r.ES:r.BX-2]; {segment address of first MCB found at} {offset -2 from List of List Pointer } Repeat MCB := Ptr(segment,0); {MCB^ points to first MCB} Found := FindEnvMcb; {Look at each MCB} segment := segment + MCB^.BlockSize + 1 Until (Found) or (MCB^.Blocktag = $5A); FindEnv := Found; end; Function IsEnvVar(Variable : String;Var Value : String):Boolean; Var Temp : String; ch : Char; i : Word; FoundIt : Boolean; begin Variable := Variable + '='; FoundIt := False; i := EnvOfs; Repeat Temp := ''; StartOfs := I; Repeat ch := Char(Mem[EnvSeg:i]); if Ch <> #0 then Temp := Temp + Ch; inc(i); Until (Ch = #0) or (I > EnvSize); if Ch = #0 then begin FoundIt := (Pos(Variable,Temp) = 1); if FoundIt then Value := Copy(Temp,Length(Variable)+1,255); end; Until (FoundIt) or (I > EnvSize); IsEnvVar := FoundIt; end; Procedure ChangeEnvVar(Variable,NewVal : String); Var OldVal : String; p1,p2 : Pointer; i,j : Word; ch, LastCh : Char; begin if IsEnvVar(Variable,OldVal) then begin p1 := Ptr(EnvSeg,StartOfs + Length(Variable)+1); if Length(OldVal) = Length(NewVal) then Move(NewVal[1],p1^,Length(NewVal)) else if Length(OldVal) > Length(NewVal) then begin Move(NewVal[1],p1^,Length(NewVal)); p1 := ptr(EnvSeg,StartOfs + Length(Variable)+Length(OldVal)+1); p2 := ptr(EnvSeg,StartOfs + Length(Variable)+Length(NewVal)+1); Move(p1^,p2^,EnvSize - ofs(p1^)); end else begin { newVar is longer than oldVar } p2 := ptr(EnvSeg,StartOfs + Length(Variable)+Length(NewVal)-length(OldVal)+1); Move(p1^,p2^,EnvSize - ofs(p2^)); Move(NewVal[1],p1^,Length(NewVal)); end; end else { creating a new Var } begin i := EnvOfs; ch := Char(Mem[EnvSeg:i]); Repeat LastCh := Ch; inc(i); ch := Char(Mem[EnvSeg:i]); Until (i > EnvSize) or ((LastCh = #0) and (Ch = #0)); if i < EnvSize then begin j := 1; Variable := Variable + '=' + NewVal + #0 + #0; While (J < Length(Variable)) and (I <= EnvSize) do begin Mem[EnvSeg:i] := ord(Variable[j]); inc(i); Inc(j); end; end; end; end; begin end. { TEST Program } Uses Enviro; Var EnvVar : String; begin if FindEnv then begin Writeln('Found the Enviroment !!'); Writeln('Env is at address ',EnvSeg,':',EnvOfs); Writeln('And is ',EnvSize,' Bytes long'); if IsEnvVar('COMSPEC',EnvVar) then Writeln('COMSPEC = ',EnvVar) else Writeln('COMSPEC is not set'); if IsEnvVar('NewVar',EnvVar) then Writeln('NewVar = ',EnvVar) else Writeln('NewVar is not set'); ChangeEnvVar('NewVar','This is a new Var'); if IsEnvVar('NewVar',EnvVar) then Writeln('NewVar = ',EnvVar) else Writeln('NewVar is not set'); ChangeEnvVar('NewVar','NewVar is now this'); if IsEnvVar('NewVar',EnvVar) then Writeln('NewVar = ',EnvVar) else Writeln('NewVar is not set'); end; end.