1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . R E G I S T R Y --
9 -- Copyright (C) 2001-2005, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 ------------------------------------------------------------------------------
36 with GNAT
.Directory_Operations
;
38 package body GNAT
.Registry
is
43 ------------------------------
44 -- Binding to the Win32 API --
45 ------------------------------
47 subtype LONG
is Interfaces
.C
.long
;
48 subtype ULONG
is Interfaces
.C
.unsigned_long
;
49 subtype DWORD
is ULONG
;
51 type PULONG
is access all ULONG
;
52 subtype PDWORD
is PULONG
;
53 subtype LPDWORD
is PDWORD
;
55 subtype Error_Code
is LONG
;
57 subtype REGSAM
is LONG
;
59 type PHKEY
is access all HKEY
;
61 ERROR_SUCCESS
: constant Error_Code
:= 0;
63 REG_SZ
: constant := 1;
64 REG_EXPAND_SZ
: constant := 2;
66 function RegCloseKey
(Key
: HKEY
) return LONG
;
67 pragma Import
(Stdcall
, RegCloseKey
, "RegCloseKey");
69 function RegCreateKeyEx
76 lpSecurityAttributes
: Address
;
78 lpdwDisposition
: LPDWORD
)
80 pragma Import
(Stdcall
, RegCreateKeyEx
, "RegCreateKeyExA");
84 lpSubKey
: Address
) return LONG
;
85 pragma Import
(Stdcall
, RegDeleteKey
, "RegDeleteKeyA");
87 function RegDeleteValue
89 lpValueName
: Address
) return LONG
;
90 pragma Import
(Stdcall
, RegDeleteValue
, "RegDeleteValueA");
95 lpValueName
: Address
;
96 lpcbValueName
: LPDWORD
;
100 lpcbData
: LPDWORD
) return LONG
;
101 pragma Import
(Stdcall
, RegEnumValue
, "RegEnumValueA");
103 function RegOpenKeyEx
108 phkResult
: PHKEY
) return LONG
;
109 pragma Import
(Stdcall
, RegOpenKeyEx
, "RegOpenKeyExA");
111 function RegQueryValueEx
113 lpValueName
: Address
;
114 lpReserved
: LPDWORD
;
117 lpcbData
: LPDWORD
) return LONG
;
118 pragma Import
(Stdcall
, RegQueryValueEx
, "RegQueryValueExA");
120 function RegSetValueEx
122 lpValueName
: Address
;
126 cbData
: DWORD
) return LONG
;
127 pragma Import
(Stdcall
, RegSetValueEx
, "RegSetValueExA");
129 ---------------------
130 -- Local Constants --
131 ---------------------
133 Max_Key_Size
: constant := 1_024
;
134 -- Maximum number of characters for a registry key
136 Max_Value_Size
: constant := 2_048
;
137 -- Maximum number of characters for a key's value
139 -----------------------
140 -- Local Subprograms --
141 -----------------------
143 function To_C_Mode
(Mode
: Key_Mode
) return REGSAM
;
144 -- Returns the Win32 mode value for the Key_Mode value
146 procedure Check_Result
(Result
: LONG
; Message
: String);
147 -- Checks value Result and raise the exception Registry_Error if it is not
148 -- equal to ERROR_SUCCESS. Message and the error value (Result) is added
149 -- to the exception message.
155 procedure Check_Result
(Result
: LONG
; Message
: String) is
159 if Result
/= ERROR_SUCCESS
then
160 Exceptions
.Raise_Exception
161 (Registry_Error
'Identity,
162 Message
& " (" & LONG
'Image (Result
) & ')');
170 procedure Close_Key
(Key
: HKEY
) is
174 Result
:= RegCloseKey
(Key
);
175 Check_Result
(Result
, "Close_Key");
185 Mode
: Key_Mode
:= Read_Write
) return HKEY
190 REG_OPTION_NON_VOLATILE
: constant := 16#
0#
;
192 C_Sub_Key
: constant String := Sub_Key
& ASCII
.Nul
;
193 C_Class
: constant String := "" & ASCII
.Nul
;
194 C_Mode
: constant REGSAM
:= To_C_Mode
(Mode
);
196 New_Key
: aliased HKEY
;
198 Dispos
: aliased DWORD
;
201 Result
:= RegCreateKeyEx
203 C_Sub_Key
(C_Sub_Key
'First)'Address,
205 C_Class
(C_Class
'First)'Address,
206 REG_OPTION_NON_VOLATILE
,
209 New_Key
'Unchecked_Access,
210 Dispos
'Unchecked_Access);
212 Check_Result
(Result
, "Create_Key " & Sub_Key
);
220 procedure Delete_Key
(From_Key
: HKEY
; Sub_Key
: String) is
221 C_Sub_Key
: constant String := Sub_Key
& ASCII
.Nul
;
225 Result
:= RegDeleteKey
(From_Key
, C_Sub_Key
(C_Sub_Key
'First)'Address);
226 Check_Result
(Result
, "Delete_Key " & Sub_Key
);
233 procedure Delete_Value
(From_Key
: HKEY
; Sub_Key
: String) is
234 C_Sub_Key
: constant String := Sub_Key
& ASCII
.Nul
;
238 Result
:= RegDeleteValue
(From_Key
, C_Sub_Key
(C_Sub_Key
'First)'Address);
239 Check_Result
(Result
, "Delete_Value " & Sub_Key
);
242 -------------------------
243 -- For_Every_Key_Value --
244 -------------------------
246 procedure For_Every_Key_Value
248 Expand
: Boolean := False)
250 use GNAT
.Directory_Operations
;
257 Sub_Key
: String (1 .. Max_Key_Size
);
258 pragma Warnings
(Off
, Sub_Key
);
260 Value
: String (1 .. Max_Value_Size
);
261 pragma Warnings
(Off
, Value
);
263 Size_Sub_Key
: aliased ULONG
;
264 Size_Value
: aliased ULONG
;
265 Type_Sub_Key
: aliased DWORD
;
271 Size_Sub_Key
:= Sub_Key
'Length;
272 Size_Value
:= Value
'Length;
274 Result
:= RegEnumValue
277 Size_Sub_Key
'Unchecked_Access,
279 Type_Sub_Key
'Unchecked_Access,
281 Size_Value
'Unchecked_Access);
283 exit when not (Result
= ERROR_SUCCESS
);
287 if Type_Sub_Key
= REG_EXPAND_SZ
and then Expand
then
288 Action
(Natural (Index
) + 1,
289 Sub_Key
(1 .. Integer (Size_Sub_Key
)),
290 Directory_Operations
.Expand_Path
291 (Value
(1 .. Integer (Size_Value
) - 1),
292 Directory_Operations
.DOS
),
295 elsif Type_Sub_Key
= REG_SZ
or else Type_Sub_Key
= REG_EXPAND_SZ
then
296 Action
(Natural (Index
) + 1,
297 Sub_Key
(1 .. Integer (Size_Sub_Key
)),
298 Value
(1 .. Integer (Size_Value
) - 1),
306 end For_Every_Key_Value
;
314 Sub_Key
: String) return Boolean
319 New_Key
:= Open_Key
(From_Key
, Sub_Key
);
322 -- We have been able to open the key so it exists
327 when Registry_Error
=>
329 -- An error occurred, the key was not found
341 Mode
: Key_Mode
:= Read_Only
) return HKEY
345 C_Sub_Key
: constant String := Sub_Key
& ASCII
.Nul
;
346 C_Mode
: constant REGSAM
:= To_C_Mode
(Mode
);
348 New_Key
: aliased HKEY
;
352 Result
:= RegOpenKeyEx
354 C_Sub_Key
(C_Sub_Key
'First)'Address,
357 New_Key
'Unchecked_Access);
359 Check_Result
(Result
, "Open_Key " & Sub_Key
);
370 Expand
: Boolean := False) return String
372 use GNAT
.Directory_Operations
;
376 Value
: String (1 .. Max_Value_Size
);
377 pragma Warnings
(Off
, Value
);
379 Size_Value
: aliased ULONG
;
380 Type_Value
: aliased DWORD
;
382 C_Sub_Key
: constant String := Sub_Key
& ASCII
.Nul
;
386 Size_Value
:= Value
'Length;
388 Result
:= RegQueryValueEx
390 C_Sub_Key
(C_Sub_Key
'First)'Address,
392 Type_Value
'Unchecked_Access,
393 Value
(Value
'First)'Address,
394 Size_Value
'Unchecked_Access);
396 Check_Result
(Result
, "Query_Value " & Sub_Key
& " key");
398 if Type_Value
= REG_EXPAND_SZ
and then Expand
then
399 return Directory_Operations
.Expand_Path
400 (Value
(1 .. Integer (Size_Value
- 1)), Directory_Operations
.DOS
);
402 return Value
(1 .. Integer (Size_Value
- 1));
415 C_Sub_Key
: constant String := Sub_Key
& ASCII
.Nul
;
416 C_Value
: constant String := Value
& ASCII
.Nul
;
421 Result
:= RegSetValueEx
423 C_Sub_Key
(C_Sub_Key
'First)'Address,
426 C_Value
(C_Value
'First)'Address,
429 Check_Result
(Result
, "Set_Value " & Sub_Key
& " key");
436 function To_C_Mode
(Mode
: Key_Mode
) return REGSAM
is
439 KEY_READ
: constant := 16#
20019#
;
440 KEY_WRITE
: constant := 16#
20006#
;
448 return KEY_READ
+ KEY_WRITE
;