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; 
}