📄 testapp.c
字号:
CloseDeviceHandles(deviceInfo);
//
// Unlink this deviceInfo from the list and free the memory
//
RemoveEntryList(&deviceInfo->ListEntry);
HeapFree (GetProcessHeap(), 0, deviceInfo);
break;
case DBT_DEVICEREMOVEPENDING:
Display(TEXT("Remove Pending (Handle Notification):%ws"),
deviceInfo->DeviceName);
//
// Device is removed so close the handle if it's there
// and unregister the notification
//
if (deviceInfo->hHandleNotification) {
UnregisterDeviceNotification(deviceInfo->hHandleNotification);
deviceInfo->hHandleNotification = NULL;
deviceInfo->hDevice = INVALID_HANDLE_VALUE;
}
//
// Unlink this deviceInfo from the list and free the memory
//
RemoveEntryList(&deviceInfo->ListEntry);
HeapFree (GetProcessHeap(), 0, deviceInfo);
break;
case DBT_DEVICEQUERYREMOVEFAILED :
Display(TEXT("Remove failed (Handle Notification):%ws"),
deviceInfo->DeviceName);
//
// Remove failed. So reopen the device and register for
// notification on the new handle. But first we should unregister
// the previous notification.
//
if (deviceInfo->hHandleNotification) {
UnregisterDeviceNotification(deviceInfo->hHandleNotification);
deviceInfo->hHandleNotification = NULL;
}
deviceInfo->hDevice = CreateFile(deviceInfo->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if(deviceInfo->hDevice == INVALID_HANDLE_VALUE) {
Display(TEXT("Failed to reopen the device: %ws"),
deviceInfo->DeviceName);
//
// Unlink this deviceInfo from the list and free the memory
//
RemoveEntryList(&deviceInfo->ListEntry);
HeapFree (GetProcessHeap(), 0, deviceInfo);
break;
}
//
// Register handle based notification to receive pnp
// device change notification on the handle.
//
memset (&filter, 0, sizeof(filter)); //zero the structure
filter.dbch_size = sizeof(filter);
filter.dbch_devicetype = DBT_DEVTYP_HANDLE;
filter.dbch_handle = deviceInfo->hDevice;
deviceInfo->hHandleNotification =
RegisterDeviceNotification(hWnd, &filter, 0);
Display(TEXT("Reopened device %ws"), deviceInfo->DeviceName);
break;
default:
Display(TEXT("Unknown (Handle Notification)"),
deviceInfo->DeviceName);
break;
}
return TRUE;
}
BOOLEAN
EnumExistingDevices(
HWND hWnd
)
{
HDEVINFO hardwareDeviceInfo;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL;
ULONG predictedLength = 0;
ULONG requiredLength = 0, bytes=0;
DWORD dwRegType, error;
DEV_BROADCAST_HANDLE filter;
PDEVICE_INFO deviceInfo =NULL;
UINT i=0;
HRESULT hr;
hardwareDeviceInfo = SetupDiGetClassDevs (
(LPGUID)&InterfaceGuid,
NULL, // Define no enumerator (global)
NULL, // Define no
(DIGCF_PRESENT | // Only Devices present
DIGCF_DEVICEINTERFACE)); // Function class devices.
if(INVALID_HANDLE_VALUE == hardwareDeviceInfo)
{
goto Error;
}
//
// Enumerate devices of toaster class
//
deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
for(i=0; SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
0, // No care about specific PDOs
(LPGUID)&InterfaceGuid,
i, //
&deviceInterfaceData); i++ ) {
//
// Allocate a function class device data structure to
// receive the information about this particular device.
//
//
// First find out required length of the buffer
//
if(deviceInterfaceDetailData)
HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData);
if(!SetupDiGetDeviceInterfaceDetail (
hardwareDeviceInfo,
&deviceInterfaceData,
NULL, // probing so no output buffer yet
0, // probing so output buffer length of zero
&requiredLength,
NULL) && (error = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
{
goto Error;
}
predictedLength = requiredLength;
deviceInterfaceDetailData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
predictedLength);
deviceInterfaceDetailData->cbSize =
sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
if (! SetupDiGetDeviceInterfaceDetail (
hardwareDeviceInfo,
&deviceInterfaceData,
deviceInterfaceDetailData,
predictedLength,
&requiredLength,
NULL)) {
goto Error;
}
deviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(DEVICE_INFO));
if(!deviceInfo)
goto Error;
InitializeListHead(&deviceInfo->ListEntry);
InsertTailList(&ListHead, &deviceInfo->ListEntry);
//
// Get the device details such as friendly name and SerialNo
//
if(!GetDeviceDescription(deviceInterfaceDetailData->DevicePath,
deviceInfo->DeviceName,
NULL)){
goto Error;
}
Display(TEXT("Found device %ws"), deviceInfo->DeviceName );
hr = StringCchCopy(deviceInfo->DevicePath, MAX_PATH, deviceInterfaceDetailData->DevicePath);
if(FAILED(hr)){
goto Error;
}
//
// Open an handle to the device.
//
deviceInfo->hDevice = CreateFile (
deviceInterfaceDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING, // No special create flags
0, // No special attributes
NULL);
if (INVALID_HANDLE_VALUE == deviceInfo->hDevice) {
Display(TEXT("Failed to open the device: %ws"),
deviceInfo->DeviceName);
continue;
}
Display(TEXT("Opened handled to the device: %ws"),
deviceInfo->DeviceName);
//
// Register handle based notification to receive pnp
// device change notification on the handle.
//
memset (&filter, 0, sizeof(filter)); //zero the structure
filter.dbch_size = sizeof(filter);
filter.dbch_devicetype = DBT_DEVTYP_HANDLE;
filter.dbch_handle = deviceInfo->hDevice;
deviceInfo->hHandleNotification = RegisterDeviceNotification(hWnd, &filter, 0);
}
if(deviceInterfaceDetailData)
HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData);
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
return 0;
Error:
error = GetLastError();
MessageBox(hWnd, TEXT("EnumExisting Devices failed"), TEXT("Error!"), MB_OK);
if(deviceInterfaceDetailData)
HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData);
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
Cleanup(hWnd);
return 0;
}
BOOLEAN Cleanup(HWND hWnd)
{
PDEVICE_INFO deviceInfo =NULL;
PLIST_ENTRY thisEntry;
while (!IsListEmpty(&ListHead)) {
thisEntry = RemoveHeadList(&ListHead);
deviceInfo = CONTAINING_RECORD(thisEntry, DEVICE_INFO, ListEntry);
if (deviceInfo->hHandleNotification) {
UnregisterDeviceNotification(deviceInfo->hHandleNotification);
deviceInfo->hHandleNotification = NULL;
}
CloseDeviceHandles(deviceInfo);
HeapFree (GetProcessHeap(), 0, deviceInfo);
}
return TRUE;
}
VOID CloseDeviceHandles(
IN PDEVICE_INFO deviceInfo)
{
if(!deviceInfo) return;
if (deviceInfo->hDevice != INVALID_HANDLE_VALUE &&
deviceInfo->hDevice != NULL) {
CloseHandle(deviceInfo->hDevice);
deviceInfo->hDevice = INVALID_HANDLE_VALUE;
//
// If there is a valid control device handle, close
// that also. We aren't going to get any notification
// on the control-device because it's not known to PNP
// subsystem.
//
if (deviceInfo->hControlDevice != INVALID_HANDLE_VALUE &&
deviceInfo->hControlDevice != NULL) {
CloseHandle(deviceInfo->hControlDevice);
deviceInfo->hControlDevice = INVALID_HANDLE_VALUE;
}
Display(TEXT("Closed handle to device %ws"), deviceInfo->DeviceName );
}
}
BOOL
GetDeviceDescription(
LPTSTR DevPath,
LPTSTR OutBuffer,
PULONG Unused
)
{
HDEVINFO hardwareDeviceInfo;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
SP_DEVINFO_DATA deviceInfoData;
DWORD dwRegType, error;
hardwareDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL);
if(INVALID_HANDLE_VALUE == hardwareDeviceInfo)
{
goto Error;
}
//
// Enumerate devices of toaster class
//
deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
SetupDiOpenDeviceInterface (hardwareDeviceInfo, DevPath,
0, //
&deviceInterfaceData);
deviceInfoData.cbSize = sizeof(deviceInfoData);
if(!SetupDiGetDeviceInterfaceDetail (
hardwareDeviceInfo,
&deviceInterfaceData,
NULL, // probing so no output buffer yet
0, // probing so output buffer length of zero
NULL,
&deviceInfoData) && (error = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
{
goto Error;
}
//
// Get the friendly name for this instance, if that fails
// try to get the device description.
//
if(!SetupDiGetDeviceRegistryProperty(hardwareDeviceInfo, &deviceInfoData,
SPDRP_FRIENDLYNAME,
&dwRegType,
(BYTE*) OutBuffer,
MAX_PATH,
NULL))
{
if(!SetupDiGetDeviceRegistryProperty(hardwareDeviceInfo, &deviceInfoData,
SPDRP_DEVICEDESC,
&dwRegType,
(BYTE*) OutBuffer,
MAX_PATH,
NULL)){
goto Error;
}
}
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
return TRUE;
Error:
error = GetLastError();
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
return FALSE;
}
BOOLEAN
SendIoctlToControlDevice(
IN PDEVICE_INFO deviceInfo)
{
BOOLEAN result = FALSE;
UINT bytes;
//
// Open handle to the control device, if it's not already opened. Please
// note that even a non-admin user can open handle to the device with
// FILE_READ_ATTRIBUTES | SYNCHRONIZE DesiredAccess and send IOCTLs if the
// IOCTL is defined with FILE_ANY_ACCESS. So for better security avoid
// specifying FILE_ANY_ACCESS in your IOCTL defintions.
// If you open the device with GENERIC_READ, you can send IOCTL with
// FILE_READ_DATA access rights. If you open the device with GENERIC_WRITE,
// you can sedn ioctl with FILE_WRITE_DATA access rights.
//
//
if(deviceInfo->hControlDevice != INVALID_HANDLE_VALUE) {
deviceInfo->hControlDevice = CreateFile (
TEXT("\\\\.\\NETVMINI"),
GENERIC_READ | GENERIC_WRITE,//FILE_READ_ATTRIBUTES | SYNCHRONIZE,
FILE_SHARE_READ,
NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING, // No special create flags
FILE_ATTRIBUTE_NORMAL, // No special attributes
NULL);
if (INVALID_HANDLE_VALUE == deviceInfo->hControlDevice) {
Display(TEXT("Failed to open the control device: %ws"),
deviceInfo->DeviceName);
return result;
}
}
//
// send ioclt requests
//
if(!DeviceIoControl (deviceInfo->hControlDevice,
IOCTL_NETVMINI_READ_DATA,
NULL, 0,
NULL, 0,
&bytes, NULL)) {
Display(TEXT("Read IOCTL to %ws failed"), deviceInfo->DeviceName);
} else {
Display(TEXT("Read IOCTL to %ws succeeded"), deviceInfo->DeviceName);
result = TRUE;
}
if(!DeviceIoControl (deviceInfo->hControlDevice,
IOCTL_NETVMINI_WRITE_DATA,
NULL, 0,
NULL, 0,
&bytes, NULL)) {
Display(TEXT("Write IOCTL to %ws failed"), deviceInfo->DeviceName);
} else {
Display(TEXT("Write IOCTL to %ws succeeded"), deviceInfo->DeviceName);
result = TRUE;
}
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -