demo下载: prjIpV4Convert_2013_0406_1749.iso
需求:
* 用户输入IP串, 转换成DWORD值. e.g. 1.1.1.1 => 0x01010101
* 计算过程在驱动中完成, 应用层只负责用户输入处理, 显示, 调用DLL.
概要设计:
* 为了维护方便, 采用 app => dll => nt driver
* 加入用户输入数据的校验
* 应用层加入输入提示, 可以运行多次, 由用户决定退出时机.
* 环境: vs2008sp1 + wdk7600 + win7x64sp1 + vmware9.0(win7x86家庭普通版)
驱动部分的实现:
NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { PVOID pInputBuffer = NULL; ULONG ulinputSize = 0; PVOID pOutputBuffer = NULL; ULONG * pulOutputSize = NULL; ULONG ulCtrlCode = 0; ULONG ulIp = 0; NTSTATUS sRc = STATUS_SUCCESS; PIO_STACK_LOCATION pIostack; DbgPrint(">> DispatchIoctrl\r\n"); pIostack = IoGetCurrentIrpStackLocation(pIrp); ulCtrlCode = pIostack->Parameters.DeviceIoControl.IoControlCode; pInputBuffer = pIrp->AssociatedIrp.SystemBuffer; ulinputSize = pIostack->Parameters.DeviceIoControl.InputBufferLength; pOutputBuffer = pIrp->AssociatedIrp.SystemBuffer; pulOutputSize = &pIostack->Parameters.DeviceIoControl.OutputBufferLength; switch(ulCtrlCode) { case IO_CTRL_CODE_IP_CONVERT: DbgPrint("IO_CTRL_CODE_IP_CONVERT\r\n"); sRc = fnIpConvert(pInputBuffer, ulinputSize, &ulIp); pIrp->IoStatus.Status = sRc; pIrp->IoStatus.Information = (STATUS_SUCCESS == sRc) ? sizeof(ULONG) : 0; if (STATUS_SUCCESS == sRc) { if (*pulOutputSize >= sizeof(ULONG)) { RtlCopyMemory(pOutputBuffer, (PVOID)(&ulIp), sizeof(ULONG)); } else { pIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; pIrp->IoStatus.Information = 0; } } break; default: DbgPrint("Unknown ulCtrlCode\r\n"); pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; break; } IoCompleteRequest(pIrp, IO_NO_INCREMENT); DbgPrint("<< DispatchIoctrl\r\n"); return STATUS_SUCCESS; }
/// @file sysInc\IpConvertFunction.h /// @brief IP转换功能的实现 #ifndef __IP_CONVERT_FUNCTION_H__ #define __IP_CONVERT_FUNCTION_H__ #include <ntddk.h> #include "IpConvertConst.h" NTSTATUS fnIpConvert(PVOID pcIpContent, ULONG ulLenIpContent, ULONG * pulIp); BOOLEAN IsInCharset(wchar_t cLetter, wchar_t * pcCharset, ULONG ulLenCharset); BOOLEAN IsValidIpField(USHORT uIpField); #endif
/// @file sysInc\IpConvertFunction.c /// @brief IP转换功能的实现 #include "IpConvertFunction.h" NTSTATUS fnIpConvert(PVOID pcIpContent, ULONG ulLenIpContent, ULONG * pulIp) { /// ulLenIpContent 是字节长度 /// pcIpContent is xx.xx.xx.xx e.g. 192.l68.1.1 ULONG ulIp = 0; ULONG ulPos = 0; wchar_t cTmp = 0; USHORT uIpSection = 0; ///< 要装下 255~999之间的数 size_t nDotCnt = 0; wchar_t cDigit[] = {L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'.'}; if ( (NULL == pcIpContent) || (NULL == pulIp) || (ulLenIpContent <= 0)) { return STATUS_INVALID_PARAMETER; } for (ulPos = 0; ulPos < ulLenIpContent;) { cTmp = *((wchar_t *)((UCHAR *)pcIpContent + ulPos)); if (!IsInCharset(cTmp, cDigit, sizeof(cDigit) / sizeof(wchar_t))) { return STATUS_INVALID_PARAMETER; } if (L'.' == cTmp) { nDotCnt++; if (!IsValidIpField(uIpSection)) { return STATUS_INVALID_PARAMETER; } ulIp = (ulIp << 8) + uIpSection; uIpSection = 0; } else { uIpSection = uIpSection * 10 + cTmp - L'0'; } ulPos += sizeof(wchar_t); } if (3 != nDotCnt) { return STATUS_INVALID_PARAMETER; } if (!IsValidIpField(uIpSection)) { return STATUS_INVALID_PARAMETER; } ulIp = (ulIp << 8) + uIpSection; ///< 加上最后一个IP字段值 *pulIp = ulIp; return STATUS_SUCCESS; } BOOLEAN IsInCharset(wchar_t cLetter, wchar_t * pcCharset, ULONG ulLenCharset) { /// ulLenCharset 是字符数 ULONG ulPos = 0; wchar_t cTmp = 0; if (NULL == pcCharset) { return FALSE; } for (ulPos = 0; ulPos < ulLenCharset; ulPos++) { cTmp = *(pcCharset + ulPos); if (cTmp == cLetter) { return TRUE; } } return FALSE; } BOOLEAN IsValidIpField(USHORT uIpField) { return ((uIpField >= 0) && (uIpField <= 255)); }