@@ -25,6 +25,10 @@ with Ada.Strings.UTF_Encoding.Wide_Strings;
2525with Ada.Wide_Characters.Handling ;
2626with Ada.Environment_Variables ;
2727with GNATCOLL.String_Builders ;
28+ with GNATCOLL.OS.Win32.Process ;
29+ pragma Warnings(Off);
30+ with System.Address_To_Access_Conversions ;
31+ pragma Warning(On);
2832
2933package body GNATCOLL.OS.Process_Types is
3034
@@ -33,10 +37,27 @@ package body GNATCOLL.OS.Process_Types is
3337 package Env_Vars renames Ada.Environment_Variables;
3438 package WCH renames Ada.Wide_Characters.Handling;
3539
40+ type EnvironW is array (1 .. Integer'Last) of Wide_Character;
41+ pragma Suppress_Initialization(EnvironW);
42+ type EnvironW_Access is access all EnvironW;
43+ for EnvironW_Access'Storage_Size use 0 ;
44+ -- This type is used to map the address returned by GetEnvironmentStrings
45+ -- to a Wide_Character array. Initialization is suppressed as only a part
46+ -- of the declared object will be used.
47+ -- The 0 storage size ensure we cannot call "new"
48+
49+ package EnvironW_Ops is new System.Address_To_Access_Conversions(EnvironW);
50+ use EnvironW_Ops;
51+ -- Provides To_Pointer to convert an Address to an EnvironW_Access.
52+
3653 Minimal_Env : Environ;
3754
3855 procedure Add_Minimal_Env (Env : in out Environ);
3956
57+ -- -------------------
58+ -- Add_Minimal_Env --
59+ -- -------------------
60+
4061 procedure Add_Minimal_Env (Env : in out Environ) is
4162 begin
4263 if Env_Vars.Exists (" SYSTEMROOT" ) then
@@ -91,14 +112,55 @@ package body GNATCOLL.OS.Process_Types is
91112 -- ----------
92113
93114 procedure Import (Env : in out Environ) is
94- procedure Import_Var (Name, Value : String);
115+ use GNATCOLL.OS.Win32.Process;
116+ use GNATCOLL.OS.Win32;
95117
96- procedure Import_Var (Name, Value : String) is
97- begin
98- Set_Variable (Env, Name, Value);
99- end Import_Var ;
118+ -- Fetch the current process environment
119+ Env_Addr : System.Address := GetEnvironmentStrings;
120+ Env_Ptr : EnvironW_Access := EnvironW_Access(To_Pointer (Env_Addr));
121+
122+ Free_Result : BOOL;
123+
124+ -- Start of a variable definition
125+ Start : Integer := 0 ;
126+
127+ -- Current position in the environ block
128+ Idx : Integer := 1 ;
129+
130+ WNUL : constant Wide_Character := Wide_Character'Val (0 );
131+ use all type System.Address;
100132 begin
101- Env_Vars.Iterate (Import_Var'Unrestricted_Access);
133+ -- Start by resetting the environment
134+ Env.Inherited := False;
135+ WSLB.Deallocate (Env.Env);
136+
137+ -- Note that the environment may contain invalid UTF-16 strings. We
138+ -- should just ignore that and pass the value to our structure.
139+ loop
140+ if Env_Ptr (Idx) /= WNUL then
141+ if Start = 0 then
142+ Start := Idx;
143+ end if ;
144+ else
145+ -- A NUL character marks the end of a variable definition
146+ if Start /= 0 then
147+ WSLB.Append (Env.Env, Wide_String (Env_Ptr (Start .. Idx - 1 )));
148+ Start := 0 ;
149+ end if ;
150+
151+ -- If a NUL character follows the end of a variable definition,
152+ -- the end of the environment block has been reached.
153+ exit when Env_Ptr (Idx + 1 ) = WNUL;
154+ end if ;
155+
156+ Idx := Idx + 1 ;
157+ end loop ;
158+
159+ Free_Result :=
160+ GNATCOLL.OS.Win32.Process.FreeEnvironmentStrings (Env_Addr);
161+ if Free_Result = BOOL_FALSE then
162+ raise OS_Error with " error while deallocating environment block" ;
163+ end if ;
102164 end Import ;
103165
104166 -- -----------
0 commit comments