12.5.2 Packet.dll库中相应函数的实现
1.PacketSetDumpName函数
该函数用于告诉内核驱动程序NPF内核转储文件的名称,其原型如下:
BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject,void*name,int len)
上述函数中,参数AdapterObject指向一个_ADAPTER结构体,描述当前的适配器;参数name是文件名称;参数len为包含文件名的缓冲区大小。
如果PacketSetDumpName函数执行成功则返回非0值;否则返回0值。
该函数的主要实现代码如下:
BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject,void*name,int len)
{
DWORD BytesReturned;
WCHAR*FileName;
BOOLEAN res;
WCHAR NameWithPath[1024];
int TStrLen;
WCHAR*NamePos;
if(AdapterObject->Flags!=INFO_FLAG_NDIS_ADAPTER)
{
//不支持的适配器类型
return FALSE;
}
/判断文件名的字符集是ASCII还是Unicode,如果是ASCII的则转换为Unicode/
if(((PUCHAR)name)[1]!=0&&len>1){//ASCII
FileName=SChar2WChar(name);
len*=2;
}
else{//Unicode
FileName=name;
}
/获得文件的全文件名/
TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos);
len=TStrLen*2+2;//添加结束符,Unicode为2字节
/检查文件名的异常/
if(len>2048){
if(((PUCHAR)name)[1]!=0&&len>1)
GlobalFreePtr(FileName);
return FALSE;
}
/设置文件名/
res=(BOOLEAN)DeviceIoControl(
AdapterObject->hFile,
BIOCSETDUMPFILENAME,
NameWithPath,
len,
NULL,
0,
&BytesReturned,
NULL);
if(((PUCHAR)name)[1]!=0&&len>1)
GlobalFreePtr(FileName);
return res;
}
2.PacketSetDumpLimits函数
PacketSetDumpLimits函数用于设置内核转储的限制值,包括文件所能存储的最大字节数与最大数据包数,其原型如下:
BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject,
UINT maxflesize,UINT maxnpacks)
上述函数中,参数AdapterObject指向一个_ADAPTER结构体,描述当前的适配器;参数maxfilesize是文件的最大字节数,0表示无限制;参数maxnpacks为能够转储的最大数据包数,0表示无限制。
如果PacketSetDumpLimits函数执行成功则返回非0值;否则返回0值。
该函数的主要实现代码如下:
BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject,
UINT maxflesize,UINT maxnpacks)
{
DWORD BytesReturned;
UINT valbuff[2];
BOOLEAN Result;
if(AdapterObject->Flags!=INFO_FLAG_NDIS_ADAPTER)
{
//不支持的适配器类型
return FALSE;
}
valbuff[0]=maxflesize;
valbuff[1]=maxnpacks;
/设置限制/
Result=(BOOLEAN)DeviceIoControl(AdapterObject->hFile,
BIOCSETDUMPLIMITS,
valbuff,
sizeof valbuff,
NULL,
0,
&BytesReturned,
NULL);
return Result;
}
上述代码中所提及的两个限制,任何一个达到后,转储即停止。
3.PacketIsDumpEnded函数
PacketIsDumpEnded函数用于返回内核转储过程的状态,比如通知通过PacketSetDumpLimits函数设置的一个限制是否已经达到,其原型如下:
BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject,BOOLEAN sync)
上述函数中,参数AdapterObject指向一个_ADAPTER结构体,描述当前的适配器;如果参数sync为TRUE,函数阻塞直到转储结束,否则立即返回。
如果转储结束,PacketIsDumpEnded函数执行成功则返回TRUE;否则返回FALSE。
该函数主要的实现代码如下:
BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject,BOOLEAN sync)
{
DWORD BytesReturned;
int IsDumpEnded;
BOOLEAN res;
if(AdapterObject->Flags!=INFO_FLAG_NDIS_ADAPTER)
{
//不支持的适配器类型
return FALSE;
}
if(sync)
{//等待内核驱动NPF设置ReadEvent事件
WaitForSingleObject(AdapterObject->ReadEvent,
INFINITE);
}
/查看状态/
res=(BOOLEAN)DeviceIoControl(AdapterObject->hFile,
0,
&IsDumpEnded,
4,
&BytesReturned,
NULL);
/如果IOCTL返回一个错误,则认为转储结束/
if(res==FALSE)
return TRUE;
return(BOOLEAN)IsDumpEnded;
}
正常的使用情况是在调用PacketSetDumpLimits函数后,再调用PacketIsDumpEnded函数。如果没有调用PacketSetDumpLimits函数,或者转储过程没有设置限制(比如PacketSetDumpLimits函数的maxfilesize或maxn packs参数为0)并把PacketIsDumpEnded函数的参数sync设为TRUE,那么PacketIsDumpEnded函数将永远阻塞。