News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Enumerating USB?

Started by georgek01, June 28, 2005, 04:03:15 PM

Previous topic - Next topic

georgek01

I'm hoping someone can assist me with this problem.

I need to enumerate USB devices connected to a WIN XP machine. For now I'm using the GUID class for a mouse just to test. I'm able (or so I think) to get a handle to that class using 'SetupDiGetClassDevs'. Once I start my first enumeration call to 'SetupDiEnumDeviceInterfaces' I receive 'No more data available.'

Any obvious reason why the enumeration is not returning TRUE?

.data

; mouse class GUID 4D36E96F-E325-11CE-BFC1-08002BE10318

sCGUID TEXTEQU <{04D36E96FH, 0E325H, 011CEH, {0BFH, 0C1H, 008H, 000H, 02BH, 0E1H, 003H, 018H}}>

CGUID GUID sCGUID


EnumUSB proc hWnd:DWORD

local interface_info:SP_DEVICE_INTERFACE_DATA
local interface_detail:SP_DEVICE_INTERFACE_DETAIL_DATA
local needed:DWORD
local mybuffer :LPVOID

invoke SetupDiGetClassDevs,addr CGUID,NULL,NULL,DIGCF_PRESENT or DIGCF_DEVICEINTERFACE

mov hInfo,eax

invoke SetLastError,0

.if hInfo == INVALID_HANDLE_VALUE
invoke MessageBox,hWnd,addr szAppError,addr szAppName,MB_OK or MB_ICONERROR
invoke SetupDiDestroyDeviceInfoList,hInfo
xor eax,eax
ret
.endif

invoke GetLastError
mov edi,eax

.if edi != 0
invoke FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,0,edi,0,addr mybuffer,0,NULL
invoke MessageBox,hWnd,mybuffer,addr szAppName,MB_OK or MB_ICONERROR
invoke SetupDiDestroyDeviceInfoList,hInfo
xor eax,eax
ret
.endif

mov ecx, 0

invoke SetLastError,0

.while eax != FALSE
mov interface_info.cbSize, sizeof interface_info
invoke SetupDiEnumDeviceInterfaces,hInfo,NULL,addr CGUID,ecx,addr interface_info

; error occurs here: 'No more data available.' on first call (ecx = 0)

.if eax == FALSE
invoke GetLastError
mov edi,eax

.if edi != 0
invoke FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,0,edi,0,addr mybuffer,0,NULL
invoke MessageBox,hWnd,mybuffer,addr szAppName,MB_OK or MB_ICONERROR
.endif

invoke SetupDiDestroyDeviceInfoList,hInfo
xor eax,eax
ret
.endif

mov interface_detail.cbSize,132
invoke SetupDiGetDeviceInterfaceDetail,hInfo,addr interface_info,addr interface_detail,0,256, NULL

.if eax == FALSE
invoke SetupDiDestroyDeviceInfoList,hInfo
invoke MessageBox,hWnd,addr szAppError,addr szAppName,MB_OK or MB_ICONERROR
xor eax,eax
ret
.endif

inc ecx

.endw

xor eax, eax
Ret
EnumUSB EndP
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

doomsday

Possibly a stupid question but based on the following assumptions
- you're enumerating USB devices
and
- you're trying to get it to enumerate your mouse (to test the code)

Is it possible that it's not finding anything because you don't have a USB mouse?

regards,
-Brent

georgek01

Yes, I do have a USB mouse attached to my machine. It is possible that the class I'm using is incorrect. Would you perhaps know where I can get the correct class from? I looked through the registry but cannot see a GUID for pointing device or mouse class.

Thank you for your response.
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

doomsday

God I hope you can read C/C++ !   :)

Take a look at the attached zip.  The list of class GUIDs is in "DevGuid.h", and hopefully some of the code in "main.cpp" will be of use to you.

regards,
-Brent



[attachment deleted by admin]

georgek01

Thanks Brent! The app does exactly what I'm looking for - now only to do the same in assembler...  :eek
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

Mark Jones

Well, you could peek at the assembler code in a debugger such as OllyDbg or just plain disassemble it if it doesn't violate any license agreements (I didn't look at the code.).
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

doomsday

Quote from: georgek01Thanks Brent! The app does exactly what I'm looking for - now only to do the same in assembler...

If you really want I could have a go at re-writing it in for MASM, but I seriously doubt there would be much benefit to be had by doing so.  I haven't run it though a profiler but I'd suggest that 90+ percent of the time, in the relevant code, is spent in API calls anyhow.  But yeah, sure if you like I'll give it a go.

regards,
-Brent

georgek01

Hi Brent,

I've got some of the code down, but I'm struggling with one piece of the puzzle.

C-code:

memset(&devInfoData,0,sizeof(devInfoData));

How will this translate to assembler?

Thank you for your assistance!







What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

georgek01

Will RtlFillMemory and memset produce the same result when passed the same parameters?
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

chep

Hi george,

Quote from: georgek01 on July 04, 2005, 03:10:12 PM
Will RtlFillMemory and memset produce the same result when passed the same parameters?

You have to swap the Length & Fill parameters :

memset(PVOID Destination, BYTE Fill, SIZE_T Length)
RtlFillMemory(PVOID Destination, SIZE_T Length, BYTE Fill)

As you are zeroing the memory, you could also use RtlZeroMemory(PVOID Destination, SIZE_T Length) and ommit the 0 parameter.

doomsday

If you swap the last two arguments, they should.

memset( PointerToMemoryBlock, ByteToFillBlockWith, SizeOfBlock)

vs

RtlFillMemory( PointerToMemoryBlock, SizeOfBlock, ByteToFillBlockWith)

vs

mov edi, PointerToMemoryBlock
mov ecx, SizeOfBlock
mov al, ByteToFillBlockWith
rep stosb



BTW, I doubt that it's necessary to 0-fill the structure in any case... but I left it there on the basis that it can't hurt.

regards,
-Brent

georgek01

Thank you!

I am however receiving The supplied user buffer is invalid for the requested operation. I think it may have something to do with my structure definition.

I've translated...

typedef struct _SP_DEVINFO_DATA { 
    DWORD cbSize; 
    GUID ClassGuid; 
    DWORD DevInst; 
    ULONG_PTR Reserved;
} SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;


to...

SP_DEVINFO_DATA STRUCT 
cbSize DWORD ?
ClassGuid DWORD ? 
DevInst DWORD  ?
Reserved DWORD ?
SP_DEVINFO_DATA EndS


Am I correct in assuming ULONG_PTR = DWORD?
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)

chep

Quote from: georgek01 on July 04, 2005, 03:34:45 PM
Am I correct in assuming ULONG_PTR = DWORD?

Yes, but a GUID is not a DWORD:

Quote from: Windows.inc_GUID STRUCT
  Data1           DWORD ?
  Data2           WORD ?
  Data3           WORD ?
  Data4           BYTE 8 dup (?)
_GUID ENDS

so I think it should be:
SP_DEVINFO_DATA STRUCT 
cbSize DWORD ?
ClassGuid _GUID <?>
DevInst DWORD  ?
Reserved DWORD ?
SP_DEVINFO_DATA EndS

georgek01

That works just fine!  :U Thank you!
What we have to learn to do, we learn by doing.

- ARISTOTLE (384-322 BC)