Test.C
上传用户:zanmei2
上传日期:2010-03-06
资源大小:775k
文件大小:11k
源码类别:

通讯编程文档

开发平台:

C/C++

  1. #include <windows.h>
  2. #include <initguid.h>
  3. #include "winioctl.h"
  4. #include <stdio.h>
  5. #include "tchar.h"
  6. #include <setupapi.h>
  7. #include "objbase.h"
  8. #include "..incwdmioctl.h"
  9. #include "conio.h"
  10. #include "test.h"
  11. /*++
  12. 打印使用信息
  13. --*/
  14. void Usage()
  15. {
  16. printf("Usage: test [-e] [-r IP:Port] [-n N] serial device numbern");
  17. printf(" -e:    enumerate serial devicen");
  18. printf(" -r:    set remote IP address and Portn");
  19. printf(" -n:    create virtual device DOS name, eg. COM5n");
  20. printf(" -d:    delete virtual device DOS namen");
  21. }
  22. /*++
  23. 格式化输入的参数
  24. argc - 参数个数
  25. argv - 参数字符串数组
  26. lpCmd - 格式化后的命令结构
  27. Return value:
  28. >=0: Success, 返回将要操作的目标设备序号
  29. -1:  Error, 输入参数格式错误
  30. -2:  Success, 没有返回特定的目标设备号
  31. --*/
  32. int Parse( int argc, char* argv[], PCMDS lpCmd )
  33. {
  34. int n;
  35. int nCmd;
  36. int Ret;
  37. nCmd = 0;
  38. Ret = -2;
  39. lpCmd->TargetDevice = -1;
  40. for ( n = 1; n < argc; n++)
  41. {
  42. if ( argv[ n ][ 0 ] == '-' )
  43. {
  44. switch ( argv[ n ][ 1 ] )
  45. {
  46. case 'e':
  47. lpCmd->bIsEnum = TRUE;
  48. break;
  49. case 'd':
  50. lpCmd->bDeleteDosName = TRUE;
  51. break;
  52. case 'r':
  53. n++;
  54. if ( n >= argc )
  55. return -1;
  56. if ( -1 == ParseAddress ( argv[ n ], &lpCmd->IPAddress, &lpCmd->Port ) )
  57. {
  58. printf("IPAddress and Port errorn");
  59. return -1;
  60. }
  61. lpCmd->bSetRmt = TRUE;
  62. break;
  63. case 'n':
  64. n++;
  65. if ( n >= argc )
  66. return -1;
  67. {
  68. int ComX;
  69. ComX = atoi ( argv[ n ] );
  70. if ( ComX > 255 ) 
  71. {
  72. printf("-n: create DOS name: Com%dn", ComX );
  73. printf("                        ~~--> error!n");
  74. return -1;
  75. }
  76. lpCmd->ComX = ComX;
  77. lpCmd->bCreateDosName = TRUE;
  78. }
  79. break;
  80. default:
  81. return -1;
  82. }
  83. }else
  84. {
  85. if ( Ret == -2 )
  86. {
  87. Ret = atoi( argv[ n ] );
  88. if ( Ret < 0 )
  89. return -1;
  90. else
  91. lpCmd->TargetDevice = Ret;
  92. }else
  93. return -1;
  94. }
  95. }
  96. return Ret;
  97. }
  98. /*++
  99. 格式化IP地址和端口参数字符串
  100. szAddress - 输入的IP地址和端口参数字符串,形如:192.168.0.3:1025
  101. IPAddress - 输出的IP地址,符合网络字节序,即 0x0301a8c0
  102. Port - 输出的端口,符合网络字节序,即 0x0104
  103. --*/
  104. int ParseAddress( const char* szAddress, PULONG IPAddress, PUSHORT Port)
  105. {
  106. int Ret;
  107. char* pdest;
  108. char  buf[ 16 ];
  109. int length;
  110. PUCHAR pa;
  111. UCHAR temp;
  112. int i, n, lastdot;
  113. Ret = -1;
  114. memset ( buf, 0, 16 );
  115. pdest = strchr ( szAddress, ':' );
  116. if ( pdest == NULL )
  117. return Ret;
  118. if ( pdest != strrchr ( szAddress, ':' ) )
  119. return Ret;
  120. strcpy ( buf, (const char* )( pdest + 1 ) );
  121. *Port = (USHORT)atoi( (const char*)buf );
  122. // change *Port from Intel order to Network Order
  123. pa = (PUCHAR)Port;
  124. temp = pa[ 0 ];
  125. pa[ 0 ] = pa[ 1 ];
  126. pa[ 1 ] = temp;
  127. if( ( pdest - szAddress ) > 15 )
  128. return Ret;
  129. memset ( buf, 0, 16 );
  130. strncpy ( buf, szAddress, ( pdest - szAddress ) );
  131. length = strlen ( buf );
  132. n = 0;
  133. lastdot = -1;
  134. if ( buf[ length - 1 ] == '.' )
  135. return Ret;
  136. for ( i = 0; i < length; i++)
  137. {
  138. if ( buf[ i ] == '.' )
  139. {
  140. if (( ( i - lastdot ) > 4 ) || ( ( i - lastdot ) < 2 ) )
  141. return Ret;
  142. buf[ i ] = 0;
  143. lastdot = i;
  144. n++;
  145. }
  146. }
  147. if ( n != 3 )
  148. return Ret;
  149. pdest = buf;
  150. pa = (PUCHAR)IPAddress;
  151. for ( i = 0; i < 4; i++ )
  152. {
  153. length = strlen ( pdest );
  154. if ( length > 3 )
  155. return Ret;
  156. n = atoi ( pdest );
  157. if ( n > 255 )
  158. return Ret;
  159. pa[ i ] = (UCHAR)n;
  160. pdest += strlen ( pdest ) + 1;
  161. }
  162. return 0;
  163. }
  164. int main(int argc, char* argv[])
  165. {
  166. CMDS cmd;
  167. int nDevice;
  168. if ( argc == 1 )
  169. {
  170. Usage();
  171. return 0;
  172. }
  173. memset ( (void*)&cmd, 0, sizeof ( CMDS ) );
  174. nDevice = Parse( argc, argv, &cmd );
  175. if ( nDevice == -1 )
  176. {
  177. printf("Error parameters!nn");
  178. Usage();
  179. return 0;
  180. }
  181. if ( cmd.bIsEnum )
  182. {
  183. printf("n- Serial ports classn--------------n");
  184. EnumDevice ( (LPGUID)&GUID_CLASS_COMPORT );
  185. printf("nn");
  186. }
  187. if ( cmd.bDeleteDosName && ( cmd.TargetDevice >= 0 ) )
  188. {
  189. printf("- Delete DOS namen-------------n");
  190. DeleteDosName ( (GUID*)&GUID_CLASS_COMPORT, (int)cmd.TargetDevice );
  191. printf("nn");
  192. }
  193. if( ( cmd.bCreateDosName ) && ( cmd.TargetDevice >= 0 ) )
  194. {
  195. printf("- Create DOS namen-------------n");
  196. CreateDosName( (GUID*)&GUID_CLASS_COMPORT, (int)cmd.TargetDevice, (ULONG)cmd.ComX );
  197. printf("nn");
  198. }
  199. if( ( cmd.bSetRmt ) && ( cmd.TargetDevice >= 0 ) )
  200. {
  201. printf("- Set remote IP infon-------------n");
  202. printf("IPAddress = 0x%x,  Port = 0x%xn", cmd.IPAddress, cmd.Port );
  203. SetRmt( (LPGUID) &GUID_CLASS_COMPORT, cmd.TargetDevice, cmd.IPAddress, cmd.Port );
  204. printf("nn");
  205. }
  206. return 0;
  207. }
  208. /*++
  209. 向虚拟串口设备发送命令,要求创建指定的DOS name,即 ComX
  210. lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT
  211. TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来。
  212. ComX - 指定的DOS name的序列号,若要创建COM10,则ComX = 10
  213. --*/
  214. void CreateDosName( LPGUID lpGuid, int TargetDevice, ULONG ComX )
  215. {
  216. HANDLE hfile;
  217. BOOL bRet;
  218. DWORD dwRet;
  219. hfile = OpenDevice( lpGuid, TargetDevice );
  220. if ( hfile == INVALID_HANDLE_VALUE )
  221. return;
  222. bRet = DeviceIoControl( hfile, 
  223. IOCTL_CREATE_DOS_NAME,
  224. &ComX, sizeof ( ULONG ), NULL, 0, &dwRet, NULL );
  225. if ( !bRet )
  226. printf("IOCTL_CREATE_DOS_NAME          Failed (0x%x)n", GetLastError() );
  227. else
  228. printf("IOCTL_CREATE_DOS_NAME          OKn");
  229. CloseHandle ( hfile );
  230. }
  231. /*++
  232. 向虚拟串口设备发送命令,要求删除DOS name
  233. lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT
  234. TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来。
  235. --*/
  236. void DeleteDosName ( LPGUID lpGuid, int TargetDevice )
  237. {
  238. HANDLE hfile;
  239. BOOL bRet;
  240. DWORD dwRet;
  241. hfile = OpenDevice( lpGuid, TargetDevice );
  242. if ( hfile == INVALID_HANDLE_VALUE )
  243. return;
  244. bRet = DeviceIoControl( hfile, 
  245. IOCTL_DELETE_DOS_NAME,
  246. NULL, 0, NULL, 0, &dwRet, NULL );
  247. if ( !bRet )
  248. printf("IOCTL_DELETE_DOS_NAME          Failed (0x%x)n", GetLastError() );
  249. else
  250. printf("IOCTL_DELETE_DOS_NAME          OKn");
  251. CloseHandle ( hfile );
  252. }
  253. /*++
  254. 向虚拟串口设备发送命令,指定远端目标机器的地址和端口,用于以后发送UDP数据。
  255. lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT
  256. TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来
  257. IPAddress - 远端目标机器的IP地址
  258. Port - 远端目标机器的端口
  259. --*/
  260. void SetRmt( LPGUID lpGuid, int TargetDevice,  ULONG IPAddress, USHORT Port )
  261. {
  262. HANDLE hfile;
  263. BOOL bRet;
  264. DWORD dwRet;
  265. ULONG buf[ 2 ];
  266. hfile = OpenDevice( lpGuid, TargetDevice );
  267. if ( hfile == INVALID_HANDLE_VALUE )
  268. return;
  269. buf[ 0 ] = IPAddress;
  270. buf[ 1 ] = (ULONG)Port;
  271. bRet = DeviceIoControl( hfile, 
  272. IOCTL_SET_REMOTE_INFO,
  273. buf, sizeof ( ULONG ) * 2, NULL, 0, &dwRet, NULL );
  274. if ( !bRet )
  275. printf("IOCTL_SET_REMOTE_INFO           Failed (0x%x)n", GetLastError() );
  276. else
  277. printf("IOCTL_SET_REMOTE_INFO           OKn");
  278. CloseHandle ( hfile );
  279. }
  280. /*++
  281. 打开TargetDevice指定的设备
  282. lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT
  283. TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来。
  284. --*/
  285. HANDLE OpenDevice( LPGUID lpGuid , int TargetDevice)
  286. {
  287. HANDLE hfile;
  288. TCHAR szDevName[ MAX_PATH ];
  289. hfile = INVALID_HANDLE_VALUE;
  290. if ( TRUE != GetDeviceName( lpGuid, TargetDevice, szDevName ) )
  291. {
  292. return hfile;
  293. }
  294. hfile = CreateFile(
  295. szDevName,
  296. GENERIC_READ | GENERIC_WRITE,
  297. 0,
  298. NULL,
  299. OPEN_EXISTING,
  300. FILE_ATTRIBUTE_NORMAL, //FILE_FLAG_OVERLAPPED ,
  301. NULL
  302. );
  303.     if (hfile == INVALID_HANDLE_VALUE)
  304.         printf("Open serial device             Failed (0x%x)n", GetLastError());
  305. else
  306. printf("Open serial device             OKn", hfile );
  307. return hfile;
  308. }
  309. /*++
  310. 枚举lpGuid指定的设备类下面所有当前存在的设备,并且打印出来
  311. lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT
  312. --*/
  313. BOOL EnumDevice( const LPGUID lpGUID )
  314. {
  315. HDEVINFO info;
  316. SP_INTERFACE_DEVICE_DATA ifdata;
  317. DWORD needed;
  318.     PSP_INTERFACE_DEVICE_DETAIL_DATA detail;
  319. BYTE buf[ 4096 ];
  320. int i;
  321. info = SetupDiGetClassDevs( lpGUID,
  322. NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
  323. if( info == INVALID_HANDLE_VALUE ){
  324. printf("Enumeration device               Failed (0x%x)n", GetLastError() );
  325. return 0;
  326. }
  327. detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA )buf;
  328. for( i = 0;; i++)
  329. {
  330. memset( &ifdata, 0, sizeof ( SP_INTERFACE_DEVICE_DATA ) );
  331. memset ( detail, 0, 4096 );
  332. ifdata.cbSize = sizeof(ifdata);
  333. if (!SetupDiEnumDeviceInterfaces(info, NULL, (LPGUID) &GUID_CLASS_COMPORT,
  334. i, &ifdata))
  335. {
  336. SetupDiDestroyDeviceInfoList(info);
  337. return 1;
  338. }
  339. detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
  340. needed = 4096;
  341. if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, detail, needed, NULL, NULL))
  342. {
  343. printf("Error %d getting interface detailn", GetLastError());
  344. SetupDiDestroyDeviceInfoList(info);
  345. return FALSE;
  346. }
  347. printf("No. %d  %sn", i, detail->DevicePath );
  348. }
  349.     SetupDiDestroyDeviceInfoList( info );
  350. return TRUE;
  351. }
  352. /*++
  353. 得到指定设备的访问路径
  354. lpGuid - 设备类GUID, 此处传入 GUID_CLASS_COMPORT
  355. TargetDevice- 目标设备的序号,此序号由 EnumDevice函数枚举设备类得来。
  356. szDevName - 输出目标设备的访问路径,以后可以使用CreateFile来打开该设备
  357. --*/
  358. BOOL GetDeviceName( LPGUID lpGuid, int TargetDevice, TCHAR* szDevName )
  359. {
  360. HDEVINFO info;
  361. SP_INTERFACE_DEVICE_DATA ifdata;
  362. DWORD needed;
  363.     PSP_INTERFACE_DEVICE_DETAIL_DATA detail;
  364. info = SetupDiGetClassDevs( lpGuid,
  365. NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
  366. if( info == INVALID_HANDLE_VALUE ){
  367. printf("Enumeration device                Failed (0x%x)n", GetLastError() );
  368. return FALSE;
  369. }
  370.     ifdata.cbSize = sizeof(ifdata);
  371.     
  372. if (!SetupDiEnumDeviceInterfaces(info, NULL, lpGuid,
  373.                                      TargetDevice, &ifdata))
  374.     {
  375.         printf("Enumerate interfaces             Failed (0x%x)n", GetLastError());
  376.         SetupDiDestroyDeviceInfoList(info);
  377.         return FALSE;
  378.      }
  379.     SetupDiGetDeviceInterfaceDetail(info, &ifdata, NULL, 0, &needed, NULL);
  380.     detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(needed);
  381. if (!detail)
  382.     {
  383.         printf("Error %d trying to get memory for interface detailn", GetLastError());
  384.         SetupDiDestroyDeviceInfoList(info);
  385.         exit(1);
  386.     }
  387.     detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
  388.     if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, detail, needed, NULL, NULL))
  389.     {
  390.         printf("Error %d getting interface detailn", GetLastError());
  391.         free((PVOID) detail);
  392.         SetupDiDestroyDeviceInfoList(info);
  393. return FALSE;
  394.     }
  395.     _tcscpy( szDevName, detail->DevicePath );
  396.     free( (PVOID)detail );
  397.     SetupDiDestroyDeviceInfoList( info );
  398. return TRUE;
  399. }