*** msitools-0.95-a/tools/msiextract.vala	2015-10-06 22:48:41.000000000 +0200
--- msitools-0.95-b/tools/msiextract.vala	2016-10-04 21:58:03.505000000 +0200
***************
*** 22,49 ****
      return str;
  }
  
  public void extract_cab (Libmsi.Database db, string cab,
                           HashTable<string, string> cab_to_name) throws GLib.Error
  {
      if (cab.has_prefix ("#")) {
          var name = cab.substring (1);
          var query = new Libmsi.Query (db, "SELECT `Data` FROM `_Streams` WHERE `Name` = '%s'".printf (name));
          query.execute ();
          var rec = query.fetch ();
-         var cabinet = new GCab.Cabinet ();
          cabinet.load (rec.get_stream (1));
-         var path = File.new_for_path (directory);
-         cabinet.extract_simple (path, (current) => {
-                 var extname = cab_to_name.lookup (current.get_name ());
-                 if (extname == null) {
-                     extname = current.get_name ();
-                     warning ("couldn't lookup MSI name, fallback on cab name %s", extname);
-                 }
-                 current.set_extract_name (extname);
-                 GLib.stdout.printf ("%s\n", extname);
-                 return true;
-             }, null);
      }
  }
  
  public string? get_directory_name (Libmsi.Record rec) throws GLib.Error {
--- 22,81 ----
      return str;
  }
  
+ // Look for a case insensitive match of cab in the directory dir.
+ public string lookup_cab (string dir, string cab) throws GLib.Error
+ {
+     var path = File.new_for_path (dir);
+     var children = path.enumerate_children ("standard::*", FileQueryInfoFlags.NONE);
+ 
+     string CAB = cab.up ();
+     FileInfo info = null;
+     while ((info = children.next_file ()) != null) {
+         if (info.get_file_type () == FileType.DIRECTORY)
+             continue;
+ 
+         if (info.get_name ().up () == CAB)
+             return path.get_child (info.get_name ()).get_path ();
+     }
+ 
+     return path.get_child (cab).get_path ();
+ }
+ 
  public void extract_cab (Libmsi.Database db, string cab,
                           HashTable<string, string> cab_to_name) throws GLib.Error
  {
+     var cabinet = new GCab.Cabinet ();
+ 
      if (cab.has_prefix ("#")) {
          var name = cab.substring (1);
          var query = new Libmsi.Query (db, "SELECT `Data` FROM `_Streams` WHERE `Name` = '%s'".printf (name));
          query.execute ();
          var rec = query.fetch ();
          cabinet.load (rec.get_stream (1));
      }
+     else {
+         // Look for the cab file in the directory the MSI file resides in.
+         var dbpath = File.new_for_path (db.path).get_parent ();
+         cab = lookup_cab (dbpath.get_path (), cab);
+ 
+         try {
+             cabinet.load (File.new_for_path (cab).read ());
+         } catch (GLib.Error err) {
+             throw new GLib.Error (err.domain, err.code, cab + ": " + err.message);
+         }
+     }
+ 
+     var path = File.new_for_path (directory);
+     cabinet.extract_simple (path, (current) => {
+             var extname = cab_to_name.lookup (current.get_name ());
+             if (extname == null) {
+                 extname = current.get_name ();
+                 warning ("couldn't lookup MSI name, fallback on cab name %s", extname);
+             }
+             current.set_extract_name (extname);
+             GLib.stdout.printf ("%s\n", extname);
+             return true;
+         }, null);
  }
  
  public string? get_directory_name (Libmsi.Record rec) throws GLib.Error {
***************
*** 154,160 ****
          foreach (var file in files)
              extract (file);
      } catch (GLib.Error error) {
!         GLib.stderr.printf (error.message);
          exit (1);
      }
  
--- 186,192 ----
          foreach (var file in files)
              extract (file);
      } catch (GLib.Error error) {
!         GLib.stderr.printf ("%s\n", error.message);
          exit (1);
      }
  
