www.pudn.com > VSer.rar > Test.C
#include#include #include "winioctl.h" #include #include "tchar.h" #include #include "objbase.h" #include "..\inc\wdmioctl.h" #include "conio.h" #include "test.h" /*++ 打印使用信息 --*/ void Usage() { printf("Usage: test [-e] [-r IP:Port] [-n N] serial device number\n"); printf(" -e: enumerate serial device\n"); printf(" -r: set remote IP address and Port\n"); printf(" -n: create virtual device DOS name, eg. COM5\n"); printf(" -d: delete virtual device DOS name\n"); } /*++ 格式化输入的参数 argc - 参数个数 argv - 参数字符串数组 lpCmd - 格式化后的命令结构 Return value: >=0: Success, 返回将要操作的目标设备序号 -1: Error, 输入参数格式错误 -2: Success, 没有返回特定的目标设备号 --*/ int Parse( int argc, char* argv[], PCMDS lpCmd ) { int n; int nCmd; int Ret; nCmd = 0; Ret = -2; lpCmd->TargetDevice = -1; for ( n = 1; n < argc; n++) { if ( argv[ n ][ 0 ] == '-' ) { switch ( argv[ n ][ 1 ] ) { case 'e': lpCmd->bIsEnum = TRUE; break; case 'd': lpCmd->bDeleteDosName = TRUE; break; case 'r': n++; if ( n >= argc ) return -1; if ( -1 == ParseAddress ( argv[ n ], &lpCmd->IPAddress, &lpCmd->Port ) ) { printf("IPAddress and Port error\n"); return -1; } lpCmd->bSetRmt = TRUE; break; case 'n': n++; if ( n >= argc ) return -1; { int ComX; ComX = atoi ( argv[ n ] ); if ( ComX > 255 ) { printf("-n: create DOS name: Com%d\n", ComX ); printf(" ~~--> error!\n"); return -1; } lpCmd->ComX = ComX; lpCmd->bCreateDosName = TRUE; } break; default: return -1; } }else { if ( Ret == -2 ) { Ret = atoi( argv[ n ] ); if ( Ret < 0 ) return -1; else lpCmd->TargetDevice = Ret; }else return -1; } } return Ret; } /*++ 格式化IP地址和端口参数字符串 szAddress - 输入的IP地址和端口参数字符串,形如:192.168.0.3:1025 IPAddress - 输出的IP地址,符合网络字节序,即 0x0301a8c0 Port - 输出的端口,符合网络字节序,即 0x0104 --*/ int ParseAddress( const char* szAddress, PULONG IPAddress, PUSHORT Port) { int Ret; char* pdest; char buf[ 16 ]; int length; PUCHAR pa; UCHAR temp; int i, n, lastdot; Ret = -1; memset ( buf, 0, 16 ); pdest = strchr ( szAddress, ':' ); if ( pdest == NULL ) return Ret; if ( pdest != strrchr ( szAddress, ':' ) ) return Ret; strcpy ( buf, (const char* )( pdest + 1 ) ); *Port = (USHORT)atoi( (const char*)buf ); // change *Port from Intel order to Network Order pa = (PUCHAR)Port; temp = pa[ 0 ]; pa[ 0 ] = pa[ 1 ]; pa[ 1 ] = temp; if( ( pdest - szAddress ) > 15 ) return Ret; memset ( buf, 0, 16 ); strncpy ( buf, szAddress, ( pdest - szAddress ) ); length = strlen ( buf ); n = 0; lastdot = -1; if ( buf[ length - 1 ] == '.' ) return Ret; for ( i = 0; i < length; i++) { if ( buf[ i ] == '.' ) { if (( ( i - lastdot ) > 4 ) || ( ( i - lastdot ) < 2 ) ) return Ret; buf[ i ] = 0; lastdot = i; n++; } } if ( n != 3 ) return Ret; pdest = buf; pa = (PUCHAR)IPAddress; for ( i = 0; i < 4; i++ ) { length = strlen ( pdest ); if ( length > 3 ) return Ret; n = atoi ( pdest ); if ( n > 255 ) return Ret; pa[ i ] = (UCHAR)n; pdest += strlen ( pdest ) + 1; } return 0; } int main(int argc, char* argv[]) { CMDS cmd; int nDevice; if ( argc == 1 ) { Usage(); return 0; } memset ( (void*)&cmd, 0, sizeof ( CMDS ) ); nDevice = Parse( argc, argv, &cmd ); if ( nDevice == -1 ) { printf("Error parameters!\n\n"); Usage(); return 0; } if ( cmd.bIsEnum ) { printf("\n- Serial ports class\n--------------\n"); EnumDevice ( (LPGUID)&GUID_CLASS_COMPORT ); printf("\n\n"); } if ( cmd.bDeleteDosName && ( cmd.TargetDevice >= 0 ) ) { printf("- Delete DOS name\n-------------\n"); DeleteDosName ( (GUID*)&GUID_CLASS_COMPORT, (int)cmd.TargetDevice ); printf("\n\n"); } if( ( cmd.bCreateDosName ) && ( cmd.TargetDevice >= 0 ) ) { printf("- Create DOS name\n-------------\n"); CreateDosName( (GUID*)&GUID_CLASS_COMPORT, (int)cmd.TargetDevice, (ULONG)cmd.ComX ); printf("\n\n"); } if( ( cmd.bSetRmt ) && ( cmd.TargetDevice >= 0 ) ) { printf("- Set remote IP info\n-------------\n"); printf("IPAddress = 0x%x, Port = 0x%x\n", cmd.IPAddress, cmd.Port ); SetRmt( (LPGUID) &GUID_CLASS_COMPORT, cmd.TargetDevice, cmd.IPAddress, cmd.Port ); printf("\n\n"); } return 0; } /*++ 向虚拟串口设备发送命令,要求创建指定的DOS name,即 ComX lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来。 ComX - 指定的DOS name的序列号,若要创建COM10,则ComX = 10 --*/ void CreateDosName( LPGUID lpGuid, int TargetDevice, ULONG ComX ) { HANDLE hfile; BOOL bRet; DWORD dwRet; hfile = OpenDevice( lpGuid, TargetDevice ); if ( hfile == INVALID_HANDLE_VALUE ) return; bRet = DeviceIoControl( hfile, IOCTL_CREATE_DOS_NAME, &ComX, sizeof ( ULONG ), NULL, 0, &dwRet, NULL ); if ( !bRet ) printf("IOCTL_CREATE_DOS_NAME Failed (0x%x)\n", GetLastError() ); else printf("IOCTL_CREATE_DOS_NAME OK\n"); CloseHandle ( hfile ); } /*++ 向虚拟串口设备发送命令,要求删除DOS name lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来。 --*/ void DeleteDosName ( LPGUID lpGuid, int TargetDevice ) { HANDLE hfile; BOOL bRet; DWORD dwRet; hfile = OpenDevice( lpGuid, TargetDevice ); if ( hfile == INVALID_HANDLE_VALUE ) return; bRet = DeviceIoControl( hfile, IOCTL_DELETE_DOS_NAME, NULL, 0, NULL, 0, &dwRet, NULL ); if ( !bRet ) printf("IOCTL_DELETE_DOS_NAME Failed (0x%x)\n", GetLastError() ); else printf("IOCTL_DELETE_DOS_NAME OK\n"); CloseHandle ( hfile ); } /*++ 向虚拟串口设备发送命令,指定远端目标机器的地址和端口,用于以后发送UDP数据。 lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来 IPAddress - 远端目标机器的IP地址 Port - 远端目标机器的端口 --*/ void SetRmt( LPGUID lpGuid, int TargetDevice, ULONG IPAddress, USHORT Port ) { HANDLE hfile; BOOL bRet; DWORD dwRet; ULONG buf[ 2 ]; hfile = OpenDevice( lpGuid, TargetDevice ); if ( hfile == INVALID_HANDLE_VALUE ) return; buf[ 0 ] = IPAddress; buf[ 1 ] = (ULONG)Port; bRet = DeviceIoControl( hfile, IOCTL_SET_REMOTE_INFO, buf, sizeof ( ULONG ) * 2, NULL, 0, &dwRet, NULL ); if ( !bRet ) printf("IOCTL_SET_REMOTE_INFO Failed (0x%x)\n", GetLastError() ); else printf("IOCTL_SET_REMOTE_INFO OK\n"); CloseHandle ( hfile ); } /*++ 打开TargetDevice指定的设备 lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来。 --*/ HANDLE OpenDevice( LPGUID lpGuid , int TargetDevice) { HANDLE hfile; TCHAR szDevName[ MAX_PATH ]; hfile = INVALID_HANDLE_VALUE; if ( TRUE != GetDeviceName( lpGuid, TargetDevice, szDevName ) ) { return hfile; } hfile = CreateFile( szDevName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, //FILE_FLAG_OVERLAPPED , NULL ); if (hfile == INVALID_HANDLE_VALUE) printf("Open serial device Failed (0x%x)\n", GetLastError()); else printf("Open serial device OK\n", hfile ); return hfile; } /*++ 枚举lpGuid指定的设备类下面所有当前存在的设备,并且打印出来 lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT --*/ BOOL EnumDevice( const LPGUID lpGUID ) { HDEVINFO info; SP_INTERFACE_DEVICE_DATA ifdata; DWORD needed; PSP_INTERFACE_DEVICE_DETAIL_DATA detail; BYTE buf[ 4096 ]; int i; info = SetupDiGetClassDevs( lpGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); if( info == INVALID_HANDLE_VALUE ){ printf("Enumeration device Failed (0x%x)\n", GetLastError() ); return 0; } detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA )buf; for( i = 0;; i++) { memset( &ifdata, 0, sizeof ( SP_INTERFACE_DEVICE_DATA ) ); memset ( detail, 0, 4096 ); ifdata.cbSize = sizeof(ifdata); if (!SetupDiEnumDeviceInterfaces(info, NULL, (LPGUID) &GUID_CLASS_COMPORT, i, &ifdata)) { SetupDiDestroyDeviceInfoList(info); return 1; } detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); needed = 4096; if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, detail, needed, NULL, NULL)) { printf("Error %d getting interface detail\n", GetLastError()); SetupDiDestroyDeviceInfoList(info); return FALSE; } printf("No. %d %s\n", i, detail->DevicePath ); } SetupDiDestroyDeviceInfoList( info ); return TRUE; } /*++ 得到指定设备的访问路径 lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来。 szDevName - 输出目标设备的访问路径,以后可以使用CreateFile来打开该设备 --*/ BOOL GetDeviceName( LPGUID lpGuid, int TargetDevice, TCHAR* szDevName ) { HDEVINFO info; SP_INTERFACE_DEVICE_DATA ifdata; DWORD needed; PSP_INTERFACE_DEVICE_DETAIL_DATA detail; info = SetupDiGetClassDevs( lpGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); if( info == INVALID_HANDLE_VALUE ){ printf("Enumeration device Failed (0x%x)\n", GetLastError() ); return FALSE; } ifdata.cbSize = sizeof(ifdata); if (!SetupDiEnumDeviceInterfaces(info, NULL, lpGuid, TargetDevice, &ifdata)) { printf("Enumerate interfaces Failed (0x%x)\n", GetLastError()); SetupDiDestroyDeviceInfoList(info); return FALSE; } 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()); SetupDiDestroyDeviceInfoList(info); exit(1); } detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, detail, needed, NULL, NULL)) { printf("Error %d getting interface detail\n", GetLastError()); free((PVOID) detail); SetupDiDestroyDeviceInfoList(info); return FALSE; } _tcscpy( szDevName, detail->DevicePath ); free( (PVOID)detail ); SetupDiDestroyDeviceInfoList( info ); return TRUE; }