Need help with WinUSB and x64 Vista

Hi. I have a small WinUSB test program (calling WinUSB from an application) that is functioning under 32-bit Windows (XP). I can compile and run the program for 64-bits but I’m experiencing a problem under Vista x64 when I run it. On x64 Vista, the program communicates successfully through WinUSB (prints out interface and pipe data), but crashes when my program “frees” my allocated memory just before ending the program. I think I’m doing something wrong with the memory allocation, but can’t pinpoint it. Here’s my data type (which should represent a single USB device") taken from the header file:

typedef struct
{
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetailData;
HANDLE deviceInterfaceHandle;
}*DeviceData;

Now, in the main program (which is quite small), I make a variable to hold a list of USB devices:

DeviceData *deviceList;

Later, after figuring out how many devices there are on the system (in the variable “index”), I allocate memory for the “deviceList”:

deviceList = malloc(index * sizeof(DeviceData));

Then, I do what’s necessary to get a WinUSB handle, print out USB device info, then my troubles begin:

  1. I free the WinUSB handle:
    WinUsb_Free(winusbHandle);

  2. I close device handles:
    CloseHandle(deviceList[i]->deviceInterfaceHandle);

  3. I free deviceDetailData (used to get WinUSB Handle)
    free(deviceList[i]->deviceDetailData);

  4. Finally, I try to free my device list:
    free (deviceList);

Does the above look right? The program crashes after the last line of the program under Vista x64 and then starts trying to contact Microsoft. Am I missing something simple? The program is relatively small and easily posted here if anyone would like to see the code.

Also, let me know if there are any good tools to catch memory leaks…

–Brian Hindman

BRIAN:

How are you allocating (and initializing) each member of the array?
That is, there’s nothing below which performs these operations for every
deviceList[index], which, according to the definition of DeviceData, is
a pointer to an unnamed structure; I only see code to allocate the
array of pointers (deviceList = malloc(index * sizeof(DeviceData));).
This information would help. If you’re still out there, as the program
is small, just post the whole thing. I don’t know anything about
WinUSB, but it doesn’t sound like it has anything to do with your
problem, and I’ll be around for a while.

mm

(P. S. - The three memory leak detectors that I know of are
BoundsChecker (Compuware), Purify (Rational/IBM) and Insure++
(Parasoft). The only one I have ever used (and even then only on a
limited basis) is BoundsChecker. It works well, but the last time I
really used it was when it was a NuMega Labs product, and, in my
opinion, Compuware is a shameless bunch of pirates to whom I do my very
best not to give a cent. I’ve had to compromise this for one product,
but SoftICE is occasionally useful to address situations that neither
WinDbg nor any other product of which I am aware can handle.)

>> xxxxx@dalsemi.com 2007-05-02 14:18 >>>
Hi. I have a small WinUSB test program (calling WinUSB from an
application) that is functioning under 32-bit Windows (XP). I can
compile and run the program for 64-bits but I’m experiencing a problem
under Vista x64 when I run it. On x64 Vista, the program communicates
successfully through WinUSB (prints out interface and pipe data), but
crashes when my program “frees” my allocated memory just before ending
the program. I think I’m doing something wrong with the memory
allocation, but can’t pinpoint it. Here’s my data type (which should
represent a single USB device") taken from the header file:

typedef struct
{
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetailData;
HANDLE deviceInterfaceHandle;
}*DeviceData;

Now, in the main program (which is quite small), I make a variable to
hold a list of USB devices:

DeviceData *deviceList;

Later, after figuring out how many devices there are on the system (in
the variable “index”), I allocate memory for the “deviceList”:

deviceList = malloc(index * sizeof(DeviceData));

Then, I do what’s necessary to get a WinUSB handle, print out USB
device info, then my troubles begin:

  1. I free the WinUSB handle:
    WinUsb_Free(winusbHandle);

  2. I close device handles:
    CloseHandle(deviceList[i]->deviceInterfaceHandle);

  3. I free deviceDetailData (used to get WinUSB Handle)
    free(deviceList[i]->deviceDetailData);

  4. Finally, I try to free my device list:
    free (deviceList);

Does the above look right? The program crashes after the last line of
the program under Vista x64 and then starts trying to contact Microsoft.
Am I missing something simple? The program is relatively small and
easily posted here if anyone would like to see the code.

Also, let me know if there are any good tools to catch memory leaks…

–Brian Hindman


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Hi. Thanks for offering to take a look. I’ll clean up the code and post it. I’m relatively new to allocating memory, so don’t be too surprised if I’ve missed an important concept or two.

–Brian Hindman

Here’s the code:

#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <setupapi.h>
#include <winusb.h>
#include <winusbio.h>
#include “WinUSBTest.h”

//----------------------------------------------------------------------
// Main for WinUSBTest
//
int main(int argc, char argv)
{
HDEVINFO hdevClassInfo; // A handle to a device information set.
// Requires passing in GUID of class info from
// inf file used to install WinUSB.
SP_DEVICE_INTERFACE_DATA deviceInfoData;
DeviceData *deviceList;
ULONG index, i;
ULONG requiredLength;
BOOL nStatus = FALSE;
LPCTSTR Path;
HANDLE DeviceInterfaceHandle;
USB_INTERFACE_DESCRIPTOR interfaceDesc;
WINUSB_PIPE_INFORMATION pipe;
UCHAR pipecount = 0;
WINUSB_INTERFACE_HANDLE winusbHandle;

// Iterate over usb devices using the new GUID based interface

// First get handle to device class info associated with the DS9490’s GUID
// registered to WinUSB through the INF installation file. It is also
// located in the WinUSBTest.h file.
hdevClassInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_DS2490,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));

// If handle is invalid then return error
if (hdevClassInfo == INVALID_HANDLE_VALUE)
{
//ERROR
printf(“Error retrieving handle to the 1-Wire USB device class. Is driver installed?\n”);
return (FALSE);
}

deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

// Iteratively call SetupDiEnumDeviceInterfaces to determine how many elements are in the device
// information set. The number of elements found will be held in “index”. For our case, this
// will signify the number of DS2490-based devices on the USB bus.
for (index = 0; TRUE; index++)
{
nStatus = SetupDiEnumDeviceInterfaces (hdevClassInfo,
NULL,
(LPGUID)&GUID_DEVINTERFACE_DS2490,
index,
&deviceInfoData);
if (nStatus != TRUE) break;
}

// Allocate memory for device list
deviceList = (DeviceData *) malloc(index * sizeof(DeviceData));
if (deviceList == NULL)
{
// ERROR
printf(“Error allocating memory\n”);
return 0;
}

// Enumerate through DS9490s found, this time retrieving their symbolic links
// otherwise known as device interface handles, and saving them off in an array
// of structs for use later on. These can be used later on to retrieve a WinUSB
// handle.

// loop through DS2490-based devices
for (i = 0; i < index; i++)
{
nStatus = SetupDiEnumDeviceInterfaces(hdevClassInfo,
0,
(LPGUID)&GUID_DEVINTERFACE_DS2490,
i,
&deviceInfoData);

// Call SetupDiGetDeviceInterfaceDetail just to get requiredLength of struct
SetupDiGetDeviceInterfaceDetail(hdevClassInfo,
&deviceInfoData,
NULL,
0,
&requiredLength,
NULL);

// Allocate memory for deviceDetailData (the length of the device path struct member).
deviceList[i]->deviceDetailData->cbSize = 0; // initialize
deviceList[i]->deviceDetailData = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(requiredLength);

// The cbSize member of struct should be the size of the struct
deviceList[i]->deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

if (deviceList[i]->deviceDetailData == NULL)
{
// Error – memory not allocated
}

// This second call to SetupDiGetDeviceInterfaceDetail gets
// deviceList[i] populated with the all important
// “device interface path”, which is used to eventually get
// a handle to WinUSB.

if (!SetupDiGetDeviceInterfaceDetail(hdevClassInfo,
&deviceInfoData,
deviceList[i]->deviceDetailData,
requiredLength,
&requiredLength,
NULL))
{
// Error
printf(“Error getting device interface paths\n”);
}
}

// print out number of devices found
printf(“\nTotal number of devices found: %i\n\n”,index);
// we have device paths, so use them to get device interface handles,
// which are used, in turn, to get winusb handles.
for (i = 0; i < index; i++)
{
// get device interface handles
// Create a handle to device interface
deviceList[i]->deviceInterfaceHandle = CreateFile (deviceList[i]->deviceDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);

if (deviceList[i]->deviceInterfaceHandle == INVALID_HANDLE_VALUE)
{
// ERROR
printf(“Error retrieving device interface handle\n”);
}
}

if (index == 0)
{
printf(“\nNo parts found. Exiting…\n”);
return 0;
}

// now, get handle to WinUSB – just get the first one
nStatus = WinUsb_Initialize (deviceList[0]->deviceInterfaceHandle, &winusbHandle);
if (nStatus == FALSE)
{
// ERROR
printf(“Error initializing WinUSB and obtaining a handle\n”);
return 0;
}

// setup USB pipes

//
******************************************
// The first interface consists of 3 endpoints.
// ********************************************

// get interface description
nStatus = WinUsb_QueryInterfaceSettings(winusbHandle, 0, &interfaceDesc);
if (nStatus == FALSE)
{
// ERROR
printf(“Error – Could not query WinUSB interface settings\n”);
}
// print out interface settings
printf(“\nInterface 0: \n\n”);
printf(" Interface info: Alternate setting = %i\n",interfaceDesc.bAlternateSetting);
printf(" Interface info: Descriptor type = %i\n",interfaceDesc.bDescriptorType);
printf(" Interface info: Interface class = %i\n",interfaceDesc.bInterfaceClass);
printf(" Interface info: Interface number = %i\n",interfaceDesc.bInterfaceNumber);
printf(" Interface info: Interface protocol = %i\n",interfaceDesc.bInterfaceProtocol);
printf(" Interface info: Interface subclass = %i\n",interfaceDesc.bInterfaceSubClass);
printf(" Interface info: Length = %i\n",interfaceDesc.bLength);
printf(" Interface info: Number of End Points (pipes) = %i\n",interfaceDesc.bNumEndpoints);
printf(" Interface info: Interface = %i\n\n",interfaceDesc.iInterface);

// get pipe (endpoint) info
pipecount = 0;
while (WinUsb_QueryPipe (winusbHandle, 0, pipecount, &pipe))
{
// print out pipe information
printf(" Pipe info: WinUSB pipe count = %i\n",pipecount);
printf(" Pipe info: Pipe polling interval = %i ms (not valid on Bulk pipes)\n",pipe.Interval);
printf(" Pipe info: Maximum packet size = %i bytes\n",pipe.MaximumPacketSize);
printf(" Pipe info: Pipe ID = 0x%02x\n",pipe.PipeId);
switch (pipe.PipeType)
{
case UsbdPipeTypeControl:
printf(" Pipe info: Pipe Type = UsbdPipeTypeControl\n");
break;
case UsbdPipeTypeIsochronous:
printf(" Pipe info: Pipe Type = UsbdPipeTypeIsochronous\n");
break;
case UsbdPipeTypeBulk:
printf(" Pipe info: Pipe Type = UsbdPipeTypeBulk\n");
break;
case UsbdPipeTypeInterrupt:
printf(" Pipe info: Pipe Type = UsbdPipeTypeInterrupt\n");
break;
default:
printf(" Pipe info: Unknown Pipe Type\n");
break;
}
printf(“\n”);
pipecount++;
}
if (pipecount == 0)
{
// ERROR
printf(“Error – Could not query WinUSB pipe settings\n”);
}

// “free” winusb handle
if (!WinUsb_Free(winusbHandle))
{
// ERROR
printf(“Error closing WinUSB handle\n”);
}

for (i = 0; i < index; i++)
{
if (deviceList[i]->deviceInterfaceHandle != NULL)
{
CloseHandle(deviceList[i]->deviceInterfaceHandle);
deviceList[i]->deviceInterfaceHandle = NULL;
}
}

for (i = 0; i < index; i++)
{
if (deviceList[i]->deviceDetailData != NULL)
{
free(deviceList[i]->deviceDetailData);
deviceList[i]->deviceDetailData = NULL;
}
}

// we must clean up…
if (deviceList != NULL)
{
free (deviceList);
}

return 1;
}</winusbio.h></winusb.h></setupapi.h></stdlib.h></stdio.h></malloc.h></windows.h>

BRIAN:

Assuming you using the definition of DeviceData that you originally
posted, it seems to that you’re either failing to call malloc for each
DeviceData member of deviceList, or, more likely, you’re typedef for
deviceData is incorrect, and should not be a pointer. That is

struct
{

} deviceData;

not

struct
{

} * deviceData;

If you’re not allocating correctly, things may work for a while, but
will eventually fail. It is totally possible that I am missing
something here, because I don’t know what WinUSB is expecting or how it
interacts with your code, if at all.

You said that you’re new at this. Did you copy this code from an
example, or base it on one? Please post the WinUSBTest.h file as well
(I assume that this is where deviceData is declared).

mm

>> xxxxx@dalsemi.com 2007-05-03 12:56 >>>
Here’s the code:

#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <setupapi.h>
#include <winusb.h>
#include <winusbio.h>
#include “WinUSBTest.h”

//----------------------------------------------------------------------
// Main for WinUSBTest
//
int main(int argc, char argv)
{
HDEVINFO hdevClassInfo; // A handle to
a device information set.

// Requires passing in GUID of class info from

// inf file used to install WinUSB.
SP_DEVICE_INTERFACE_DATA deviceInfoData;
DeviceData *deviceList;
ULONG index, i;
ULONG requiredLength;
BOOL nStatus =
FALSE;
LPCTSTR Path;
HANDLE
DeviceInterfaceHandle;
USB_INTERFACE_DESCRIPTOR interfaceDesc;
WINUSB_PIPE_INFORMATION pipe;
UCHAR pipecount = 0;
WINUSB_INTERFACE_HANDLE winusbHandle;

// Iterate over usb devices using the new GUID based interface

// First get handle to device class info associated with the
DS9490’s GUID
// registered to WinUSB through the INF installation file. It is
also
// located in the WinUSBTest.h file.
hdevClassInfo =
SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_DS2490,
NULL,
NULL,
(DIGCF_PRESENT |
DIGCF_DEVICEINTERFACE));

// If handle is invalid then return error
if (hdevClassInfo == INVALID_HANDLE_VALUE)
{
//ERROR
printf(“Error retrieving handle to the 1-Wire USB device class.
Is driver installed?\n”);
return (FALSE);
}

deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

// Iteratively call SetupDiEnumDeviceInterfaces to determine how
many elements are in the device
// information set. The number of elements found will be held in
“index”. For our case, this
// will signify the number of DS2490-based devices on the USB bus.
for (index = 0; TRUE; index++)
{
nStatus = SetupDiEnumDeviceInterfaces (hdevClassInfo,
NULL,

(LPGUID)&GUID_DEVINTERFACE_DS2490,
index,
&deviceInfoData);
if (nStatus != TRUE) break;
}

// Allocate memory for device list
deviceList = (DeviceData *) malloc(index * sizeof(DeviceData));
if (deviceList == NULL)
{
// ERROR
printf(“Error allocating memory\n”);
return 0;
}

// Enumerate through DS9490s found, this time retrieving their
symbolic links
// otherwise known as device interface handles, and saving them off
in an array
// of structs for use later on. These can be used later on to
retrieve a WinUSB
// handle.

// loop through DS2490-based devices
for (i = 0; i < index; i++)
{
nStatus = SetupDiEnumDeviceInterfaces(hdevClassInfo,
0,

(LPGUID)&GUID_DEVINTERFACE_DS2490,
i,
&deviceInfoData);

// Call SetupDiGetDeviceInterfaceDetail just to get
requiredLength of struct
SetupDiGetDeviceInterfaceDetail(hdevClassInfo,
&deviceInfoData,
NULL,
0,
&requiredLength,
NULL);

// Allocate memory for deviceDetailData (the length of the
device path struct member).
deviceList[i]->deviceDetailData->cbSize = 0; // initialize
deviceList[i]->deviceDetailData =
(PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(requiredLength);

// The cbSize member of struct should be the size of the struct
deviceList[i]->deviceDetailData->cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

if (deviceList[i]->deviceDetailData == NULL)
{
// Error – memory not allocated
}

// This second call to SetupDiGetDeviceInterfaceDetail gets

// deviceList[i] populated with the all important
// “device interface path”, which is used to eventually get

// a handle to WinUSB.

if (!SetupDiGetDeviceInterfaceDetail(hdevClassInfo,
&deviceInfoData,

deviceList[i]->deviceDetailData,
requiredLength,
&requiredLength,
NULL))
{
// Error
printf(“Error getting device interface paths\n”);
}
}

// print out number of devices found
printf(“\nTotal number of devices found: %i\n\n”,index);
// we have device paths, so use them to get device interface
handles,
// which are used, in turn, to get winusb handles.
for (i = 0; i < index; i++)
{
// get device interface handles
// Create a handle to device interface
deviceList[i]->deviceInterfaceHandle = CreateFile
(deviceList[i]->deviceDetailData->DevicePath,
GENERIC_READ |
GENERIC_WRITE,

FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,

FILE_FLAG_OVERLAPPED,
NULL);

if (deviceList[i]->deviceInterfaceHandle == INVALID_HANDLE_VALUE)

{
// ERROR
printf(“Error retrieving device interface handle\n”);
}
}

if (index == 0)
{
printf(“\nNo parts found. Exiting…\n”);
return 0;
}

// now, get handle to WinUSB – just get the first one
nStatus = WinUsb_Initialize (deviceList[0]->deviceInterfaceHandle,
&winusbHandle);
if (nStatus == FALSE)
{
// ERROR
printf(“Error initializing WinUSB and obtaining a handle\n”);
return 0;
}

// setup USB pipes

//
******************************************
// The first interface consists of 3 endpoints.
// ********************************************

// get interface description
nStatus = WinUsb_QueryInterfaceSettings(winusbHandle, 0,
&interfaceDesc);
if (nStatus == FALSE)
{
// ERROR
printf(“Error – Could not query WinUSB interface settings\n”);
}
// print out interface settings
printf(“\nInterface 0: \n\n”);
printf(" Interface info: Alternate setting =
%i\n",interfaceDesc.bAlternateSetting);
printf(" Interface info: Descriptor type =
%i\n",interfaceDesc.bDescriptorType);
printf(" Interface info: Interface class =
%i\n",interfaceDesc.bInterfaceClass);
printf(" Interface info: Interface number =
%i\n",interfaceDesc.bInterfaceNumber);
printf(" Interface info: Interface protocol =
%i\n",interfaceDesc.bInterfaceProtocol);
printf(" Interface info: Interface subclass =
%i\n",interfaceDesc.bInterfaceSubClass);
printf(" Interface info: Length = %i\n",interfaceDesc.bLength);
printf(" Interface info: Number of End Points (pipes) =
%i\n",interfaceDesc.bNumEndpoints);
printf(" Interface info: Interface =
%i\n\n",interfaceDesc.iInterface);

// get pipe (endpoint) info
pipecount = 0;
while (WinUsb_QueryPipe (winusbHandle, 0, pipecount, &pipe))
{
// print out pipe information
printf(" Pipe info: WinUSB pipe count = %i\n",pipecount);
printf(" Pipe info: Pipe polling interval = %i ms (not
valid on Bulk pipes)\n",pipe.Interval);
printf(" Pipe info: Maximum packet size = %i
bytes\n",pipe.MaximumPacketSize);
printf(" Pipe info: Pipe ID = 0x%02x\n",pipe.PipeId);
switch (pipe.PipeType)
{
case UsbdPipeTypeControl:
printf(" Pipe info: Pipe Type =
UsbdPipeTypeControl\n");
break;
case UsbdPipeTypeIsochronous:
printf(" Pipe info: Pipe Type =
UsbdPipeTypeIsochronous\n");
break;
case UsbdPipeTypeBulk:
printf(" Pipe info: Pipe Type =
UsbdPipeTypeBulk\n");
break;
case UsbdPipeTypeInterrupt:
printf(" Pipe info: Pipe Type =
UsbdPipeTypeInterrupt\n");
break;
default:
printf(" Pipe info: Unknown Pipe Type\n");
break;
}
printf(“\n”);
pipecount++;
}
if (pipecount == 0)
{
// ERROR
printf(“Error – Could not query WinUSB pipe settings\n”);
}

// “free” winusb handle
if (!WinUsb_Free(winusbHandle))
{
// ERROR
printf(“Error closing WinUSB handle\n”);
}

for (i = 0; i < index; i++)
{
if (deviceList[i]->deviceInterfaceHandle != NULL)
{
CloseHandle(deviceList[i]->deviceInterfaceHandle);
deviceList[i]->deviceInterfaceHandle = NULL;
}
}

for (i = 0; i < index; i++)
{
if (deviceList[i]->deviceDetailData != NULL)
{
free(deviceList[i]->deviceDetailData);
deviceList[i]->deviceDetailData = NULL;
}
}

// we must clean up…
if (deviceList != NULL)
{
free (deviceList);
}

return 1;
}


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer</winusbio.h></winusb.h></setupapi.h></stdlib.h></stdio.h></malloc.h></windows.h>

Hi. Thanks for taking a look! Yes, I based this code on the WinUSB example located here:

http://msdn2.microsoft.com/en-us/library/aa476413.aspx

As the code in the above linked page does seem to have a few problems, I also based some of the code on the usbview program in the WDK.

One more thing to mention is that I have been able to cut out the WinUSB stuff and just leave the SetupAPI stuff. I still get the problem under x64 Vista (which I think means WinUSB is out of the picture).

Here is the header file:
#include <initguid.h>

#ifdef DEFINE_GUID // don’t break compiles of drivers that
// include this header but don’t want the
// GUIDs

DEFINE_GUID(GUID_DEVINTERFACE_DS2490, 0xE958DAA2, 0xF01C, 0x47CB, 0x8A, 0x1E, 0x36, 0x67, 0x9A, 0x16, 0x23, 0x5E);

#endif // DEFINE_GUID

#define MAX_NUMBER_OF_DS2490_DEVICES 16

// An array of DeviceData makes a good list of ds2490-based devices. A list should be
// kept as a global array…
typedef struct myDeviceData
{
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetailData;
HANDLE deviceInterfaceHandle;
}*DeviceData;</initguid.h>

THANKS!!! That was it! I just re-defined my pointers, and everything worked!!!

That puts my project much closer to release… :slight_smile:

–Brian Hindman

glad it worked, brian.

>> xxxxx@dalsemi.com 2007-05-03 17:44 >>>
THANKS!!! That was it! I just re-defined my pointers, and everything
worked!!!

That puts my project much closer to release… :slight_smile:

–Brian Hindman


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer