📄 test.c
字号:
#include <windows.h>
#include <initguid.h>
#include "winioctl.h"
#include <stdio.h>
#include "tchar.h"
#include <setupapi.h>
#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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -