-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathregdiff.clj
More file actions
143 lines (125 loc) · 4.83 KB
/
regdiff.clj
File metadata and controls
143 lines (125 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
(ns regdiff
(:import [Microsoft.Win32
RegistryKey
Registry
RegistryHive
RegistryValueKind
RegistryView])
(:require [clojure.string :as string])
(:gen-class))
(defn stderr![& args]
(binding [*out* *err*]
(apply println args)))
;(def hklm-software (.OpenSubKey Registry/LocalMachine "Software"))
(def reg-key? (partial instance? RegistryKey))
(defn maybe-open-subkey [^RegistryKey k ^String name]
(try
(.OpenSubKey k name)
(catch System.Security.SecurityException se
(stderr! "Cannot open " (.-Name k) ":" name ". " (.Name (.GetType se)))
nil)))
(defn reg-subkeys [^RegistryKey k]
(->> (.GetSubKeyNames k)
(map (partial maybe-open-subkey k))
(filter identity)))
(defn reg-values [^RegistryKey k]
(map
(fn [value-name]
{:key (str (.-Name k) "::" value-name)
:kind (.GetValueKind k value-name)
:value (.GetValue k value-name)})
(.GetValueNames k)))
;(reg-subkeys hklm-software)
;(reg-values hklm-software)
(defn reg-children [^RegistryKey k]
(concat (reg-subkeys k)
(reg-values k)))
;(reg-children hklm-software)
(defn reg-seq
([^RegistryKey k]
(tree-seq reg-key? reg-children k)))
;(clojure.pprint/pprint
; (take 100
; (reg-seq hklm-software))))
(defn reg-key [regkey-or-valuemap]
(cond (reg-key? regkey-or-valuemap) (.-Name ^RegistryKey regkey-or-valuemap)
(associative? regkey-or-valuemap) (:key regkey-or-valuemap)
:else regkey-or-valuemap))
(defn make-title-reporter [ct]
(let [value (long-array 1)]
(fn reporter [[path]]
(let [v (nth value 0)]
(when (zero? (mod v ct))
(System.Console/set_Title (str v " comparisons. " path)))
(aset value 0 (+ 1 v))))))
(defn values-equal? [{lv :value :as l} {rv :value :as r}]
(or (= l r)
(and (array? lv)
(array? rv)
(= (clojure.string/join "\n" lv)
(clojure.string/join "\n" rv)))))
(defn reg-compare [s1 s2 filter? progress-reporter]
(lazy-seq
(let [[f1 & r1] s1
[f2 & r2] s2]
(let [k1 (reg-key f1)
k2 (reg-key f2)
key-comparison (compare k1 k2)
[n1 n2 c]
(cond (= key-comparison 0) [r1 r2 [k1 (if (or (and (reg-key? f1) (reg-key? f2))
(values-equal? f1 f2))
:same
:different)
f1 f2]]
(< key-comparison 0) [r1 s2 [k1 :left-only f1 nil]]
(> key-comparison 0) [s1 r2 [k2 :right-only nil f2]])]
(when (or k1 k2)
(progress-reporter c)
(if (filter? c)
(cons c (reg-compare n1 n2 filter? progress-reporter))
(reg-compare n1 n2 filter? progress-reporter)))))))
#_
(->>
(reg-compare (reg-seq hklm-software)
(reg-seq hklm-software)
(fn[[path difference]]
(and (reg-key? path)
(not= :same difference)))
(make-title-reporter 10))
(take 5))
(defn open-subkey [rkey subkeys]
(reduce #(.OpenSubKey % %2) rkey subkeys))
(def ignore-kind #{RegistryValueKind/Binary})
(defn -main[& args]
(let [[machine hive-name subkey-csv] args
hive (enum-val RegistryHive hive-name)
subkeys (remove empty? (string/split subkey-csv #","))
remote-key (RegistryKey/OpenRemoteBaseKey hive machine)
local-key (RegistryKey/OpenBaseKey hive RegistryView/Registry64)
differences
(reg-compare (reg-seq (open-subkey local-key subkeys))
(reg-seq (open-subkey remote-key subkeys))
(fn compare-filter [[path difference l r]]
(and (not (reg-key? path))
(not= :same difference)
(not (or (ignore-kind (:kind l))
(ignore-kind (:kind r))))))
(make-title-reporter 100))]
(stderr! "Comparing" hive "hive on this computer to" machine "under" subkey-csv)
(println "[")
(doseq [diff differences]
(let [fmt (fn fmt[r]
(cond (reg-key? r) (.get_Name r)
(associative? r) (-> r
(dissoc :key)
(update :value #(if (array? %)
(clojure.string/join "\n" %)
%)))
:else r))
d (-> diff
(update-in [2] fmt)
(update-in [3] fmt))]
(prn d)))
(println "]"))
(stderr! "Done!"))
;(-main "pan-thing1" "LocalMachine" "Software,Softek")