123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- (* Copyright (c) 1994 - 2000 Emil J. Zeller *)
- MODULE Registry IN Oberon; (** non-portable / source: Win32.Registry.Mod *) (* ejz *)
- IMPORT SYSTEM, Kernel32 IN A2, ADVAPI32 IN A2;
- (** This module provides an interface to the Windows registry. To read Oberon configuration data stored in the registry use Oberon.OpenScanner and the commands System.Set and System.Get . *)
- CONST
- (** root keys *)
- ClassesRoot* = ADVAPI32.HKEYClassesRoot; CurrentUser* = ADVAPI32.HKEYCurrentUser;
- (** result codes *)
- Done* = 0; Failed* = 1; NotFound* = 2;
- TYPE
- PathEnumerator* = PROCEDURE (path: ARRAY OF CHAR);
- KeyValueEnumerator* = PROCEDURE (key, value: ARRAY OF CHAR);
- VAR
- oberonRoot*, (** root path for all Oberon settings *)
- oberonSystem*: ARRAY Kernel32.MaxPath OF CHAR; (** path for System settings *)
- res*: LONGINT; (** Done, Failed, NotFound *)
- stamp*: LONGINT; (** Time stamp of last modification to the registry. *)
- hFile: Kernel32.HANDLE; logfile: BOOLEAN;
- PROCEDURE Append(VAR to: ARRAY OF CHAR; this: ARRAY OF CHAR);
- VAR i, j, l: LONGINT;
- BEGIN
- i := 0; WHILE to[i] # 0X DO INC(i) END;
- l := LEN(to)-1; j := 0;
- WHILE (i < l) & (this[j] # 0X) DO
- to[i] := this[j]; INC(i); INC(j)
- END;
- to[i] := 0X
- END Append;
- PROCEDURE AppendCh(VAR to: ARRAY OF CHAR; this: CHAR);
- VAR i: LONGINT;
- BEGIN
- i := 0; WHILE to[i] # 0X DO INC(i) END;
- IF i < (LEN(to)-1) THEN
- to[i] := this; to[i+1] := 0X
- END
- END AppendCh;
- (** Get the full path to Oberon settings stored under key.
- Note: Oberon uses CurrentUser as root key. *)
- PROCEDURE OberonPath*(path: ARRAY OF CHAR; VAR fullPath: ARRAY OF CHAR);
- BEGIN
- COPY(oberonRoot, fullPath); AppendCh(fullPath, "\"); Append(fullPath, path)
- END OberonPath;
- (** Set a key/value pair, key = "" sets the default value for path. *)
- PROCEDURE SetKeyValue*(root: ADVAPI32.HKEY; path, key, value: ARRAY OF CHAR);
- VAR hKey: ADVAPI32.HKEY; i: LONGINT;
- BEGIN
- IF ADVAPI32.RegCreateKeyEx(root, path, 0, NIL, ADVAPI32.RegOptionNonVolatile, {ADVAPI32.KeySetValue, ADVAPI32.KeyCreateSubKey}, NIL, hKey, NIL) # ADVAPI32.Success THEN
- res := NotFound; RETURN
- END;
- i := 0; WHILE value[i] # 0X DO INC(i) END; INC(i);
- IF ADVAPI32.RegSetValueEx(hKey, key, 0, ADVAPI32.RegSZ, value, i) = ADVAPI32.Success THEN
- INC(stamp); res := Done
- ELSE
- res := Failed
- END;
- ADVAPI32.RegCloseKey(hKey)
- END SetKeyValue;
- (** Retrieve the value stored under key. use key = "" to retrieve the default value for path. *)
- PROCEDURE GetKeyValue*(root: ADVAPI32.HKEY; path, key: ARRAY OF CHAR; VAR value: ARRAY OF CHAR);
- VAR hKey: ADVAPI32.HKEY; type, len, ret: LONGINT; buf: POINTER TO ARRAY OF CHAR;
- BEGIN
- IF ADVAPI32.RegOpenKeyEx(root, path, 0, {ADVAPI32.KeyQueryValue}, hKey) # ADVAPI32.Success THEN
- res := NotFound; RETURN
- END;
- len := LEN(value); type := ADVAPI32.RegNone;
- ret := ADVAPI32.RegQueryValueEx(hKey, key, NIL, type, value, len);
- IF (type # ADVAPI32.RegSZ) OR (ret # ADVAPI32.Success) THEN
- IF (type = ADVAPI32.RegSZ) & (ret = ADVAPI32.ErrorMoreData) THEN
- NEW(buf, len+1);
- ADVAPI32.RegQueryValueEx(hKey, key, NIL, type, buf^, len);
- COPY(buf^, value); res := Done
- ELSE
- res := NotFound
- END
- ELSE
- res := Done
- END;
- ADVAPI32.RegCloseKey(hKey)
- END GetKeyValue;
- (** Delete key and its value, key = "" deletes the default value for path. *)
- PROCEDURE DeleteKeyValue*(root: ADVAPI32.HKEY; path, key: ARRAY OF CHAR);
- VAR hKey: ADVAPI32.HKEY;
- BEGIN
- IF ADVAPI32.RegOpenKeyEx(root, path, 0, {ADVAPI32.KeySetValue}, hKey) # ADVAPI32.Success THEN
- res := NotFound; RETURN
- END;
- IF ADVAPI32.RegDeleteValue(hKey, key) = ADVAPI32.Success THEN
- INC(stamp); res := Done
- ELSE
- res := NotFound
- END;
- ADVAPI32.RegCloseKey(hKey)
- END DeleteKeyValue;
- (** Recursive delete all sub-paths, keys and values in path.
- Note: be very careful when using this procedure!!! *)
- PROCEDURE DeletePath*(root: ADVAPI32.HKEY; path: ARRAY OF CHAR);
- VAR buffer: ARRAY Kernel32.MaxPath OF CHAR; hKey: ADVAPI32.HKEY; size: LONGINT;
- BEGIN
- IF ADVAPI32.RegOpenKeyEx(root, path, 0, ADVAPI32.KeyAllAccess, hKey) # ADVAPI32.Success THEN
- res := NotFound; RETURN
- END;
- size := Kernel32.MaxPath;
- WHILE ADVAPI32.RegEnumKeyEx(hKey, 0, buffer, size, NIL, NIL, NIL, NIL) = ADVAPI32.Success DO
- DeletePath(hKey, buffer);
- IF res # Done THEN
- ADVAPI32.RegCloseKey(hKey); RETURN
- END;
- size := Kernel32.MaxPath
- END;
- ADVAPI32.RegCloseKey(hKey);
- IF ADVAPI32.RegDeleteKey(root, path) = ADVAPI32.Success THEN
- INC(stamp); res := Done
- ELSE
- res := Failed
- END
- END DeletePath;
- (** Enumerate all sub-paths in path. *)
- PROCEDURE EnumeratePath*(root: ADVAPI32.HKEY; path: ARRAY OF CHAR; enum: PathEnumerator);
- VAR subPath: ARRAY Kernel32.MaxPath OF CHAR; hKey: ADVAPI32.HKEY; ret, i, size: LONGINT;
- BEGIN
- ret := ADVAPI32.RegOpenKeyEx(root, path, 0, {ADVAPI32.KeyEnumerateSubKeys}, hKey);
- IF ret # ADVAPI32.Success THEN
- res := NotFound; RETURN
- END;
- i := 0;
- WHILE ret = ADVAPI32.Success DO
- size := Kernel32.MaxPath;
- ret := ADVAPI32.RegEnumKeyEx(hKey, i, subPath, size, NIL, NIL, NIL, NIL);
- IF ret = ADVAPI32.Success THEN enum(subPath) END;
- INC(i)
- END;
- ADVAPI32.RegCloseKey(hKey); res := Done
- END EnumeratePath;
- (** Enumerate all key/value pairs in path.*)
- PROCEDURE EnumerateKeyValue*(root: ADVAPI32.HKEY; path: ARRAY OF CHAR; enum: KeyValueEnumerator);
- VAR
- key, value: ARRAY Kernel32.MaxPath OF CHAR; hKey: ADVAPI32.HKEY;
- ret, i, type, kLen, vLen: LONGINT;
- BEGIN
- ret := ADVAPI32.RegOpenKeyEx(root, path, 0, {ADVAPI32.KeyQueryValue}, hKey);
- IF ret # ADVAPI32.Success THEN
- res := NotFound; RETURN
- END;
- i := 0;
- WHILE ret = ADVAPI32.Success DO
- kLen := Kernel32.MaxPath; vLen := Kernel32.MaxPath; type := ADVAPI32.RegNone;
- ret := ADVAPI32.RegEnumValue(hKey, i, key, kLen, NIL, type, value, vLen);
- IF (ret = ADVAPI32.Success) & (type = ADVAPI32.RegSZ) THEN enum(key, value) END;
- INC(i)
- END;
- ADVAPI32.RegCloseKey(hKey); res := Done
- END EnumerateKeyValue;
- PROCEDURE OutputFileString(VAR str: ARRAY OF CHAR);
- VAR n: LONGINT; b: Kernel32.BOOL;
- BEGIN
- n := 0; WHILE str[n] # 0X DO INC(n) END;
- b := Kernel32.WriteFile(hFile, str, n, n, NIL);
- IF logfile THEN Kernel32.FlushFileBuffers(hFile) END
- END OutputFileString;
- (*
- PROCEDURE InitConsole();
- VAR rect: Kernel32.SmallRect; file: ARRAY 260 OF CHAR; con: ARRAY 64 OF CHAR; i, j: LONGINT;
- BEGIN
- Kernel32.OutputString := NIL; logfile := FALSE; hFile := Kernel32.InvalidHandleValue;
- GetKeyValue(CurrentUser, oberonSystem, "Console", con);
- IF res = Done THEN
- IF con[0] = '"' THEN con[0] := con[1] END;
- IF CAP(con[0]) = "C" THEN (* console window *)
- con := "ETH Oberon - Console";
- Kernel32.AllocConsole(); Kernel32.SetConsoleTitle(con);
- hFile := Kernel32.GetStdHandle(Kernel32.STDOutput);
- Kernel32.SetConsoleScreenBufferSize(hFile, 80 + ASH(1024, 16));
- rect.top := 0; rect. left := 0; rect.bottom := 24; rect.right := 79;
- Kernel32.SetConsoleWindowInfo(hFile, Kernel32.True, rect)
- ELSIF CAP(con[0]) = "S" THEN (* standard output -> requires CUI*)
- hFile := Kernel32.GetStdHandle(Kernel32.STDOutput)
- ELSIF CAP(con[0]) = "F" THEN (* log file *)
- con := "Oberon.Log"; logfile := TRUE;
- Kernel32.GetModuleFileName(Kernel.hInstance, file, 260);
- i := 0; j := 0;
- WHILE file[i] # 0X DO
- IF file[i] = "\" THEN j := i+1 END;
- INC(i)
- END;
- file[j] := 0X; i := 0;
- WHILE con[i] # 0X DO
- file[j] := con[i]; INC(i); INC(j)
- END;
- file[j] := 0X;
- hFile := Kernel32.CreateFile(file, {Kernel32.GenericWrite}, {Kernel32.FileShareRead}, NIL, Kernel32.CreateAlways, {Kernel32.FileAttributeNormal}, Kernel32.NULL);
- i := 1;
- WHILE (i <= 9) & (hFile = Kernel32.InvalidHandleValue) DO
- file[j] := CHR(i+ORD("0")); file[j+11] := 0X;
- hFile := Kernel32.CreateFile(file, {Kernel32.GenericWrite}, {Kernel32.FileShareRead}, NIL, Kernel32.CreateAlways, {Kernel32.FileAttributeNormal}, Kernel32.NULL);
- INC(i)
- END
- END;
- IF hFile # Kernel32.InvalidHandleValue THEN
- Kernel32.OutputString := OutputFileString
- ELSIF (CAP(con[0]) # "N") & (Kernel32.OutputString = NIL) THEN (* debugger *)
- Kernel32.OutputString := Kernel32.OutputDebugString
- END
- ELSE
- Kernel32.OutputString := Kernel32.OutputDebugString
- END;
- Modules.InstallTermHandler(ShutdownConsole)
- END InitConsole;
- PROCEDURE ShutdownConsole();
- BEGIN
- IF logfile & (hFile # Kernel32.InvalidHandleValue) THEN
- Kernel32.CloseHandle(hFile); hFile := Kernel32.InvalidHandleValue
- END;
- Kernel32.OutputString := Kernel32.OutputDebugString
- END ShutdownConsole;
- *)
- PROCEDURE Init;
- VAR
- file, name, value, software, version: ARRAY Kernel32.MaxPath OF CHAR;
- buf: POINTER TO ARRAY OF SYSTEM.BYTE; adr: ADDRESS; len, i: LONGINT; ch: CHAR;
- BEGIN
- res := Done; stamp := 0;
- Kernel32.GetModuleFileName(Kernel32.hInstance, file, Kernel32.MaxPath);
- len := ADVAPI32.GetFileVersionInfoSize(file, NIL);
- NEW(buf, len);
- ADVAPI32.GetFileVersionInfo(file, 0, len, buf^);
- ADVAPI32.VerQueryValue(buf^, "\StringFileInfo\040904e4\FileDescription", adr, len);
- IF len >= Kernel32.MaxPath THEN HALT(99) END;
- SYSTEM.MOVE(adr, ADDRESSOF(software), len);
- ADVAPI32.VerQueryValue(buf^, "\StringFileInfo\040904e4\FileVersion", adr, len);
- IF len >= Kernel32.MaxPath THEN HALT(99) END;
- SYSTEM.MOVE(adr, ADDRESSOF(version), len);
- (* cmd { "-" name [ "=" value ] } *)
- name := ""; i := 0;
- adr := Kernel32.GetCommandLine();
- REPEAT
- SYSTEM.GET(adr, ch); INC(adr);
- IF ch = "-" THEN
- value[i] := 0X; i := 0;
- IF name = "Registry" THEN COPY(value, version) END
- ELSIF ch = "=" THEN
- value[i] := 0X; i := 0; COPY(value, name)
- ELSIF ch > " " THEN
- value[i] := ch; INC(i)
- ELSE
- value[i] := 0X
- END
- UNTIL (ch = 0X) OR (i >= LEN(name)) ;
- IF (i > 0) & (name = "Registry") THEN
- value[i] := 0X; COPY(value, version)
- END;
- oberonRoot := "Software\"; Append(oberonRoot, software);
- AppendCh(oberonRoot, "\"); Append(oberonRoot, version);
- OberonPath("System", oberonSystem);
- END Init;
- BEGIN
- Init(); (* InitConsole() *)
- END Registry.
|