Windows.Oberon.Registry.Mod 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. (* Copyright (c) 1994 - 2000 Emil J. Zeller *)
  2. MODULE Registry IN Oberon; (** non-portable / source: Win32.Registry.Mod *) (* ejz *)
  3. IMPORT SYSTEM, Kernel32 IN A2, ADVAPI32 IN A2;
  4. (** 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 . *)
  5. CONST
  6. (** root keys *)
  7. ClassesRoot* = ADVAPI32.HKEYClassesRoot; CurrentUser* = ADVAPI32.HKEYCurrentUser;
  8. (** result codes *)
  9. Done* = 0; Failed* = 1; NotFound* = 2;
  10. TYPE
  11. PathEnumerator* = PROCEDURE (path: ARRAY OF CHAR);
  12. KeyValueEnumerator* = PROCEDURE (key, value: ARRAY OF CHAR);
  13. VAR
  14. oberonRoot*, (** root path for all Oberon settings *)
  15. oberonSystem*: ARRAY Kernel32.MaxPath OF CHAR; (** path for System settings *)
  16. res*: LONGINT; (** Done, Failed, NotFound *)
  17. stamp*: LONGINT; (** Time stamp of last modification to the registry. *)
  18. hFile: Kernel32.HANDLE; logfile: BOOLEAN;
  19. PROCEDURE Append(VAR to: ARRAY OF CHAR; this: ARRAY OF CHAR);
  20. VAR i, j, l: LONGINT;
  21. BEGIN
  22. i := 0; WHILE to[i] # 0X DO INC(i) END;
  23. l := LEN(to)-1; j := 0;
  24. WHILE (i < l) & (this[j] # 0X) DO
  25. to[i] := this[j]; INC(i); INC(j)
  26. END;
  27. to[i] := 0X
  28. END Append;
  29. PROCEDURE AppendCh(VAR to: ARRAY OF CHAR; this: CHAR);
  30. VAR i: LONGINT;
  31. BEGIN
  32. i := 0; WHILE to[i] # 0X DO INC(i) END;
  33. IF i < (LEN(to)-1) THEN
  34. to[i] := this; to[i+1] := 0X
  35. END
  36. END AppendCh;
  37. (** Get the full path to Oberon settings stored under key.
  38. Note: Oberon uses CurrentUser as root key. *)
  39. PROCEDURE OberonPath*(path: ARRAY OF CHAR; VAR fullPath: ARRAY OF CHAR);
  40. BEGIN
  41. COPY(oberonRoot, fullPath); AppendCh(fullPath, "\"); Append(fullPath, path)
  42. END OberonPath;
  43. (** Set a key/value pair, key = "" sets the default value for path. *)
  44. PROCEDURE SetKeyValue*(root: ADVAPI32.HKEY; path, key, value: ARRAY OF CHAR);
  45. VAR hKey: ADVAPI32.HKEY; i: LONGINT;
  46. BEGIN
  47. IF ADVAPI32.RegCreateKeyEx(root, path, 0, NIL, ADVAPI32.RegOptionNonVolatile, {ADVAPI32.KeySetValue, ADVAPI32.KeyCreateSubKey}, NIL, hKey, NIL) # ADVAPI32.Success THEN
  48. res := NotFound; RETURN
  49. END;
  50. i := 0; WHILE value[i] # 0X DO INC(i) END; INC(i);
  51. IF ADVAPI32.RegSetValueEx(hKey, key, 0, ADVAPI32.RegSZ, value, i) = ADVAPI32.Success THEN
  52. INC(stamp); res := Done
  53. ELSE
  54. res := Failed
  55. END;
  56. ADVAPI32.RegCloseKey(hKey)
  57. END SetKeyValue;
  58. (** Retrieve the value stored under key. use key = "" to retrieve the default value for path. *)
  59. PROCEDURE GetKeyValue*(root: ADVAPI32.HKEY; path, key: ARRAY OF CHAR; VAR value: ARRAY OF CHAR);
  60. VAR hKey: ADVAPI32.HKEY; type, len, ret: LONGINT; buf: POINTER TO ARRAY OF CHAR;
  61. BEGIN
  62. IF ADVAPI32.RegOpenKeyEx(root, path, 0, {ADVAPI32.KeyQueryValue}, hKey) # ADVAPI32.Success THEN
  63. res := NotFound; RETURN
  64. END;
  65. len := LEN(value); type := ADVAPI32.RegNone;
  66. ret := ADVAPI32.RegQueryValueEx(hKey, key, NIL, type, value, len);
  67. IF (type # ADVAPI32.RegSZ) OR (ret # ADVAPI32.Success) THEN
  68. IF (type = ADVAPI32.RegSZ) & (ret = ADVAPI32.ErrorMoreData) THEN
  69. NEW(buf, len+1);
  70. ADVAPI32.RegQueryValueEx(hKey, key, NIL, type, buf^, len);
  71. COPY(buf^, value); res := Done
  72. ELSE
  73. res := NotFound
  74. END
  75. ELSE
  76. res := Done
  77. END;
  78. ADVAPI32.RegCloseKey(hKey)
  79. END GetKeyValue;
  80. (** Delete key and its value, key = "" deletes the default value for path. *)
  81. PROCEDURE DeleteKeyValue*(root: ADVAPI32.HKEY; path, key: ARRAY OF CHAR);
  82. VAR hKey: ADVAPI32.HKEY;
  83. BEGIN
  84. IF ADVAPI32.RegOpenKeyEx(root, path, 0, {ADVAPI32.KeySetValue}, hKey) # ADVAPI32.Success THEN
  85. res := NotFound; RETURN
  86. END;
  87. IF ADVAPI32.RegDeleteValue(hKey, key) = ADVAPI32.Success THEN
  88. INC(stamp); res := Done
  89. ELSE
  90. res := NotFound
  91. END;
  92. ADVAPI32.RegCloseKey(hKey)
  93. END DeleteKeyValue;
  94. (** Recursive delete all sub-paths, keys and values in path.
  95. Note: be very careful when using this procedure!!! *)
  96. PROCEDURE DeletePath*(root: ADVAPI32.HKEY; path: ARRAY OF CHAR);
  97. VAR buffer: ARRAY Kernel32.MaxPath OF CHAR; hKey: ADVAPI32.HKEY; size: LONGINT;
  98. BEGIN
  99. IF ADVAPI32.RegOpenKeyEx(root, path, 0, ADVAPI32.KeyAllAccess, hKey) # ADVAPI32.Success THEN
  100. res := NotFound; RETURN
  101. END;
  102. size := Kernel32.MaxPath;
  103. WHILE ADVAPI32.RegEnumKeyEx(hKey, 0, buffer, size, NIL, NIL, NIL, NIL) = ADVAPI32.Success DO
  104. DeletePath(hKey, buffer);
  105. IF res # Done THEN
  106. ADVAPI32.RegCloseKey(hKey); RETURN
  107. END;
  108. size := Kernel32.MaxPath
  109. END;
  110. ADVAPI32.RegCloseKey(hKey);
  111. IF ADVAPI32.RegDeleteKey(root, path) = ADVAPI32.Success THEN
  112. INC(stamp); res := Done
  113. ELSE
  114. res := Failed
  115. END
  116. END DeletePath;
  117. (** Enumerate all sub-paths in path. *)
  118. PROCEDURE EnumeratePath*(root: ADVAPI32.HKEY; path: ARRAY OF CHAR; enum: PathEnumerator);
  119. VAR subPath: ARRAY Kernel32.MaxPath OF CHAR; hKey: ADVAPI32.HKEY; ret, i, size: LONGINT;
  120. BEGIN
  121. ret := ADVAPI32.RegOpenKeyEx(root, path, 0, {ADVAPI32.KeyEnumerateSubKeys}, hKey);
  122. IF ret # ADVAPI32.Success THEN
  123. res := NotFound; RETURN
  124. END;
  125. i := 0;
  126. WHILE ret = ADVAPI32.Success DO
  127. size := Kernel32.MaxPath;
  128. ret := ADVAPI32.RegEnumKeyEx(hKey, i, subPath, size, NIL, NIL, NIL, NIL);
  129. IF ret = ADVAPI32.Success THEN enum(subPath) END;
  130. INC(i)
  131. END;
  132. ADVAPI32.RegCloseKey(hKey); res := Done
  133. END EnumeratePath;
  134. (** Enumerate all key/value pairs in path.*)
  135. PROCEDURE EnumerateKeyValue*(root: ADVAPI32.HKEY; path: ARRAY OF CHAR; enum: KeyValueEnumerator);
  136. VAR
  137. key, value: ARRAY Kernel32.MaxPath OF CHAR; hKey: ADVAPI32.HKEY;
  138. ret, i, type, kLen, vLen: LONGINT;
  139. BEGIN
  140. ret := ADVAPI32.RegOpenKeyEx(root, path, 0, {ADVAPI32.KeyQueryValue}, hKey);
  141. IF ret # ADVAPI32.Success THEN
  142. res := NotFound; RETURN
  143. END;
  144. i := 0;
  145. WHILE ret = ADVAPI32.Success DO
  146. kLen := Kernel32.MaxPath; vLen := Kernel32.MaxPath; type := ADVAPI32.RegNone;
  147. ret := ADVAPI32.RegEnumValue(hKey, i, key, kLen, NIL, type, value, vLen);
  148. IF (ret = ADVAPI32.Success) & (type = ADVAPI32.RegSZ) THEN enum(key, value) END;
  149. INC(i)
  150. END;
  151. ADVAPI32.RegCloseKey(hKey); res := Done
  152. END EnumerateKeyValue;
  153. PROCEDURE OutputFileString(VAR str: ARRAY OF CHAR);
  154. VAR n: LONGINT; b: Kernel32.BOOL;
  155. BEGIN
  156. n := 0; WHILE str[n] # 0X DO INC(n) END;
  157. b := Kernel32.WriteFile(hFile, str, n, n, NIL);
  158. IF logfile THEN Kernel32.FlushFileBuffers(hFile) END
  159. END OutputFileString;
  160. (*
  161. PROCEDURE InitConsole();
  162. VAR rect: Kernel32.SmallRect; file: ARRAY 260 OF CHAR; con: ARRAY 64 OF CHAR; i, j: LONGINT;
  163. BEGIN
  164. Kernel32.OutputString := NIL; logfile := FALSE; hFile := Kernel32.InvalidHandleValue;
  165. GetKeyValue(CurrentUser, oberonSystem, "Console", con);
  166. IF res = Done THEN
  167. IF con[0] = '"' THEN con[0] := con[1] END;
  168. IF CAP(con[0]) = "C" THEN (* console window *)
  169. con := "ETH Oberon - Console";
  170. Kernel32.AllocConsole(); Kernel32.SetConsoleTitle(con);
  171. hFile := Kernel32.GetStdHandle(Kernel32.STDOutput);
  172. Kernel32.SetConsoleScreenBufferSize(hFile, 80 + ASH(1024, 16));
  173. rect.top := 0; rect. left := 0; rect.bottom := 24; rect.right := 79;
  174. Kernel32.SetConsoleWindowInfo(hFile, Kernel32.True, rect)
  175. ELSIF CAP(con[0]) = "S" THEN (* standard output -> requires CUI*)
  176. hFile := Kernel32.GetStdHandle(Kernel32.STDOutput)
  177. ELSIF CAP(con[0]) = "F" THEN (* log file *)
  178. con := "Oberon.Log"; logfile := TRUE;
  179. Kernel32.GetModuleFileName(Kernel.hInstance, file, 260);
  180. i := 0; j := 0;
  181. WHILE file[i] # 0X DO
  182. IF file[i] = "\" THEN j := i+1 END;
  183. INC(i)
  184. END;
  185. file[j] := 0X; i := 0;
  186. WHILE con[i] # 0X DO
  187. file[j] := con[i]; INC(i); INC(j)
  188. END;
  189. file[j] := 0X;
  190. hFile := Kernel32.CreateFile(file, {Kernel32.GenericWrite}, {Kernel32.FileShareRead}, NIL, Kernel32.CreateAlways, {Kernel32.FileAttributeNormal}, Kernel32.NULL);
  191. i := 1;
  192. WHILE (i <= 9) & (hFile = Kernel32.InvalidHandleValue) DO
  193. file[j] := CHR(i+ORD("0")); file[j+11] := 0X;
  194. hFile := Kernel32.CreateFile(file, {Kernel32.GenericWrite}, {Kernel32.FileShareRead}, NIL, Kernel32.CreateAlways, {Kernel32.FileAttributeNormal}, Kernel32.NULL);
  195. INC(i)
  196. END
  197. END;
  198. IF hFile # Kernel32.InvalidHandleValue THEN
  199. Kernel32.OutputString := OutputFileString
  200. ELSIF (CAP(con[0]) # "N") & (Kernel32.OutputString = NIL) THEN (* debugger *)
  201. Kernel32.OutputString := Kernel32.OutputDebugString
  202. END
  203. ELSE
  204. Kernel32.OutputString := Kernel32.OutputDebugString
  205. END;
  206. Modules.InstallTermHandler(ShutdownConsole)
  207. END InitConsole;
  208. PROCEDURE ShutdownConsole();
  209. BEGIN
  210. IF logfile & (hFile # Kernel32.InvalidHandleValue) THEN
  211. Kernel32.CloseHandle(hFile); hFile := Kernel32.InvalidHandleValue
  212. END;
  213. Kernel32.OutputString := Kernel32.OutputDebugString
  214. END ShutdownConsole;
  215. *)
  216. PROCEDURE Init;
  217. VAR
  218. file, name, value, software, version: ARRAY Kernel32.MaxPath OF CHAR;
  219. buf: POINTER TO ARRAY OF SYSTEM.BYTE; adr: ADDRESS; len, i: LONGINT; ch: CHAR;
  220. BEGIN
  221. res := Done; stamp := 0;
  222. Kernel32.GetModuleFileName(Kernel32.hInstance, file, Kernel32.MaxPath);
  223. len := ADVAPI32.GetFileVersionInfoSize(file, NIL);
  224. NEW(buf, len);
  225. ADVAPI32.GetFileVersionInfo(file, 0, len, buf^);
  226. ADVAPI32.VerQueryValue(buf^, "\StringFileInfo\040904e4\FileDescription", adr, len);
  227. IF len >= Kernel32.MaxPath THEN HALT(99) END;
  228. SYSTEM.MOVE(adr, ADDRESSOF(software), len);
  229. ADVAPI32.VerQueryValue(buf^, "\StringFileInfo\040904e4\FileVersion", adr, len);
  230. IF len >= Kernel32.MaxPath THEN HALT(99) END;
  231. SYSTEM.MOVE(adr, ADDRESSOF(version), len);
  232. (* cmd { "-" name [ "=" value ] } *)
  233. name := ""; i := 0;
  234. adr := Kernel32.GetCommandLine();
  235. REPEAT
  236. SYSTEM.GET(adr, ch); INC(adr);
  237. IF ch = "-" THEN
  238. value[i] := 0X; i := 0;
  239. IF name = "Registry" THEN COPY(value, version) END
  240. ELSIF ch = "=" THEN
  241. value[i] := 0X; i := 0; COPY(value, name)
  242. ELSIF ch > " " THEN
  243. value[i] := ch; INC(i)
  244. ELSE
  245. value[i] := 0X
  246. END
  247. UNTIL (ch = 0X) OR (i >= LEN(name)) ;
  248. IF (i > 0) & (name = "Registry") THEN
  249. value[i] := 0X; COPY(value, version)
  250. END;
  251. oberonRoot := "Software\"; Append(oberonRoot, software);
  252. AppendCh(oberonRoot, "\"); Append(oberonRoot, version);
  253. OberonPath("System", oberonSystem);
  254. END Init;
  255. BEGIN
  256. Init(); (* InitConsole() *)
  257. END Registry.