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函数将永远阻塞。