1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . R E G I S T R Y --
9 -- Copyright (C) 2001-2009, 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#;
541 return KEY_READ + KEY_WRITE;