Check an handle for validity

Hi there,

I'm having a little fun with a USB device, this one's HID compliant.
Connecting to the the device is pretty simple, after a bunch of calls I get the device path, with this I can eventually open an handle to the device, like this:

1
2
3
4
5
6
7
8
	HANDLE hdl_device = CreateFile(
		ptr_detail_data->DevicePath,
		GENERIC_WRITE | GENERIC_READ,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_OVERLAPPED,
		NULL);


Well, it works just fine.
The question is now: How can I know if the device has been disconnected?
I'd like to know this prior to further calls to ReadFile() / WriteFile(). A polling solution would be just fine, I could place it in a different thread and continuously call some kind of function in order to know whether the handle is still valid (that is, the device is still attached).
Do you guys know any suitable function for doing so?
I did something like this before using DeviceIoControl and IOCTL_STORAGE_CHECK_VERIFY
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <windows.h>
#include <winioctl.h>

bool is_connected(HANDLE hDev)
{
DWORD ret;
if(DeviceIoControl(hDev, IOCTL_STORAGE_CHECK_VERIFY, NULL,0,NULL, 0, &ret, 0 )!=0)    return true;

}

int main()
{
DWORD ret;

HANDLE hFile=CreateFile("\\\\.\\A:",GENERIC_READ,7,0,OPEN_EXISTING,0,0);
MessageBox(0,"after you press enter, program will check if disk is accessible","",64);
if(is_connected(hFile)==true) MessageBox(0,"Accessible","",64);
else MessageBox(0,"Not accessible","",16);


}



http://msdn.microsoft.com/en-us/library/aa363404(v=VS.85).aspx
Last edited on
Exactly what I was looking for!

Thanks man, you saved me a lot of time and googling pain ^^
Btw, can you show me how to get USB device path?
Sure, here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

	class Device {
	public:

		....

	private:

		....

		HANDLE hdl_device;
		HIDD_ATTRIBUTES hid_dev_attributes;
		PSP_DEVICE_INTERFACE_DETAIL_DATA ptr_detail_data;
		HDEVINFO hdl_dev_info;
		GUID hid_guid;
		HANDLE hdl_io_event;
		OVERLAPPED overlap_io;
	};

void Hid::Device::connect()
throw(DeviceExc::NotAttached, DeviceExc::ApiCallFail)
{
	hdl_dev_info = SetupDiGetClassDevs(
			&hid_guid,
			NULL,
			NULL,
			DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );
	if (!hdl_dev_info)
		throw DeviceExc::ApiCallFail(GetLastError());

	hdl_io_event = CreateEvent(
			NULL,
			TRUE,
			TRUE,
			"");
	if (!hdl_io_event)
	{
		DWORD last_err = GetLastError();
		SetupDiDestroyDeviceInfoList(hdl_dev_info);
		hdl_dev_info = 0;
		throw DeviceExc::ApiCallFail(last_err);
	}
	overlap_io.hEvent = hdl_io_event;
	overlap_io.Offset = 0;
	overlap_io.OffsetHigh = 0;

	unsigned int interf_indexer = 0;
	unsigned char more_available;
	do {

		SP_DEVICE_INTERFACE_DATA dev_info_data;
		dev_info_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
		more_available = SetupDiEnumDeviceInterfaces(
				hdl_dev_info,
				0,
				&hid_guid,
				interf_indexer,
				&dev_info_data);

		DWORD length;
		SetupDiGetDeviceInterfaceDetail(
				hdl_dev_info,
				&dev_info_data,
				NULL,
				0,
				&length,
				0 );
		ptr_detail_data = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>
					(new unsigned char[length]);
		ptr_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
		BOOL result = SetupDiGetDeviceInterfaceDetail(
				hdl_dev_info,
				&dev_info_data,
				ptr_detail_data,
				length,
				NULL,
				NULL );
		if (!result)
		{
			DWORD last_err = GetLastError();
			delete[] ptr_detail_data;
			ptr_detail_data = 0;
			SetupDiDestroyDeviceInfoList(hdl_dev_info);
			hdl_dev_info = 0;
			CloseHandle(hdl_io_event);
			hdl_io_event = 0;
			throw DeviceExc::ApiCallFail(last_err);
		}

		hdl_device = CreateFile(
				ptr_detail_data->DevicePath,
				GENERIC_WRITE | GENERIC_READ,
				FILE_SHARE_READ | FILE_SHARE_WRITE,
				NULL,
				OPEN_EXISTING,
				FILE_FLAG_OVERLAPPED,
				NULL);
		if (hdl_device != INVALID_HANDLE_VALUE)
		{
			hid_dev_attributes.Size = sizeof(hid_dev_attributes);
			result = HidD_GetAttributes(
					hdl_device,
					&hid_dev_attributes);

			if ( hid_dev_attributes.VendorID == this->vendor_id &&
					hid_dev_attributes.ProductID == this->product_id)
				return;

			CloseHandle(hdl_device);
			hdl_device = INVALID_HANDLE_VALUE;
		}
		delete[] ptr_detail_data;
		ptr_detail_data = 0;

		interf_indexer++;
	} while(more_available);

	SetupDiDestroyDeviceInfoList(hdl_dev_info);
	hdl_dev_info = 0;
	CloseHandle(hdl_io_event);
	hdl_io_event = 0;
	throw DeviceExc::NotAttached();
}


Basically you iterate through all the devices until you find out a device with vendor_id and product_id which fits.

BTW I just finished going through some ReadFile() trouble, gonna try out DeviceIoControl() :)
I'm in a pickle, again x_x

I'm building Win32 native code using GCC (MinGW).
Let's say I got a cpp file with some inclusions, like this:
1
2
3
#include <windows.h>
#include <setupapi.h>
#include <ddk/hidsdi.h> 


Let's now say I need a definition which comes from the header "winioctl.h", I include it too as a consequence:
1
2
3
4
#include <windows.h>
#include <setupapi.h>
#include <ddk/hidsdi.h>
#include <winioctl.h> 


Well, let's compile it! Oh my god what the......

C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/winioctl.h:208: error: multiple definition of `enum _PARTITION_STYLE'
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/ddk/winddk.h:3575: error: previous definition here
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/winioctl.h:209: error: conflicting declaration 'PARTITION_STYLE_MBR'
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/ddk/winddk.h:3576: error: 'PARTITION_STYLE_MBR' has a previous declaration as `_PARTITION_STYLE PARTITION_STYLE_MBR'
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/winioctl.h:209: error: declaration of `PARTITION_STYLE_MBR'
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/ddk/winddk.h:3576: error: conflicts with previous declaration `_PARTITION_STYLE PARTITION_STYLE_MBR'
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/winioctl.h:210: error: conflicting declaration 'PARTITION_STYLE_GPT'
....................... (this goes on and on and on and on....)


Am I that retarded or is MinGW broken down? Could you guys please try this out on your machines? Just an empty hello world project, with those inclusions



PS: Since I only need IOCTL_STORAGE_CHECK_VERIFY from that header I managed to make some copy pasting from it, and it works:

1
2
3
4
5
6
#include <windows.h>
#include <setupapi.h>
#include <ddk/hidsdi.h>
//#include <winioctl.h>
#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE
#define IOCTL_STORAGE_CHECK_VERIFY     CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) 


But this is quite an awful workaround, I'd like to understand why MinGW has that many redundant definitions in its headers, causing code compiling to fail.

BTW Null the IOCTL_STORAGE_CHECK_VERIFY trick works just fine :D
Last edited on
Mixing the DDK headers and the normal API headers produces a lot of conflict like that.
I see, does this also happen with M$ VC++ ?
yes
Topic archived. No new replies allowed.