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
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
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.
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]
Thanks Brent! The app does exactly what I'm looking for - now only to do the same in assembler... :eek
Well, you could peek at the assembler code in a debugger such as OllyDbg (http://www.ollydbg.de/) or just plain disassemble it if it doesn't violate any license agreements (I didn't look at the code.).
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
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!
Will RtlFillMemory and memset produce the same result when passed the same parameters?
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.
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
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?
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
That works just fine! :U Thank you!