Put the code to convert a GUID string to a GUID structure into a routine
authorGuy Harris <guy@alum.mit.edu>
Sat, 24 Nov 2012 18:55:06 +0000 (18:55 -0000)
committerGuy Harris <guy@alum.mit.edu>
Sat, 24 Nov 2012 18:55:06 +0000 (18:55 -0000)
of its own.  Export that routine from capture_win_ifnames.c.

Rename GetInterfaceFriendlyNameFromDeviceGuid() to
get_interface_friendly_name_from_device_guid(), to match the style of
names of the other routines exported from capture_win_ifnames.c, and
export it as well.

Have if_info_new() use those routines, and, if parse_as_guid() fails,
treat the "description" as a friendly name rather than a vendor
description, so that we don't have a vendor description for, for
example, the device offered on some versions of Windows to handle
dial-up devices.

svn path=/trunk/; revision=46170

capture-pcap-util.c
capture_win_ifnames.c
capture_win_ifnames.h

index e1ce888695595754f979d72bfb9cc55776d465bb..7e843220b19732a3821e72e12be388af2a973562 100644 (file)
@@ -62,6 +62,10 @@ if_info_t *
 if_info_new(const char *name, const char *description, gboolean loopback)
 {
        if_info_t *if_info;
+#ifdef _WIN32
+       const char *guid_text;
+       GUID guid;
+#endif
 
        if_info = (if_info_t *)g_malloc(sizeof (if_info_t));
        if_info->name = g_strdup(name);
@@ -71,8 +75,37 @@ if_info_new(const char *name, const char *description, gboolean loopback)
         * and the friendly name isn't returned by WinPcap.
         * Fetch it ourselves.
         */
-       if_info->friendly_name = get_windows_interface_friendly_name(name);
-       if_info->vendor_description = g_strdup(description);
+
+       /*
+        * Skip over the "\Device\NPF_" prefix in the device name,
+        * if present.
+        */
+       if (strncmp("\\Device\\NPF_", name, 12) == 0)
+               guid_text = name + 12;
+       else
+               guid_text = name;
+
+       /* Now try to parse what remains as a GUID. */
+       if (parse_as_guid(guid_text, &guid)) {
+               /*
+                * Success. Try to get a friendly name using the GUID.
+                * As this is a regular interface, the description is a
+                * vendor description.
+                */
+               if_info->friendly_name = get_interface_friendly_name_from_device_guid(&guid);
+               if_info->vendor_description = g_strdup(description);
+       } else {
+               /*
+                * This is probably not a regular interface; we only
+                * support NT 5 (W2K) and later, so all regular interfaces
+                * should have GUIDs at the end of the name.  Therefore,
+                * the description, if supplied, is a friendly name
+                * provided by WinPcap, and there is no vendor
+                * description.
+                */
+               if_info->friendly_name = g_strdup(description);
+               if_info->description = NULL;
+       }
 #else
        /*
         * On UN*X, if there is a description, it's a friendly
index 1e4aac497a4fa4c2e2eaccfef5eaa00f5131813d..a20945cc8080a6de1c7714b8a547d178a166a857 100644 (file)
 #include "capture_win_ifnames.h"
 #include "wsutil/file_util.h"
 
+static int gethexdigit(const char *p)
+{
+    if(*p >= '0' && *p <= '9'){
+        return *p - '0';
+    }else if(*p >= 'A' && *p <= 'F'){
+        return *p - 'A' + 0xA;
+    }else if(*p >= 'a' && *p <= 'f'){
+        return *p - 'a' + 0xa;
+    }else{
+        return -1; /* Not a hex digit */
+    }
+}
+
+static gboolean get8hexdigits(const char *p, DWORD *d)
+{
+    int digit;
+    DWORD val;
+    int i;
+
+    val = 0;
+    for(i = 0; i < 8; i++){
+        digit = gethexdigit(p++);
+        if(digit == -1){
+            return FALSE; /* Not a hex digit */
+        }
+        val = (val << 4) | digit;
+    }
+    *d = val;
+    return TRUE;
+}
+
+static gboolean get4hexdigits(const char *p, WORD *w)
+{
+    int digit;
+    WORD val;
+    int i;
+
+    val = 0;
+    for(i = 0; i < 4; i++){
+        digit = gethexdigit(p++);
+        if(digit == -1){
+            return FALSE; /* Not a hex digit */
+        }
+        val = (val << 4) | digit;
+    }
+    *w = val;
+    return TRUE;
+}
+
+/*
+ * If a string is a GUID in {}, fill in a GUID structure with the GUID
+ * value and return TRUE; otherwise, if the string is not a valid GUID
+ * in {}, return FALSE.
+ */
+gboolean
+parse_as_guid(const char *guid_text, GUID *guid)
+{
+    int i;
+    int digit1, digit2;
+
+    if(*guid_text != '{'){
+        return FALSE; /* Nope, not enclosed in {} */
+    }
+    guid_text++;
+    /* There must be 8 hex digits; if so, they go into guid->Data1 */
+    if(!get8hexdigits(guid_text, &guid->Data1)){
+        return FALSE; /* nope, not 8 hex digits */
+    }
+    guid_text += 8;
+    /* Now there must be a hyphen */
+    if(*guid_text != '-'){
+        return FALSE; /* Nope */
+    }
+    guid_text++;
+    /* There must be 4 hex digits; if so, they go into guid->Data2 */
+    if(!get4hexdigits(guid_text, &guid->Data2)){
+        return FALSE; /* nope, not 4 hex digits */
+    }
+    guid_text += 4;
+    /* Now there must be a hyphen */
+    if(*guid_text != '-'){
+        return FALSE; /* Nope */
+    }
+    guid_text++;
+    /* There must be 4 hex digits; if so, they go into guid->Data3 */
+    if(!get4hexdigits(guid_text, &guid->Data3)){
+        return FALSE; /* nope, not 4 hex digits */
+    }
+    guid_text += 4;
+    /* Now there must be a hyphen */
+    if(*guid_text != '-'){
+        return FALSE; /* Nope */
+    }
+    guid_text++;
+    /*
+     * There must be 4 hex digits; if so, they go into the first 2 bytes
+     * of guid->Data4.
+     */
+    for(i = 0; i < 2; i++){
+        digit1 = gethexdigit(guid_text);
+        if(digit1 == -1){
+            return FALSE; /* Not a hex digit */
+        }
+        guid_text++;
+        digit2 = gethexdigit(guid_text);
+        if(digit2 == -1){
+            return FALSE; /* Not a hex digit */
+        }
+        guid_text++;
+        guid->Data4[i] = (digit1 << 4)|(digit2);
+    }
+    /* Now there must be a hyphen */
+    if(*guid_text != '-'){
+        return FALSE; /* Nope */
+    }
+    guid_text++;
+    /*
+     * There must be 12 hex digits; if so,t hey go into the next 6 bytes
+     * of guid->Data4.
+     */
+    for(i = 0; i < 6; i++){
+        digit1 = gethexdigit(guid_text);
+        if(digit1 == -1){
+            return FALSE; /* Not a hex digit */
+        }
+        guid_text++;
+        digit2 = gethexdigit(guid_text);
+        if(digit2 == -1){
+            return FALSE; /* Not a hex digit */
+        }
+        guid_text++;
+        guid->Data4[i+2] = (digit1 << 4)|(digit2);
+    }
+    /* Now there must be a closing } */
+    if(*guid_text != '}'){
+        return FALSE; /* Nope */
+    }
+    guid_text++;
+    /* And that must be the end of the string */
+    if(*guid_text != '\0'){
+        return FALSE; /* Nope */
+    }
+    return TRUE;
+}
+
 /**********************************************************************************/
 gboolean IsWindowsVistaOrLater()
 {
@@ -68,9 +213,9 @@ gboolean IsWindowsVistaOrLater()
 }
 
 /**********************************************************************************/
-/* Get the Connection Name for the given GUID */
-static char *
-GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid)
+/* Get the friendly name for the given GUID */
+char *
+get_interface_friendly_name_from_device_guid(__in GUID *guid)
 {
     HMODULE hIPHlpApi;
     HRESULT status;
@@ -161,7 +306,8 @@ GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid)
         return NULL;
     }
 
-    /* Get the required buffer size, and then convert the string */
+    /* Get the required buffer size, and then convert the string
+    * from UTF-16 to UTF-8. */
     size=WideCharToMultiByte(CP_UTF8, 0, wName, -1, NULL, 0, NULL, NULL);
     name=(char *) g_malloc(size);
     if (name == NULL){
@@ -176,65 +322,18 @@ GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid)
     return name;
 }
 
-static int gethexdigit(const char *p)
-{
-    if(*p >= '0' && *p <= '9'){
-        return *p - '0';
-    }else if(*p >= 'A' && *p <= 'F'){
-        return *p - 'A' + 0xA;
-    }else if(*p >= 'a' && *p <= 'f'){
-        return *p - 'a' + 0xa;
-    }else{
-        return -1; /* Not a hex digit */
-    }
-}
-
-static gboolean get8hexdigits(const char *p, DWORD *d)
-{
-    int digit;
-    DWORD val;
-    int i;
-
-    val = 0;
-    for(i = 0; i < 8; i++){
-        digit = gethexdigit(p++);
-        if(digit == -1){
-            return FALSE; /* Not a hex digit */
-        }
-        val = (val << 4) | digit;
-    }
-    *d = val;
-    return TRUE;
-}
-
-static gboolean get4hexdigits(const char *p, WORD *w)
-{
-    int digit;
-    WORD val;
-    int i;
-
-    val = 0;
-    for(i = 0; i < 4; i++){
-        digit = gethexdigit(p++);
-        if(digit == -1){
-            return FALSE; /* Not a hex digit */
-        }
-        val = (val << 4) | digit;
-    }
-    *w = val;
-    return TRUE;
-}
-
-/**********************************************************************************/
-/* returns the interface friendly name for a device name, if it is unable to
-* resolve the name, "" is returned */
+/*
+ * Given an interface name, try to extract the GUID from it and parse it.
+ * If that fails, return NULL; if that succeeds, attempt to get the
+ * friendly name for the interface in question.  If that fails, return
+ * NULL, otherwise return the friendly name, allocated with g_malloc()
+ * (so that it must be freed with g_free()).
+ */
 char *
-get_windows_interface_friendly_name(/* IN */ const char *interface_devicename)
+get_windows_interface_friendly_name(const char *interface_devicename)
 {
     const char* guid_text;
     GUID guid;
-    int i;
-    int digit1, digit2;
 
     /* Extract the guid text from the interface device name */
     if(strncmp("\\Device\\NPF_", interface_devicename, 12)==0){
@@ -243,95 +342,12 @@ get_windows_interface_friendly_name(/* IN */ const char *interface_devicename)
         guid_text=interface_devicename;
     }
 
-    /*
-     * If what follows is a GUID in {}, then convert it to a GUID structure
-     * and use that to look up the interface to get its friendly name.
-     */
-    if(*guid_text != '{'){
-        return NULL; /* Nope, not enclosed in {} */
-    }
-    guid_text++;
-    /* There must be 8 hex digits; if so, they go into guid.Data1 */
-    if(!get8hexdigits(guid_text, &guid.Data1)){
-        return NULL; /* nope, not 8 hex digits */
-    }
-    guid_text += 8;
-    /* Now there must be a hyphen */
-    if(*guid_text != '-'){
-        return NULL; /* Nope */
-    }
-    guid_text++;
-    /* There must be 4 hex digits; if so, they go into guid.Data2 */
-    if(!get4hexdigits(guid_text, &guid.Data2)){
-        return NULL; /* nope, not 4 hex digits */
-    }
-    guid_text += 4;
-    /* Now there must be a hyphen */
-    if(*guid_text != '-'){
-        return NULL; /* Nope */
-    }
-    guid_text++;
-    /* There must be 4 hex digits; if so, they go into guid.Data3 */
-    if(!get4hexdigits(guid_text, &guid.Data3)){
-        return NULL; /* nope, not 4 hex digits */
-    }
-    guid_text += 4;
-    /* Now there must be a hyphen */
-    if(*guid_text != '-'){
-        return NULL; /* Nope */
-    }
-    guid_text++;
-    /*
-     * There must be 4 hex digits; if so, they go into the first 2 bytes
-     * of guid.Data4.
-     */
-    for(i = 0; i < 2; i++){
-        digit1 = gethexdigit(guid_text);
-        if(digit1 == -1){
-            return NULL; /* Not a hex digit */
-        }
-        guid_text++;
-        digit2 = gethexdigit(guid_text);
-        if(digit2 == -1){
-            return NULL; /* Not a hex digit */
-        }
-        guid_text++;
-        guid.Data4[i] = (digit1 << 4)|(digit2);
-    }
-    /* Now there must be a hyphen */
-    if(*guid_text != '-'){
-        return NULL; /* Nope */
-    }
-    guid_text++;
-    /*
-     * There must be 12 hex digits; if so,t hey go into the next 6 bytes
-     * of guid.Data4.
-     */
-    for(i = 0; i < 6; i++){
-        digit1 = gethexdigit(guid_text);
-        if(digit1 == -1){
-            return NULL; /* Not a hex digit */
-        }
-        guid_text++;
-        digit2 = gethexdigit(guid_text);
-        if(digit2 == -1){
-            return NULL; /* Not a hex digit */
-        }
-        guid_text++;
-        guid.Data4[i+2] = (digit1 << 4)|(digit2);
-    }
-    /* Now there must be a closing } */
-    if(*guid_text != '}'){
-        return NULL; /* Nope */
-    }
-    guid_text++;
-    /* And that must be the end of the string */
-    if(*guid_text != '\0'){
-        return NULL; /* Nope */
+    if (!parse_as_guid(guid_text, &guid)){
+        return NULL; /* not a GUID, so no friendly name */
     }
 
     /* guid okay, get the interface friendly name associated with the guid */
-    return GetInterfaceFriendlyNameFromDeviceGuid(&guid);
+    return get_interface_friendly_name_from_device_guid(&guid);
 }
 
 /**************************************************************************************/
index 564c4d14a10ea197eea32112dd8821375ab44133..513ac74296a310a878e5a319e0a430c9e468f040 100644 (file)
 #ifndef CAPTURE_WIN_IFNAMES_H
 #define CAPTURE_WIN_IFNAMES_H
 
-char *get_windows_interface_friendly_name(/* IN */ const char *interface_devicename);
+/*
+ * If a string is a GUID in {}, fill in a GUID structure with the GUID
+ * value and return TRUE; otherwise, if the string is not a valid GUID
+ * in {}, return FALSE.
+ */
+extern gboolean parse_as_guid(const char *guid_text, GUID *guid);
+
+/* Get the friendly name for the given GUID */
+extern char *get_interface_friendly_name_from_device_guid(GUID *guid);
+
+/*
+ * Given an interface name, try to extract the GUID from it and parse it.
+ * If that fails, return NULL; if that succeeds, attempt to get the
+ * friendly name for the interface in question.  If that fails, return
+ * NULL, otherwise return the friendly name, allocated with g_malloc()
+ * (so that it must be freed with g_free()).
+ */
+extern char *get_windows_interface_friendly_name(const char *interface_devicename);
 
 #endif