⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test.c

📁 好东东
💻 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 + -