[Gpsbabel-code] RFC: horrible NT hack
Brought to you by:
robertl
From: Robert L. <rob...@us...> - 2004-12-22 19:36:04
|
Once GPSBabel earned Garmin USB support, we had to start linking with the 'setupapi' library as we needed access to a handful of services in it. Unfortunately, we needed access to services that didn't exist in Windows NT. (Maybe it was "Windows 2000" - they're all kind of the same to me.) This means that we had unresolved externals on load time and can no longer run on such systems. In the months since we've done this - including the GSAK user base - I've known of exactly two people that are affected which means I'm not too wound up about addressing this. I started down the attached path before getting distracted and moving on. (I can't recall if I ever got around to actually _testing_ this before my laptop flatlined.) The idea is to use LoadLibrary to dynamically load setupapi.dll instead of staticly linking it. Then only people that needed the USB code (which would exclude both of the NT users since that wouldn't work anyway) would pay the price of bringing it in. Unfortunately, the implementation got all wrapped around its own axle of complexity. Is this really how this is done in the world of Windows? Do any of you guys that are more attuned to the Zen of Win32 have a better way to make this work? As it stands, it's so ugly (and the user base appears so small) that I'm inclined to stick with the "It doesn't work on NT" position and Clyde agrees that it's just not worth it. RJL Index: gpsusbwin.c =================================================================== RCS file: /cvsroot/gpsbabel/gpsbabel/jeeps/gpsusbwin.c,v retrieving revision 1.4 diff -p -u -r1.4 gpsusbwin.c --- gpsusbwin.c 1 Nov 2004 02:27:05 -0000 1.4 +++ gpsusbwin.c 22 Dec 2004 19:28:44 -0000 @@ -25,6 +25,7 @@ #include <malloc.h> #include <windows.h> #include <winioctl.h> +#include <winbase.h> #include <initguid.h> #include <setupapi.h> @@ -52,6 +53,7 @@ DEFINE_GUID(GARMIN_GUID, 0x2c9c45c2L, 0x static HANDLE *usb_handle ; static int usb_tx_packet_size ; +static char nousb[] = "Attempt to call USB function before loaded"; static const char oinit[12] = {0, 0, 0, 0, 0x05, 0, 0, 0, 0, 0, 0, 0}; garmin_usb_packet iresp; garmin_usb_packet iresp_junk; @@ -59,6 +61,112 @@ static int ct; static char * id_unit(void); + +BOOL (*sdgdidp)( + HDEVINFO DeviceInfoSet, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, + DWORD DeviceInterfaceDetailDataSize, + PDWORD RequiredSize, + PSP_DEVINFO_DATA DeviceInfoData) ; + +HDEVINFO (*gcdp)( + const GUID* ClassGuid, + PCSTR Enumerator, + HWND hwndParent, + DWORD Flags +); + +BOOL (*sdedip)( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + const GUID* InterfaceClassGuid, + DWORD MemberIndex, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData +); + +BOOL (*ddilp)( + HDEVINFO DeviceInfoSet +); + + +static +BOOL gusb_SetupDiGetDeviceInterfaceDetail( + HDEVINFO DeviceInfoSet, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, + DWORD DeviceInterfaceDetailDataSize, + PDWORD RequiredSize, + PSP_DEVINFO_DATA DeviceInfoData) +{ + if (sdgdidp) + (*sdgdidp)(DeviceInfoSet, DeviceInterfaceData, + DeviceInterfaceDetailData, + DeviceInterfaceDetailDataSize, RequiredSize, + DeviceInfoData); + else + fatal(nousb); +} + +static +HDEVINFO gusb_SetupDiGetClassDevs( + const GUID* ClassGuid, + PCSTR Enumerator, + HWND hwndParent, + DWORD Flags) +{ + if (gcdp) + (*gcdp)(ClassGuid, Enumerator, hwndParent, Flags); + else + fatal(nousb); +} + +BOOL gusb_SetupDiEnumDeviceInterfaces( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + const GUID* InterfaceClassGuid, + DWORD MemberIndex, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData +) +{ + if (sdedip) + (*sdedip)(DeviceInfoSet, DeviceInfoData, InterfaceClassGuid, + MemberIndex, DeviceInterfaceData); + else + fatal(nousb); + +} + +BOOL gusb_SetupDiDestroyDeviceInfoList( + HDEVINFO DeviceInfoSet +) +{ + if (sdedip) + ddilp(DeviceInfoSet); + else + fatal(nousb); +} + +HMODULE libp; + +int +gusb_libinit() +{ + libp = LoadLibrary("setupapi.dll"); + if (!libp) { + fatal("Can not load setupapi.dll"); + } + sdgdidp = GetProcAddress(libp, "SetupDiGetDeviceInterfaceDetail"); + gcdp = GetProcAddress(libp, "SetupDiGetClassDevs"); + sdedip = GetProcAddress(libp, "SetupDiEnumDeviceInterfaces"); + ddilp = GetProcAddress(libp, "SetupDiDestroyDeviceInfoList"); + + if (sdgdidp && gcdp && sdedip && ddilp) + return 0; + else + return 1; +} + int gusb_open(const char *pname) { @@ -83,7 +191,7 @@ gusb_open(const char *pname) // } } - hdevinfo = SetupDiGetClassDevs( &GARMIN_GUID, NULL, NULL, + hdevinfo = gusb_SetupDiGetClassDevs( &GARMIN_GUID, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); if (hdevinfo == INVALID_HANDLE_VALUE) { @@ -93,21 +201,21 @@ gusb_open(const char *pname) /* Get the device associated with this index. */ devinterface.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA); - if (!SetupDiEnumDeviceInterfaces(hdevinfo, NULL, &GARMIN_GUID, + if (!gusb_SetupDiEnumDeviceInterfaces(hdevinfo, NULL, &GARMIN_GUID, 0, &devinterface)) { GPS_Serial_Error("SetupDiEnumDeviceInterfaces"); warning("Is the unit powered up and connected?"); return 0; } - SetupDiGetDeviceInterfaceDetail(hdevinfo, &devinterface, + gusb_SetupDiGetDeviceInterfaceDetail(hdevinfo, &devinterface, NULL, 0, &size, NULL); pdd = malloc(size); pdd->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); devinfo.cbSize = sizeof(SP_DEVINFO_DATA); - if (!SetupDiGetDeviceInterfaceDetail(hdevinfo, &devinterface, pdd, size, NULL, &devinfo)) { + if (!gusb_SetupDiGetDeviceInterfaceDetail(hdevinfo, &devinterface, pdd, size, NULL, &devinfo)) { GPS_Serial_Error("SetupDiGetDeviceInterfaceDetail"); return 0; } @@ -130,7 +238,7 @@ gusb_open(const char *pname) if (pdd) { free(pdd); } - SetupDiDestroyDeviceInfoList(hdevinfo); + gusb_SetupDiDestroyDeviceInfoList(hdevinfo); for (maxtries = maxct; maxtries; maxtries--) { |