diff --git a/hald/ids.c b/hald/ids.c
index 223c8d4..5f253eb 100644
--- a/hald/ids.c
+++ b/hald/ids.c
@@ -28,14 +28,14 @@ #  include <config.h>
 #endif
 
 #include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <stdint.h>
 #include <string.h>
-#include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
-#include <fcntl.h>
-#include <errno.h>
+#include <unistd.h>
 
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
@@ -47,11 +47,17 @@ #include "ids.h"
 /** Pointer to where the pci.ids file is loaded */
 static char *pci_ids = NULL;
 
+/** Array of pointers to the beginning of the lines */
+static char **pci_ids_list = NULL;
+
 /** Length of data store at at pci_ids */
-static size_t pci_ids_len;
+static unsigned int pci_ids_len;
 
-/** Iterator position into pci_ids */
-static size_t pci_ids_iter_pos;
+/** number of lines in pci_ids_list */
+static unsigned int pci_ids_lines;
+
+/** Iterator position into pci_ids_list */
+static unsigned int pci_ids_iter_pos;
 
 /** Initialize the pci.ids line iterator to the beginning of the file */
 static void
@@ -74,22 +80,15 @@ static char *
 pci_ids_line_iter_get_line (unsigned int *line_len)
 {
 	unsigned int i;
-	static char line[PCI_IDS_MAX_LINE_LEN];
 
-	for (i = 0;
-	     pci_ids_iter_pos < pci_ids_len &&
-	     i < PCI_IDS_MAX_LINE_LEN - 1 &&
-	     pci_ids[pci_ids_iter_pos] != '\n'; i++, pci_ids_iter_pos++) {
-		line[i] = pci_ids[pci_ids_iter_pos];
-	}
+	i = strlen(pci_ids_list[pci_ids_iter_pos]);
 
-	line[i] = '\0';
 	if (line_len != NULL)
 		*line_len = i;
 
 	pci_ids_iter_pos++;
 
-	return line;
+	return pci_ids_list[pci_ids_iter_pos-1];
 }
 
 /** See if there are more lines to process in pci.ids
@@ -99,7 +98,7 @@ pci_ids_line_iter_get_line (unsigned int
 static dbus_bool_t
 pci_ids_line_iter_has_more ()
 {
-	return pci_ids_iter_pos < pci_ids_len;
+	return pci_ids_iter_pos < pci_ids_lines;
 }
 
 
@@ -133,21 +132,29 @@ ids_find_pci (int vendor_id, int product
 	char rep_spi[8];
 	dbus_bool_t vendor_matched = FALSE;
 	dbus_bool_t product_matched = FALSE;
+	dbus_bool_t subvendor_matched = FALSE;
+	dbus_bool_t subproduct_matched = FALSE;
 	static char store_vn[PCI_IDS_MAX_LINE_LEN];
 	static char store_pn[PCI_IDS_MAX_LINE_LEN];
 	static char store_svn[PCI_IDS_MAX_LINE_LEN];
 	static char store_spn[PCI_IDS_MAX_LINE_LEN];
 
-	snprintf (rep_vi, 8, "%04x", vendor_id);
-	snprintf (rep_pi, 8, "%04x", product_id);
-	snprintf (rep_svi, 8, "%04x", subsys_vendor_id);
-	snprintf (rep_spi, 8, "%04x", subsys_product_id);
-
 	*vendor_name = NULL;
 	*product_name = NULL;
 	*subsys_vendor_name = NULL;
 	*subsys_product_name = NULL;
 
+	if (vendor_id == 0 && product_id == 0 && subsys_vendor_id == 0 && subsys_product_id == 0) {
+		HAL_DEBUG (("ids_find_pci: all id's == 0, nothing to search for. return."));
+		goto out;
+	}
+	
+	snprintf (rep_vi, 8, "%04x", vendor_id);
+	snprintf (rep_pi, 8, "%04x", product_id);
+	snprintf (rep_svi, 8, "%04x", subsys_vendor_id);
+	snprintf (rep_spi, 8, "%04x", subsys_product_id);
+	
+
 	for (pci_ids_line_iter_init (); pci_ids_line_iter_has_more ();) {
 		line = pci_ids_line_iter_get_line (&line_len);
 
@@ -167,11 +174,12 @@ ids_find_pci (int vendor_id, int product
 			num_tabs++;
 		}
 
+		/* check if we already found all */ 
+		if (vendor_matched && product_matched && subvendor_matched && subproduct_matched)
+			goto out;
+
 		switch (num_tabs) {
 		case 0:
-			/* vendor names */
-			vendor_matched = FALSE;
-
 			/* first check subsys_vendor_id, if haven't done 
 			 * already */
 			if (*subsys_vendor_name == NULL
@@ -179,6 +187,8 @@ ids_find_pci (int vendor_id, int product
 				if ((*((dbus_uint32_t *) line)) ==
 				    (*((dbus_uint32_t *) rep_svi))) {
 					/* found it */
+					subvendor_matched = TRUE;
+
 					for (i = 4; i < line_len; i++) {
 						if (!isspace (line[i]))
 							break;
@@ -186,11 +196,14 @@ ids_find_pci (int vendor_id, int product
 					strncpy (store_svn, line + i,
 						 PCI_IDS_MAX_LINE_LEN);
 					*subsys_vendor_name = store_svn;
+
+					if (vendor_matched && product_matched && subsys_product_id == 0)
+						goto out;
 				}
 			}
 
 			/* check vendor_id */
-			if (vendor_id != 0) {
+			if (vendor_id != 0 && !vendor_matched) {
 				if (memcmp (line, rep_vi, 4) == 0) {
 					/* found it */
 					vendor_matched = TRUE;
@@ -202,20 +215,17 @@ ids_find_pci (int vendor_id, int product
 					strncpy (store_vn, line + i,
 						 PCI_IDS_MAX_LINE_LEN);
 					*vendor_name = store_vn;
+
+					if (product_id == 0 && subsys_vendor_id == 0 && subsys_product_id == 0)
+						goto out;
 				}
 			}
 
 			break;
 
 		case 1:
-			product_matched = FALSE;
-
-			/* product names */
-			if (!vendor_matched)
-				continue;
-
-			/* check product_id */
-			if (product_id != 0) {
+			
+			if (product_id != 0 && vendor_matched && !product_matched) {
 				if (memcmp (line + 1, rep_pi, 4) == 0) {
 					/* found it */
 
@@ -228,6 +238,10 @@ ids_find_pci (int vendor_id, int product
 					strncpy (store_pn, line + i,
 						 PCI_IDS_MAX_LINE_LEN);
 					*product_name = store_pn;
+
+					if ((subsys_vendor_id == 0 && subsys_product_id == 0) ||
+					    (subvendor_matched && subsys_product_id == 0))
+                                                goto out;
 				}
 			}
 			break;
@@ -236,6 +250,8 @@ ids_find_pci (int vendor_id, int product
 			/* subsystem_vendor subsystem_product */
 			if (!vendor_matched || !product_matched)
 				continue;
+			if (vendor_matched && product_matched && subvendor_matched && subsys_product_id == 0)
+				goto out;
 
 			/* check product_id */
 			if (subsys_vendor_id != 0
@@ -244,6 +260,8 @@ ids_find_pci (int vendor_id, int product
 				    && memcmp (line + 7, rep_spi,
 					       4) == 0) {
 					/* found it */
+					subproduct_matched = TRUE;
+
 					for (i = 11; i < line_len; i++) {
 						if (!isspace (line[i]))
 							break;
@@ -251,6 +269,8 @@ ids_find_pci (int vendor_id, int product
 					strncpy (store_spn, line + i,
 						 PCI_IDS_MAX_LINE_LEN);
 					*subsys_product_name = store_spn;
+					
+					goto out;
 				}
 			}
 
@@ -261,8 +281,26 @@ ids_find_pci (int vendor_id, int product
 		}
 
 	}
+out:
+	return;
 }
 
+/** Free resources used by to store the PCI database
+ *
+ *  @param                      #FALSE if the PCI database wasn't loaded
+ */
+static dbus_bool_t
+pci_ids_free ()
+{
+	if (pci_ids != NULL) {
+		free (pci_ids);
+		pci_ids = NULL;
+		free (pci_ids_list);
+		pci_ids_list = NULL;
+		return TRUE;
+	}
+	return FALSE;
+}
 
 /** Load the PCI database used for mapping vendor, product, subsys_vendor
  *  and subsys_product numbers into names.
@@ -274,36 +312,91 @@ ids_find_pci (int vendor_id, int product
 static dbus_bool_t
 pci_ids_load (const char *path)
 {
-	int fd;
-	struct stat statbuf;
-	gboolean ret;
+	FILE *fp;
+	unsigned int num_read;
+	unsigned int line_count;
+	unsigned int i;
+	char *pci_ids_tmp;
+	char *pci_ids_tmp2;
+	char **pci_ids_list_tmp;
+	int start_of_line;
+
+	fp = fopen (path, "r");
+	if (fp == NULL) {
+		HAL_ERROR (("couldn't open PCI database at %s,", path));
+		return FALSE;
+	}
 
-	ret = FALSE;
+	fseek (fp, 0, SEEK_END);
+	pci_ids_len = ftell (fp);
+	fseek (fp, 0, SEEK_SET);
 
-	if (stat (path, &statbuf) != 0) {
-		HAL_WARNING (("Couldn't stat pci.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
-		goto out;
+	pci_ids = malloc (pci_ids_len);
+	if (pci_ids == NULL) {
+		DIE (("Couldn't allocate %d bytes for PCI database file\n",
+		      pci_ids_len));
 	}
-	pci_ids_len = statbuf.st_size;
 
-	fd = open (path, O_RDONLY);
-	if (fd < 0) {
-		HAL_WARNING (("Couldn't open pci.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
-		goto out;
+	num_read = fread (pci_ids, sizeof (char), pci_ids_len, fp);
+	if (pci_ids_len != num_read) {
+		HAL_ERROR (("Error loading PCI database file"));
+		pci_ids_free();
+		fclose(fp);
+		return FALSE;
 	}
 
-	pci_ids = mmap (NULL, pci_ids_len, PROT_READ, MAP_SHARED, fd, 0);
-	if (pci_ids == MAP_FAILED) {
-		HAL_WARNING (("Couldn't mmap pci.ids file '%s', errno=%d: %s", path, errno, strerror (errno)));
-		close (fd);
-		goto out;
+	fclose(fp);
+	
+	/* File loaded into mem. Build pointer list lines starting with # are skipped. */
+        line_count = 0;
+        pci_ids_tmp = pci_ids;
+        start_of_line = TRUE;
+        do {
+		if (start_of_line && *pci_ids_tmp != '#') 
+			line_count++;
+		
+		start_of_line = FALSE;
+		if (*pci_ids_tmp == '\n') 
+			start_of_line = TRUE;
+		
+		pci_ids_tmp++;
+	} while (pci_ids_tmp < (pci_ids + pci_ids_len)); 
+
+        /* create list */
+	pci_ids_list = (char **)malloc(sizeof(char *) * (line_count + 1));
+	if (pci_ids_list == NULL) {
+		HAL_ERROR (("Error loading PCI database file"));
+		free (pci_ids);
+		pci_ids = NULL;
+		return FALSE;
 	}
 
-	ret = TRUE;
+        memset(pci_ids_list, 0, sizeof(char *) * (line_count + 1));
+        /* now the beginning of each string into the list */
+        pci_ids_list_tmp = pci_ids_list;
+        pci_ids_tmp = pci_ids;
+        i = 0;
+        while (i < line_count) {
+		if (*pci_ids_tmp != '#') {
+			*pci_ids_list_tmp = pci_ids_tmp;
+			pci_ids_list_tmp++,i++;
+		}
 
-	close (fd);
-out:
-	return ret;
+		pci_ids_tmp2 = pci_ids_tmp;
+		pci_ids_tmp = strchr(pci_ids_tmp,'\n');
+		if (pci_ids_tmp != NULL) {
+			/* replace \n by \0 */
+			if ((pci_ids_tmp - pci_ids_tmp2) < PCI_IDS_MAX_LINE_LEN) {
+				*pci_ids_tmp = '\0';
+			} else {
+				*(pci_ids_tmp2 + PCI_IDS_MAX_LINE_LEN) = '\0';
+			}
+
+			pci_ids_tmp++;
+		} 
+	} 
+	pci_ids_lines = line_count;
+	return TRUE;
 }
 
 /*==========================================================================*/
