1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . R E G I S T R Y --
9 -- Copyright (C) 2001-2014, 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 3, 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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 ------------------------------------------------------------------------------
33 with GNAT
.Directory_Operations
;
35 package body GNAT
.Registry
is
39 ------------------------------
40 -- Binding to the Win32 API --
41 ------------------------------
43 subtype LONG
is Interfaces
.C
.long
;
44 subtype ULONG
is Interfaces
.C
.unsigned_long
;
45 subtype DWORD
is ULONG
;
47 type PULONG
is access all ULONG
;
48 subtype PDWORD
is PULONG
;
49 subtype LPDWORD
is PDWORD
;
51 subtype Error_Code
is LONG
;
53 subtype REGSAM
is LONG
;
55 type PHKEY
is access all HKEY
;
57 ERROR_SUCCESS
: constant Error_Code
:= 0;
59 REG_SZ
: constant := 1;
60 REG_EXPAND_SZ
: constant := 2;
62 function RegCloseKey
(Key
: HKEY
) return LONG
;
63 pragma Import
(Stdcall
, RegCloseKey
, "RegCloseKey");
65 function RegCreateKeyEx
72 lpSecurityAttributes
: Address
;
74 lpdwDisposition
: LPDWORD
)
76 pragma Import
(Stdcall
, RegCreateKeyEx
, "RegCreateKeyExA");
80 lpSubKey
: Address
) return LONG
;
81 pragma Import
(Stdcall
, RegDeleteKey
, "RegDeleteKeyA");
83 function RegDeleteValue
85 lpValueName
: Address
) return LONG
;
86 pragma Import
(Stdcall
, RegDeleteValue
, "RegDeleteValueA");
91 lpValueName
: Address
;
92 lpcbValueName
: LPDWORD
;
96 lpcbData
: LPDWORD
) return LONG
;
97 pragma Import
(Stdcall
, RegEnumValue
, "RegEnumValueA");
104 phkResult
: PHKEY
) return LONG
;
105 pragma Import
(Stdcall
, RegOpenKeyEx
, "RegOpenKeyExA");
107 function RegQueryValueEx
109 lpValueName
: Address
;
110 lpReserved
: LPDWORD
;
113 lpcbData
: LPDWORD
) return LONG
;
114 pragma Import
(Stdcall
, RegQueryValueEx
, "RegQueryValueExA");
116 function RegSetValueEx
118 lpValueName
: Address
;
122 cbData
: DWORD
) return LONG
;
123 pragma Import
(Stdcall
, RegSetValueEx
, "RegSetValueExA");
129 cchName
: DWORD
) return LONG
;
130 pragma Import
(Stdcall
, RegEnumKey
, "RegEnumKeyA");
132 ---------------------
133 -- Local Constants --
134 ---------------------
136 Max_Key_Size
: constant := 1_024
;
137 -- Maximum number of characters for a registry key
139 Max_Value_Size
: constant := 2_048
;
140 -- Maximum number of characters for a key's value
142 -----------------------
143 -- Local Subprograms --
144 -----------------------
146 function To_C_Mode
(Mode
: Key_Mode
) return REGSAM
;
147 -- Returns the Win32 mode value for the Key_Mode value
149 procedure Check_Result
(Result
: LONG
; Message
: String);
150 -- Checks value Result and raise the exception Registry_Error if it is not
151 -- equal to ERROR_SUCCESS. Message and the error value (Result) is added
152 -- to the exception message.
158 procedure Check_Result
(Result
: LONG
; Message
: String) is
161 if Result
/= ERROR_SUCCESS
then
162 raise Registry_Error
with
163 Message
& " (" & LONG
'Image (Result
) & ')';
171 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
;
204 C_Sub_Key
(C_Sub_Key
'First)'Address,
206 C_Class
(C_Class
'First)'Address,
207 REG_OPTION_NON_VOLATILE
,
210 New_Key
'Unchecked_Access,
211 Dispos
'Unchecked_Access);
213 Check_Result
(Result
, "Create_Key " & Sub_Key
);
221 procedure Delete_Key
(From_Key
: HKEY
; Sub_Key
: String) is
222 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
;
237 Result
:= RegDeleteValue
(From_Key
, C_Sub_Key
(C_Sub_Key
'First)'Address);
238 Check_Result
(Result
, "Delete_Value " & Sub_Key
);
245 procedure For_Every_Key
247 Recursive
: Boolean := False)
249 procedure Recursive_For_Every_Key
251 Recursive
: Boolean := False;
252 Quit
: in out Boolean);
254 -----------------------------
255 -- Recursive_For_Every_Key --
256 -----------------------------
258 procedure Recursive_For_Every_Key
260 Recursive
: Boolean := False;
261 Quit
: in out Boolean)
269 Sub_Key
: Interfaces
.C
.char_array
(1 .. Max_Key_Size
);
270 pragma Warnings
(Off
, Sub_Key
);
272 Size_Sub_Key
: aliased ULONG
;
275 function Current_Name
return String;
281 function Current_Name
return String is
283 return Interfaces
.C
.To_Ada
(Sub_Key
);
286 -- Start of processing for Recursive_For_Every_Key
290 Size_Sub_Key
:= Sub_Key
'Length;
294 (From_Key
, Index
, Sub_Key
(1)'Address, Size_Sub_Key
);
296 exit when not (Result
= ERROR_SUCCESS
);
298 Sub_Hkey
:= Open_Key
(From_Key
, Interfaces
.C
.To_Ada
(Sub_Key
));
300 Action
(Natural (Index
) + 1, Sub_Hkey
, Current_Name
, Quit
);
302 if not Quit
and then Recursive
then
303 Recursive_For_Every_Key
(Sub_Hkey
, True, Quit
);
306 Close_Key
(Sub_Hkey
);
312 end Recursive_For_Every_Key
;
316 Quit
: Boolean := False;
318 -- Start of processing for For_Every_Key
321 Recursive_For_Every_Key
(From_Key
, Recursive
, Quit
);
324 -------------------------
325 -- For_Every_Key_Value --
326 -------------------------
328 procedure For_Every_Key_Value
330 Expand
: Boolean := False)
332 use GNAT
.Directory_Operations
;
339 Sub_Key
: String (1 .. Max_Key_Size
);
340 pragma Warnings
(Off
, Sub_Key
);
342 Value
: String (1 .. Max_Value_Size
);
343 pragma Warnings
(Off
, Value
);
345 Size_Sub_Key
: aliased ULONG
;
346 Size_Value
: aliased ULONG
;
347 Type_Sub_Key
: aliased DWORD
;
353 Size_Sub_Key
:= Sub_Key
'Length;
354 Size_Value
:= Value
'Length;
360 Size_Sub_Key
'Unchecked_Access,
362 Type_Sub_Key
'Unchecked_Access,
364 Size_Value
'Unchecked_Access);
366 exit when not (Result
= ERROR_SUCCESS
);
370 if Type_Sub_Key
= REG_EXPAND_SZ
and then Expand
then
372 (Natural (Index
) + 1,
373 Sub_Key
(1 .. Integer (Size_Sub_Key
)),
374 Directory_Operations
.Expand_Path
375 (Value
(1 .. Integer (Size_Value
) - 1),
376 Directory_Operations
.DOS
),
379 elsif Type_Sub_Key
= REG_SZ
or else Type_Sub_Key
= REG_EXPAND_SZ
then
381 (Natural (Index
) + 1,
382 Sub_Key
(1 .. Integer (Size_Sub_Key
)),
383 Value
(1 .. Integer (Size_Value
) - 1),
391 end For_Every_Key_Value
;
399 Sub_Key
: String) return Boolean
404 New_Key
:= Open_Key
(From_Key
, Sub_Key
);
407 -- We have been able to open the key so it exists
412 when Registry_Error
=>
414 -- An error occurred, the key was not found
426 Mode
: Key_Mode
:= Read_Only
) return HKEY
430 C_Sub_Key
: constant String := Sub_Key
& ASCII
.NUL
;
431 C_Mode
: constant REGSAM
:= To_C_Mode
(Mode
);
433 New_Key
: aliased HKEY
;
440 C_Sub_Key
(C_Sub_Key
'First)'Address,
443 New_Key
'Unchecked_Access);
445 Check_Result
(Result
, "Open_Key " & Sub_Key
);
456 Expand
: Boolean := False) return String
458 use GNAT
.Directory_Operations
;
462 Value
: String (1 .. Max_Value_Size
);
463 pragma Warnings
(Off
, Value
);
465 Size_Value
: aliased ULONG
;
466 Type_Value
: aliased DWORD
;
468 C_Sub_Key
: constant String := Sub_Key
& ASCII
.NUL
;
472 Size_Value
:= Value
'Length;
477 C_Sub_Key
(C_Sub_Key
'First)'Address,
479 Type_Value
'Unchecked_Access,
480 Value
(Value
'First)'Address,
481 Size_Value
'Unchecked_Access);
483 Check_Result
(Result
, "Query_Value " & Sub_Key
& " key");
485 if Type_Value
= REG_EXPAND_SZ
and then Expand
then
486 return Directory_Operations
.Expand_Path
487 (Value
(1 .. Integer (Size_Value
- 1)),
488 Directory_Operations
.DOS
);
490 return Value
(1 .. Integer (Size_Value
- 1));
502 Expand
: Boolean := False)
504 C_Sub_Key
: constant String := Sub_Key
& ASCII
.NUL
;
505 C_Value
: constant String := Value
& ASCII
.NUL
;
511 Value_Type
:= (if Expand
then REG_EXPAND_SZ
else REG_SZ
);
516 C_Sub_Key
(C_Sub_Key
'First)'Address,
519 C_Value
(C_Value
'First)'Address,
522 Check_Result
(Result
, "Set_Value " & Sub_Key
& " key");
529 function To_C_Mode
(Mode
: Key_Mode
) return REGSAM
is
532 KEY_READ
: constant := 16#
20019#
;
533 KEY_WRITE
: constant := 16#
20006#
;
534 KEY_WOW64_64KEY
: constant := 16#
00100#
;
535 KEY_WOW64_32KEY
: constant := 16#
00200#
;
540 return KEY_READ
+ KEY_WOW64_32KEY
;
543 return KEY_READ
+ KEY_WRITE
+ KEY_WOW64_32KEY
;
546 return KEY_READ
+ KEY_WOW64_64KEY
;
548 when Read_Write_64
=>
549 return KEY_READ
+ KEY_WRITE
+ KEY_WOW64_64KEY
;