Put the code to convert a GUID string to a GUID structure into a routine

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
This commit is contained in:
Guy Harris 2012-11-24 18:55:06 +00:00
parent 67ea470cc8
commit 319891ade3
3 changed files with 214 additions and 148 deletions

View 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

View File

@ -53,6 +53,151 @@
#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);
}
/**************************************************************************************/

View File

@ -26,6 +26,23 @@
#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