+
+(* Called when the top level registry node has been opened and the
+ * hive file was downloaded to the cache file successfully.
+ *)
+and when_downloaded_registry ({ model = model } as t) path () =
+ debug "when_downloaded_registry";
+ let row = model#get_iter path in
+
+ let hdata = get_hdata t row in
+ match hdata.content with
+ | TopWinReg (src, rootkey, remotefile, cachefile) ->
+ (try
+ (* Open the hive and save the hive handle in the row hdata. *)
+ let flags = if verbose () then [ Hivex.OPEN_VERBOSE ] else [] in
+ let h = Hivex.open_file cachefile flags in
+ hdata.hiveh <- Some h;
+
+ (* Continue as if expanding any other hive node. *)
+ let root = Hivex.root h in
+ expand_hive_node t row root
+ with
+ Hivex.Error _ as exn -> when_downloaded_registry_fail t path exn
+ )
+ | _ -> assert false
+
+(* Called instead of {!when_downloaded_registry} if the download failed. *)
+and when_downloaded_registry_fail ({ model = model } as t) path exn =
+ debug "when_downloaded_registry_fail: %s" (Printexc.to_string exn);
+
+ match exn with
+ | G.Error msg
+ | Hivex.Error (_, _, msg) ->
+ let row = model#get_iter path in
+ let row = model#iter_children ~nth:0 (Some row) in
+
+ let hdata =
+ { state=IsLeaf; content=ErrorMessage msg; visited=false; hiveh=None } in
+ store_hdata t row hdata;
+
+ model#set ~row ~column:t.name_col (markup_escape msg)
+
+ | exn ->
+ (* unexpected exception: re-raise it *)
+ raise exn
+
+(* Expand a hive node. *)
+and expand_hive_node ({ model = model } as t) row node =
+ debug "expand_hive_node";
+ let hdata = get_hdata t row in
+ let h = Option.get hdata.hiveh in
+
+ (* Read the hive entries (values, subkeys) at this node and add them
+ * to the tree.
+ *)
+ let values = Hivex.node_values h node in
+ let cmp v1 v2 = compare (Hivex.value_key h v1) (Hivex.value_key h v2) in
+ Array.sort cmp values;
+ Array.iter (
+ fun value ->
+ let row = model#append ~parent:row () in
+ make_leaf t row (RegValue value) (Some h);
+ model#set ~row ~column:t.name_col (markup_of_regvalue h value);
+ model#set ~row ~column:t.size_col (markup_of_regvaluesize h value);
+ model#set ~row ~column:t.date_col (markup_of_regvaluetype h value);
+ ) values;
+
+ let children = Hivex.node_children h node in
+ let cmp n1 n2 = compare (Hivex.node_name h n1) (Hivex.node_name h n2) in
+ Array.sort cmp children;
+ Array.iter (
+ fun node ->
+ let row = model#append ~parent:row () in
+ make_node t row (RegKey node) (Some h);
+ model#set ~row ~column:t.name_col (markup_of_regkey h node);
+ ) children;
+
+ (* Remove the placeholder "Loading" entry. NB. Must be done AFTER
+ * adding the other entries, or else Gtk will unexpand the row.
+ *)
+ (try
+ let row = find_child_node_by_content t row Loading in
+ ignore (model#remove row)
+ with Invalid_argument _ | Not_found -> ()
+ );
+
+ (* The original entry has now been loaded, so update its state. *)
+ hdata.state <- IsNode;
+ set_visited t row