summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2013-01-06 01:55:31 +0100
committerMarc-André Lureau <marcandre.lureau@gmail.com>2013-01-06 16:38:26 +0100
commit09460231052736715e666ee0f230379fb7fc69cd (patch)
treebe6b699106be10451ace8e66c8a822ed5f5c8197
parent05676e2ab509122490fbfeb6c0d8d581f4cf9cf6 (diff)
downloadmsitools-09460231052736715e666ee0f230379fb7fc69cd.tar.gz
msitools-09460231052736715e666ee0f230379fb7fc69cd.tar.xz
msitools-09460231052736715e666ee0f230379fb7fc69cd.zip
Populate Shortcut table
-rw-r--r--src/builder.vala41
-rw-r--r--src/msi.vala48
-rw-r--r--src/util.vala8
-rw-r--r--src/wix.vala75
4 files changed, 168 insertions, 4 deletions
diff --git a/src/builder.vala b/src/builder.vala
index 699be29..a7a5cf0 100644
--- a/src/builder.vala
+++ b/src/builder.vala
@@ -41,6 +41,8 @@ namespace Wixl {
add ("CostFinalize", 1000);
add ("InstallValidate", 1400);
add ("InstallInitialize", 1500);
+ if (db.table_shortcut.records.length () > 0)
+ add ("CreateShortcuts", 4500);
add ("PublishFeatures", 6300);
add ("PublishProduct", 6400);
add ("InstallFinalize", 6600);
@@ -60,10 +62,14 @@ namespace Wixl {
add ("RemoveRegistryValues", 2600);
add ("WriteRegistryValues", 2600);
}
+ if (db.table_shortcut.records.length () > 0)
+ add ("RemoveShortcuts", 3200);
if (db.table_remove_file.records.length () > 0)
add ("RemoveFiles", 3500);
if (db.table_file.records.length () > 0)
add ("InstallFiles", 4000);
+ if (db.table_shortcut.records.length () > 0)
+ add ("CreateShortcuts", 4500);
add ("RegisterUser", 6000);
add ("RegisterProduct", 6100);
add ("PublishFeatures", 6300);
@@ -108,10 +114,21 @@ namespace Wixl {
}
}
+ public void shortcut_target () throws GLib.Error {
+ var shortcuts = root.get_elements<WixShortcut> ();
+
+ foreach (var sc in shortcuts) {
+ var component = sc.get_component ();
+ var feature = component.in_feature.first ().data;
+ MsiTableShortcut.set_target (sc.record, feature.Id);
+ }
+ }
+
public MsiDatabase build () throws GLib.Error {
db = new MsiDatabase ();
root.accept (this);
+ shortcut_target ();
sequence_actions ();
build_cabinet ();
@@ -204,8 +221,11 @@ namespace Wixl {
public override void visit_component_ref (WixComponentRef ref) throws GLib.Error {
if (ref.parent is WixFeature) {
- var parent = ref.parent as WixFeature;
- db.table_feature_components.add (parent.Id, @ref.Id);
+ var feature = ref.parent as WixFeature;
+
+ var component = root.find_element (typeof (WixComponent), @ref.Id) as WixComponent;
+ component.in_feature.append (feature);
+ db.table_feature_components.add (feature.Id, @ref.Id);
} else
warning ("unhandled parent type %s", @ref.parent.name);
}
@@ -299,6 +319,23 @@ namespace Wixl {
visit_key_element (file);
}
+
+ public override void visit_shortcut (WixShortcut shortcut) throws GLib.Error {
+ if (!parse_yesno (shortcut.Advertise))
+ throw new Wixl.Error.FIXME ("unimplemented");
+
+ var component = shortcut.get_component ();
+ var rec = db.table_shortcut.add (shortcut.Id, shortcut.Directory, shortcut.Name, component.Id);
+ shortcut.record = rec;
+
+ if (shortcut.Icon != null)
+ MsiTableShortcut.set_icon (rec, shortcut.Icon, int.parse (shortcut.IconIndex));
+ if (shortcut.WorkingDirectory != null)
+ MsiTableShortcut.set_working_dir (rec, shortcut.WorkingDirectory);
+ }
+
+ public override void visit_create_folder (WixCreateFolder folder) throws GLib.Error {
+ }
}
} // Wixl
diff --git a/src/msi.vala b/src/msi.vala
index 027f44f..a85eecd 100644
--- a/src/msi.vala
+++ b/src/msi.vala
@@ -362,6 +362,51 @@ namespace Wixl {
}
}
+ class MsiTableShortcut: MsiTable {
+ construct {
+ name = "Shortcut";
+ }
+
+ public Libmsi.Record add (string Shortcut, string Directory, string Name, string Component) throws GLib.Error {
+ var rec = new Libmsi.Record (8);
+
+ if (!rec.set_string (1, Shortcut) ||
+ !rec.set_string (2, Directory) ||
+ !rec.set_string (3, Name) ||
+ !rec.set_string (4, Component))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+
+ return rec;
+ }
+
+ public static void set_target (Libmsi.Record rec, string Target) throws GLib.Error {
+ if (!rec.set_string (5, Target))
+ throw new Wixl.Error.FAILED ("failed to set record");
+ }
+
+ public static void set_icon (Libmsi.Record rec, string Icon, int IconIndex) throws GLib.Error {
+ if (!rec.set_string (6, Icon) ||
+ !rec.set_int (7, IconIndex))
+ throw new Wixl.Error.FAILED ("failed to set record");
+ }
+
+ public static void set_working_dir (Libmsi.Record rec, string WkDir) throws GLib.Error {
+ if (!rec.set_string (8, WkDir))
+ throw new Wixl.Error.FAILED ("failed to set record");
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `Shortcut` (`Shortcut` CHAR(72) NOT NULL, `Directory_` CHAR(72) NOT NULL, `Name` CHAR(128) NOT NULL LOCALIZABLE, `Component_` CHAR(72) NOT NULL, `Target` CHAR(72) NOT NULL, `Arguments` CHAR(255), `Description` CHAR(255) LOCALIZABLE, `Hotkey` INT, `Icon_` CHAR(72), `IconIndex` INT, `ShowCmd` INT, `WkDir` CHAR(72), `DisplayResourceDLL` CHAR(255), `DisplayResourceId` INT, `DescriptionResourceDLL` CHAR(255), `DescriptionResourceId` INT PRIMARY KEY `Shortcut`)");
+ query.execute (null);
+
+ query = new Libmsi.Query (db, "INSERT INTO `Shortcut` (`Shortcut`, `Directory_`, `Name`, `Component_`, `Target`, `Icon_`, `IconIndex`, `WkDir`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
class MsiTableRemoveFile: MsiTable {
construct {
name = "RemoveFile";
@@ -513,6 +558,7 @@ namespace Wixl {
public MsiTableInstallExecuteSequence table_install_execute_sequence;
public MsiTableInstallUISequence table_install_ui_sequence;
public MsiTableStreams table_streams;
+ public MsiTableShortcut table_shortcut;
HashTable<string, MsiTable> tables;
@@ -551,6 +597,7 @@ namespace Wixl {
table_install_execute_sequence = new MsiTableInstallExecuteSequence ();
table_install_ui_sequence = new MsiTableInstallUISequence ();
table_streams = new MsiTableStreams ();
+ table_shortcut = new MsiTableShortcut ();
foreach (var t in new MsiTable[] {
table_admin_execute_sequence,
@@ -569,6 +616,7 @@ namespace Wixl {
table_registry,
table_file,
table_streams,
+ table_shortcut,
new MsiTableError (),
new MsiTableValidation ()
}) {
diff --git a/src/util.vala b/src/util.vala
index 00ae957..a5514a3 100644
--- a/src/util.vala
+++ b/src/util.vala
@@ -1,7 +1,8 @@
namespace Wixl {
public errordomain Error {
- FAILED
+ FAILED,
+ FIXME,
}
namespace UUID {
@@ -85,7 +86,10 @@ namespace Wixl {
return str;
}
- bool parse_yesno (string str) {
+ bool parse_yesno (string? str) {
+ if (str == null)
+ return false;
+
return (str[0] == 'Y' || str[0] == 'y');
}
} // Wixl
diff --git a/src/wix.vala b/src/wix.vala
index 33291fd..2b25f18 100644
--- a/src/wix.vala
+++ b/src/wix.vala
@@ -14,6 +14,7 @@ namespace Wixl {
public abstract void visit_registry_value (WixRegistryValue reg) throws GLib.Error;
public abstract void visit_file (WixFile reg) throws GLib.Error;
public abstract void visit_shortcut (WixShortcut shortcut) throws GLib.Error;
+ public abstract void visit_create_folder (WixCreateFolder folder) throws GLib.Error;
}
public abstract class WixElement: Object {
@@ -44,6 +45,37 @@ namespace Wixl {
children.append (e);
}
+ private G[] add_elements<G> (owned G[] a) {
+ // jeez, vala, took me a while to workaround generics & array issues..
+ var array = a;
+ var type = typeof (G);
+
+ if (this.get_type () == type)
+ array += this;
+
+ foreach (var c in children)
+ array = c.add_elements<G> (array);
+
+ return array;
+ }
+
+ public G[] get_elements<G> () {
+ return add_elements<G> ({});
+ }
+
+ public WixElement? find_element (Type type, string Id) {
+ if (this.Id == Id && this.get_type () == type)
+ return this;
+
+ foreach (var c in children) {
+ var e = c.find_element (type, Id);
+ if (e != null)
+ return e;
+ }
+
+ return null;
+ }
+
public virtual void load (Xml.Node *node) throws Wixl.Error {
if (node->name != name)
throw new Error.FAILED ("%s: invalid node %s".printf (name, node->name));
@@ -152,6 +184,18 @@ namespace Wixl {
}
}
+ public class WixCreateFolder: WixElement {
+ static construct {
+ name = "CreateFolder";
+ }
+
+ public string Directory { get; set; }
+
+ public override void accept (WixElementVisitor visitor) throws GLib.Error {
+ visitor.visit_create_folder (this);
+ }
+ }
+
public class WixIcon: WixElement {
static construct {
name = "Icon";
@@ -164,6 +208,32 @@ namespace Wixl {
}
}
+ public class WixShortcut: WixElement {
+ static construct {
+ name = "Shortcut";
+ }
+
+ public string Directory { get; set; }
+ public string Name { get; set; }
+ public string IconIndex { get; set; }
+ public string WorkingDirectory { get; set; }
+ public string Icon { get; set; }
+ public string Advertise { get; set; }
+
+ public Libmsi.Record record;
+
+ public WixComponent? get_component () {
+ if (parent is WixFile || parent is WixCreateFolder)
+ return parent.parent as WixComponent;
+ else
+ return parent as WixComponent;
+ }
+
+ public override void accept (WixElementVisitor visitor) throws GLib.Error {
+ visitor.visit_shortcut (this);
+ }
+ }
+
public abstract class WixKeyElement: WixElement {
public string KeyPath { get; set; }
}
@@ -171,6 +241,8 @@ namespace Wixl {
public class WixFile: WixKeyElement {
static construct {
name = "File";
+
+ add_child_types (child_types, { typeof (WixShortcut) });
}
public string DiskId { get; set; }
@@ -180,6 +252,7 @@ namespace Wixl {
public Libmsi.Record record;
public override void accept (WixElementVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
visitor.visit_file (this);
}
}
@@ -297,6 +370,8 @@ namespace Wixl {
public string Guid { get; set; }
public WixKeyElement? key;
+ public List<WixFeature> in_feature;
+
public override void accept (WixElementVisitor visitor) throws GLib.Error {
base.accept (visitor);
visitor.visit_component (this);