zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
阅读:2116回复:18

TdiRecv (80分)

楼主#
更多 发布于:2005-06-07 14:51
98的TDI RECV
Status = pDt->TdiReceiveEntry(&((PTDICONTEXT98)pTdiContext)->ConnRequest, &Flags, &RecvLen, NB);
DebugString(\"Recv Status = %X\",Status);
if ( Status == TDI_PENDING ) {
Wait_Semaphore(CallBack.cbm_sem, BLOCK_SVC_INTS);
DebugString(\"recv wait complete %d\",CallBack.Length);
*ReturnLength=CallBack.Length;
Status=CallBack.cbm_status;
}
我把这个函数加了异常处理
和SEND是完全一样的 SEND能成功,这个RECV也能成功收到数据 就是会产生异常 到了CATCH里。这是为何?
---内核开发合作或提供基础技术服务QQ:22863668 ---
zzzcn
驱动牛犊
驱动牛犊
  • 注册日期2004-08-23
  • 最后登录2014-06-23
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望43点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-06-07 16:10
NB->VirtualAddress指向的页锁定了吗?
不锁定可能会出错。
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2005-06-07 16:14
NB->VirtualAddress指向的页锁定了吗?
不锁定可能会出错。

如何锁定,我是用下面的方法分配的
NdisAllocateBufferPool(&NStatus,&PoolHandle,iNumber);
NdisAllocateBuffer(&NStatus,&NB,PoolHandle,Data,DataLen);
但是SEND没问题呀?
---内核开发合作或提供基础技术服务QQ:22863668 ---
zzzcn
驱动牛犊
驱动牛犊
  • 注册日期2004-08-23
  • 最后登录2014-06-23
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望43点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
地板#
发布于:2005-06-07 16:18
给你个封装好的函数
unsigned int CSocket::Receive(unsigned char *buf, unsigned int len)
{
if(!m_pConnRequest)return 0;

unsigned char* pBuf;
DWORD pLinBuf, nPages, pLockedBuf;
unsigned int nBytesSent;
int res = 0;
TDI_STATUS err;
pLinBuf = (unsigned long)buf;
nPages = ((pLinBuf + len - 1) >> 12) - (pLinBuf >> 12) + 1;

if (nPages!=0)
{
pLockedBuf = _LinPageLock(pLinBuf >> 12, nPages, PAGEMAPGLOBAL);
if (pLockedBuf==0)
{
}
}

PNDIS_BUFFER pNB;
pNB = (PNDIS_BUFFER)_HeapAllocate(sizeof(NDIS_BUFFER), HEAPZEROINIT);
memcpy((PVOID)&pNB->Signature, \"NBUF\", 4);
pNB->VirtualAddress = (PVOID)(pLockedBuf + (pLinBuf & 0xfff));
pNB->Length = len;

m_pConnRequest->RequestNotifyObject = EventReceiveCallback;
m_pConnRequest->RequestContext = this;

err = TdiReceive(m_pConnRequest,0, &len,pNB);
if (err == TDI_PENDING)
{
//waiting ...
Wait_Semaphore(m_EventSem,BLOCK_SVC_INTS);

}

_LinPageUnLock(((DWORD) pLockedBuf) >> 12, nPages, PAGEMAPGLOBAL);
if (pNB) _HeapFree(pNB, 0);
return len;
}
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
地下室#
发布于:2005-06-07 18:18
我已经把代码全部改成差不多一样的了,但还是有个异常,而且第二次加载这个驱动的时候系统就死机了。
NTSTATUS TdiRecv(PTDICONTEXT pTdiContext,PVOID Data,ULONG DataLen,ULONG *ReturnLength)
{
CALLBACK CallBack;
USHORT Flags=TDI_RECEIVE_NORMAL;
PNDIS_BUFFER NB;
TDI_STATUS Status=STATUS_SUCCESS;
TDIDispatchTable *pDt;
NDIS_STATUS NStatus;
NDIS_HANDLE PoolHandle;
UINT iNumber=1;
UINT RecvLen=DataLen;

ULONG ulLinBuf, nPages,pLockBuf;

__try
{
pDt=GetTDIDispatchTable();
CallBack.cbm_sem=Create_Semaphore(0);
CallBack.Command=2;
if(CallBack.cbm_sem==NULL)
{
DebugString(\"CreateSemaphore error %X\",0);
}
((PTDICONTEXT98)pTdiContext)->ConnRequest.RequestNotifyObject = CompleteConnection;
((PTDICONTEXT98)pTdiContext)->ConnRequest.RequestContext      = &CallBack;

ulLinBuf = (unsigned long)Data;
nPages = ((ulLinBuf + DataLen - 1) >> 12) - (ulLinBuf >> 12) + 1;
if (nPages!=0)
{
pLockBuf = _LinPageLock(ulLinBuf >> 12, nPages, PAGEMAPGLOBAL);
if (pLockBuf==0)
{
DebugString(\"Lock Page error %d\",1);
return 0;
}
}
else
{
DebugString(\"Lock Page error %d\",0);
return 0;
}

/* NdisAllocateBufferPool(&NStatus,&PoolHandle,iNumber);
NdisAllocateBuffer(&NStatus,&NB,PoolHandle,(PVOID)((unsigned char *)pLockBuf + ((ULONG)Data & 0xfff)),DataLen);
if(NStatus!=STATUS_SUCCESS)
{
DebugString(\"Tdi Recv Allocate buffer error %X\",NStatus);
return 0;
}
*/
NB = (PNDIS_BUFFER)_HeapAllocate(sizeof(NDIS_BUFFER), HEAPZEROINIT);
memcpy((PVOID)&NB->Signature, \"NBUF\", 4);
NB->VirtualAddress = (PVOID)(pLockBuf + (ulLinBuf & 0xfff));
NB->Length = DataLen;

// NB->VirtualAddress = (PVOID)((unsigned char *)pLockBuf + ((ULONG)Data & 0xfff));

Status = pDt->TdiReceiveEntry(&((PTDICONTEXT98)pTdiContext)->ConnRequest, &Flags, &RecvLen, NB);
// DebugString(\"Recv Status = %X\",Status);
if ( Status == TDI_PENDING ) {
Wait_Semaphore(CallBack.cbm_sem, BLOCK_SVC_INTS);
// DebugString(\"recv wait complete %d\",CallBack.Length);
*ReturnLength=CallBack.Length;
Status=CallBack.cbm_status;
}
else
{
DebugString(\"Recv return direct %d\",RecvLen);
*ReturnLength=RecvLen;
}

if(!_LinPageUnLock(((DWORD) pLockBuf) >> 12, nPages, PAGEMAPGLOBAL))
{
DebugString(\"Unlock page error %d\",0);
}

Destroy_Semaphore(CallBack.cbm_sem);
//NdisFreeBuffer(NB);
//NdisFreeBufferPool(PoolHandle);
if (NB) _HeapFree(NB, 0);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DebugString(\"Exception recv: %X\",Status); //就出现在这里
}
return Status;
}
---内核开发合作或提供基础技术服务QQ:22863668 ---
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
5楼#
发布于:2005-06-07 21:11
会不会和其他环境有关系,这个是个客户端,服务器是个普通的应用程序。
---内核开发合作或提供基础技术服务QQ:22863668 ---
zzzcn
驱动牛犊
驱动牛犊
  • 注册日期2004-08-23
  • 最后登录2014-06-23
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望43点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2005-06-08 09:12
服务器程序是应用程序不影响。

检查一下你的回调函数,有没有问题。

实在不行就把代码一段一段的封起来再试了,呵呵。
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
7楼#
发布于:2005-06-08 10:03
这种问题我觉得比较怪异 完整历程已经过了,状态和长度都对,数据也对
就是TdiReceiveEntry调用完后就直接到异常里了,异常码是STATUS_ACCESS_VIOLATION
但是我要把Wait_Semaphore去了就没事
而且再次调用的时候就死机了。
---内核开发合作或提供基础技术服务QQ:22863668 ---
zzzcn
驱动牛犊
驱动牛犊
  • 注册日期2004-08-23
  • 最后登录2014-06-23
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望43点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2005-06-08 12:11
建议用全局的信号量,不要用局部变量。
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
9楼#
发布于:2005-06-08 13:44
非常感谢你的帮助 能不能加我QQ聊聊?
---内核开发合作或提供基础技术服务QQ:22863668 ---
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
10楼#
发布于:2005-06-08 14:32
在receive的时候调用Wait_Semaphore应该不可以,没有分析过98,可以类比2k的代码,你的receive是一个回调函数,是在dpc里面被调用,这个时候调用KeWaitForSingleObject去切换线程肯定是不可以的。
98虽然不同,但os原理是一样的,不要去调用Wait_Semophore,最好安装回调函数,在回调函数里处理。看看98上tdi有没有这种机制
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
11楼#
发布于:2005-06-08 14:40
在receive的时候调用Wait_Semaphore应该不可以,没有分析过98,可以类比2k的代码,你的receive是一个回调函数,是在dpc里面被调用,这个时候调用KeWaitForSingleObject去切换线程肯定是不可以的。
98虽然不同,但os原理是一样的,不要去调用Wait_Semophore,最好安装回调函数,在回调函数里处理。看看98上tdi有没有这种机制

回调是安了的,在回调里释放的。98里必须安装回调函数,我在SEND CONN里都是这么用的都没有问题就是RECEIVE里就不行。
而且我看网上几乎所有的RECV实现都是这么做的。
---内核开发合作或提供基础技术服务QQ:22863668 ---
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
12楼#
发布于:2005-06-08 15:21
[quote]在receive的时候调用Wait_Semaphore应该不可以,没有分析过98,可以类比2k的代码,你的receive是一个回调函数,是在dpc里面被调用,这个时候调用KeWaitForSingleObject去切换线程肯定是不可以的。
98虽然不同,但os原理是一样的,不要去调用Wait_Semophore,最好安装回调函数,在回调函数里处理。看看98上tdi有没有这种机制

回调是安了的,在回调里释放的。98里必须安装回调函数,我在SEND CONN里都是这么用的都没有问题就是RECEIVE里就不行。
而且我看网上几乎所有的RECV实现都是这么做的。 [/quote]
1。网上Recv里面调了Wait_Semaphore吗?
2。还是类比2k,Send是在passiv level,recevice是在dpc,所以send
可以,但receive就会有问题
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
13楼#
发布于:2005-06-08 15:49
[quote][quote]在receive的时候调用Wait_Semaphore应该不可以,没有分析过98,可以类比2k的代码,你的receive是一个回调函数,是在dpc里面被调用,这个时候调用KeWaitForSingleObject去切换线程肯定是不可以的。
98虽然不同,但os原理是一样的,不要去调用Wait_Semophore,最好安装回调函数,在回调函数里处理。看看98上tdi有没有这种机制

回调是安了的,在回调里释放的。98里必须安装回调函数,我在SEND CONN里都是这么用的都没有问题就是RECEIVE里就不行。
而且我看网上几乎所有的RECV实现都是这么做的。 [/quote]
1。网上Recv里面调了Wait_Semaphore吗?
2。还是类比2k,Send是在passiv level,recevice是在dpc,所以send
可以,但receive就会有问题 [/quote]
网上例子比较少,但偶尔发现的代码里都是这样。
我跟踪发现并不是这出错因为调用完RECEIVE后进行完成历程完了就直接到了异常里去了,后面那句调试输出都没有出来。
这几天发现的问题太奇怪了,这个东东我都搞了一个星期了
---内核开发合作或提供基础技术服务QQ:22863668 ---
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
14楼#
发布于:2005-06-08 16:08
不要用Wait_semaphore,如果还有问题,再分析
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
15楼#
发布于:2005-06-08 16:19
不要用Wait_semaphore,如果还有问题,再分析

我已经换成WaitForSingleObject了,但是错误还是一样的。
Status = pDt->TdiReceiveEntry(&((PTDICONTEXT98)pTdiContext)->ConnRequest, &Flags, &RecvLen, NB);
DebugString(\"Recv Status = %X\",Status);
if ( Status == TDI_PENDING ) {
WaitEvent(CallBack.m_Event);

WaitEvent是封装了的。
---内核开发合作或提供基础技术服务QQ:22863668 ---
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
16楼#
发布于:2005-06-08 16:34
[quote]不要用Wait_semaphore,如果还有问题,再分析

我已经换成WaitForSingleObject了,但是错误还是一样的。
Status = pDt->TdiReceiveEntry(&((PTDICONTEXT98)pTdiContext)->ConnRequest, &Flags, &RecvLen, NB);
DebugString(\"Recv Status = %X\",Status);
if ( Status == TDI_PENDING ) {
WaitEvent(CallBack.m_Event);

WaitEvent是封装了的。
 [/quote]
WaitForSingleOjbect和Wait_Semaphore是一样的,都不要用,总之在这里不能等待,
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
17楼#
发布于:2005-06-08 16:58
如果不等的话,问题是我怎么知道什么时候返回了
---内核开发合作或提供基础技术服务QQ:22863668 ---
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
18楼#
发布于:2005-06-08 17:58
晕死,活人让尿憋死了,怎样都是对的只是回调函数必须是__cdecl类型,希望大家不要犯类似的错误。
非常感谢两位的热切帮助,分已给出.........

---内核开发合作或提供基础技术服务QQ:22863668 ---
游客

返回顶部