www.pudn.com > 2004-01-16_SimSerial.rar > Test.cpp
// Test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include#include //#include #include #include #include "objbase.h" #include #include "..\inc\wdmioctl.h" DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73); typedef struct _Dev_Desc{ BOOL bIsUsed; int ComX; int Instance; char InterfaceName[ MAX_PATH ]; }DEV_DESC, *LPDEV_DESC; #define MAX_NUM 256 DEV_DESC gDevDesc[ MAX_NUM ] = { 0 }; //void ConnectPorts(); void Useage(); int ScanDevice(); BOOL IsVSD( char* lpDevicePath ); void AddDevDesc( char* lpDevicePath ); void SetComX(); void ConnectPorts(); void Disconnect(); int gTotalNum = 0; int main(int argc, char* argv[]) { Useage(); if( 0 == ScanDevice() ){ printf("don't find out virtual serial device\n"); return 0; } SetComX(); ConnectPorts(); //Disconnect(); return 0; } void Useage() { printf("------ Virtual serial device controller ------\n"); } int ScanDevice() { int n, nVSD; DWORD needed; HDEVINFO info; SP_INTERFACE_DEVICE_DATA ifdata; PSP_INTERFACE_DEVICE_DETAIL_DATA detail = NULL; n = 0; nVSD = 0; // 首先得到该ClassGUID值下的设备信息句柄 info. 本程序中ClassGUID代表串口设备类 // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{86e0d1e0-8089-11d0-9ce4-08003e301f73} info = SetupDiGetClassDevs( (LPGUID) &GUID_CLASS_COMPORT,//(LPGUID)&GUID_WDMSAMPLE_DEVICE_INTERFACE_CLASS, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); if( info == INVALID_HANDLE_VALUE ){ printf("Error %d trying to open enumeration handle for \n", GetLastError() ); return 0; } ifdata.cbSize = sizeof(ifdata); // 使用该 info 依次枚举当前该ClassGUID下的所有设备接口,将该接口信息放在ifdata while( SetupDiEnumDeviceInterfaces(info, NULL, (LPGUID)&GUID_CLASS_COMPORT,//(LPGUID) &GUID_WDMSAMPLE_DEVICE_INTERFACE_CLASS, n, &ifdata)) { // 第一次调用 SetupDiGetDeviceInterfaceDetail,得到ifdata所需空间大小 SetupDiGetDeviceInterfaceDetail(info, &ifdata, NULL, 0, &needed, NULL); detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(needed); if (!detail) { printf("Error %d trying to get memory for interface detail\n", GetLastError()); goto FAILED; } // 第二次调用 SetupDiGetDeviceInterfaceDetail,得到ifdata指代的设备的详细信息 detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, detail, needed, NULL, NULL)) { printf("Error %d getting interface detail\n", GetLastError()); goto FAILED; } printf("%d. %s", n, detail->DevicePath ); // 判断是否我们的虚拟串口设备 if( IsVSD( detail->DevicePath ) ){ printf(" Virtual serial\n"); nVSD++; AddDevDesc( detail->DevicePath ); }else{ printf(" Real serial\n"); } free( detail ); detail = NULL; n++; } FAILED: if( detail != NULL ){ free( detail ); } SetupDiDestroyDeviceInfoList( info ); return nVSD; } BOOL IsVSD( char* lpDevicePath ) { HANDLE hfile; DWORD dwIdentifier = 0; BOOL bIsVSD = FALSE; DWORD junk; hfile = CreateFile( lpDevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hfile == INVALID_HANDLE_VALUE) { printf("Error %d trying to open %s\n", GetLastError(), lpDevicePath); return bIsVSD; } if( DeviceIoControl( hfile, IOCTL_GET_IDENTITIER, NULL, 0, &dwIdentifier, sizeof( DWORD ), &junk, NULL ) ){ if( dwIdentifier == VIRTUAL_SERIAL_DEVICE_ID ){ bIsVSD = TRUE; } } CloseHandle( hfile ); return bIsVSD; } void AddDevDesc( char* lpDevicePath ) { HANDLE hfile; int instance; DWORD junk; hfile = CreateFile( lpDevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hfile == INVALID_HANDLE_VALUE) { printf("Error %d trying to open %s\n", GetLastError(), lpDevicePath); return; } instance = 0; if( DeviceIoControl( hfile, IOCTL_GET_CURRENT_INSTANCE, NULL, 0, &instance, sizeof( DWORD ), &junk, NULL ) ){ gDevDesc[ instance ].Instance = instance; strcpy( gDevDesc[ instance ].InterfaceName, lpDevicePath ); gDevDesc[ instance ].bIsUsed = TRUE; } CloseHandle( hfile ); } void SetComX() { int i; HANDLE hfile; int ComX; DWORD junk; ComX = 15; printf("\n------ Set COMn( 1~255 ) ------\n"); for( i = 0; i < MAX_NUM; i++) { if( gDevDesc[ i ].bIsUsed ){ printf("\\Device\\SiSerial%d ---> ", gDevDesc[ i ].Instance ); hfile = CreateFile( gDevDesc[ i ].InterfaceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hfile == INVALID_HANDLE_VALUE) { printf("Error %d trying to open %s\n", GetLastError(), gDevDesc[ i ].InterfaceName); return; } ComX = -1; if( DeviceIoControl( hfile, IOCTL_GET_CURRENT_COMX, NULL, 0, &ComX, sizeof( DWORD ), &junk, NULL ) ){ printf("COM%d\n", ComX ); }else{ ComX = 20 + i; if( DeviceIoControl( hfile, IOCTL_CREATE_DOS_NAME, &ComX, sizeof( DWORD ), NULL, 0, &junk, NULL ) ){ printf("COM%d\n", ComX ); }else printf(" Failed\n"); } CloseHandle( hfile ); } } } void ConnectPorts() { int i; HANDLE hfile, hRemotefile; int ComX; DWORD junk; DWORD remoteInstance, remoteComX; printf("\n------ Connect COM ports ------\n"); for( i = 0; i < MAX_NUM; i++) { if( gDevDesc[ i ].bIsUsed ){ printf("\\Device\\SiSerial%d <---> ", gDevDesc[ i ].Instance ); hfile = CreateFile( gDevDesc[ i ].InterfaceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hfile == INVALID_HANDLE_VALUE) { printf("Error %d trying to open %s\n", GetLastError(), gDevDesc[ i ].InterfaceName); return; } if( !DeviceIoControl( hfile, IOCTL_GET_CURRENT_COMX, NULL, 0, &ComX, sizeof( DWORD ), &junk, NULL ) ){ printf("Don't create dos device name\n"); CloseHandle( hfile ); continue; } if( DeviceIoControl( hfile, IOCTL_GET_REMOTE_INSTANCE, NULL, 0, &remoteInstance, sizeof( DWORD ), &junk, NULL ) ){ printf("\\Device\\SiSerial%d ", remoteInstance ); printf("COM%d <---> ", ComX ); hRemotefile = CreateFile( gDevDesc[ remoteInstance ].InterfaceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if( hRemotefile == INVALID_HANDLE_VALUE ) { printf("????\n"); CloseHandle( hfile ); continue; } if( DeviceIoControl( hRemotefile, IOCTL_GET_CURRENT_COMX, NULL, 0, &remoteComX, sizeof( DWORD ), &junk, NULL ) ){ printf(" COM%d\n", remoteComX ); }else{ printf(" COM?\n" ); } CloseHandle( hRemotefile ); }else{ remoteInstance = i + 1; if( DeviceIoControl( hfile, IOCTL_SET_REMOTE_INSTANCE, &remoteInstance, sizeof( ULONG ), NULL, 0, &junk, NULL ) ){ printf("\\Device\\SiSerial%d ", remoteInstance ); printf("COM%d <---> ", ComX ); hRemotefile = CreateFile( gDevDesc[ remoteInstance ].InterfaceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if( hRemotefile == INVALID_HANDLE_VALUE ) { printf("????\n"); CloseHandle( hfile ); continue; } if( DeviceIoControl( hRemotefile, IOCTL_GET_CURRENT_COMX, NULL, 0, &remoteComX, sizeof( DWORD ), &junk, NULL ) ){ printf(" COM%d\n", remoteComX ); }else{ printf(" COM?\n" ); } CloseHandle( hRemotefile ); }else{ printf("Set remote ports failed\n"); CloseHandle( hfile ); continue; } } CloseHandle( hfile ); } } } void Disconnect() { int i; DWORD junk; HANDLE hfile; ULONG remoteInstance; for( i = 0; i < MAX_NUM; i++) { if( gDevDesc[ i ].bIsUsed ){ printf("\\Device\\SiSerial%d <---> ", gDevDesc[ i ].Instance ); hfile = CreateFile( gDevDesc[ i ].InterfaceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hfile == INVALID_HANDLE_VALUE) { printf("Error %d trying to open %s\n", GetLastError(), gDevDesc[ i ].InterfaceName); return; } if( DeviceIoControl( hfile, IOCTL_GET_REMOTE_INSTANCE, NULL, 0, &remoteInstance, sizeof( DWORD ), &junk, NULL ) ){ printf("\\Device\\SiSerial%d Disconnect...", remoteInstance ); if( DeviceIoControl( hfile, IOCTL_DISCONNECT, NULL, 0, NULL, 0, &junk, NULL ) ){ printf(" OK\n"); }else{ printf(" Failed\n"); } }else{ printf("NULL\n"); } } } } #if 0 void HandleDevice( PSP_INTERFACE_DEVICE_DETAIL_DATA detail ) { char name[ MAX_PATH ]; DWORD junk; INT ComX; int i; int instance; // 打开设备,此处的设备名称为Kernel mode下IoRegisterDeviceInterface后OS自动生成名称。如下形式 // ##?#Toaster#MsToaster#1&1aafb3d5&2&01#{86e0d1e0-8089-11d0-9ce4-08003e301f73} strncpy(name, detail->DevicePath, sizeof(name)); for( i = 0; i < 2 ; i++) { if( !gDevDesc[ i ].bIsUsed ) break; } ComX = gDevDesc[ i ].ComX; if(!DeviceIoControl(hfile,IOCTL_INIT_SETTING, &ComX, sizeof( INT ), NULL , 0, &junk, NULL)) { printf("Direct IOCTL failed with code %d\n", GetLastError()); }else{ if( DeviceIoControl( hfile, IOCTL_GET_CURRENT_INSTANCE, NULL, 0, &instance, sizeof( ULONG ), &junk, NULL ) ){ gDevDesc[ i ].Instance = instance; strcpy( gDevDesc[ i ].InterfaceName, detail->DevicePath ); gDevDesc[ i ].bIsUsed = TRUE; } } if(!DeviceIoControl(hfile,IOCTL_FINISH_SETTING,NULL,0,NULL,0,&junk,NULL)) { printf("Direct IOCTL failed with code %d\n", GetLastError()); } CloseHandle( hfile ); return; } #endif