首页
社区
课程
招聘
[求助]驱动卸载前如何等待所有线程都关闭了再卸载
发表于: 2009-8-30 21:06 10520

[求助]驱动卸载前如何等待所有线程都关闭了再卸载

2009-8-30 21:06
10520
驱动 创建了一条线程   再全局变量做了个标记
线程一直运行 直到全局变量为FALSE 然后自杀
如果想卸载驱动  把这个标记变为FALSE 结果出现
driver_unloaded_without_cancelling_pending_operation

似乎是驱动在线程结束前就被卸载了。
用事件等待也不行。。设置事件总要在PsTerminateSystemThread函数之前
请问怎么解决啊?
等待所有线程结束了 再卸载驱动

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (17)
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
2
KeWaitForSingleObject,等待线程对象
2009-8-30 21:08
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
3
Klog里面不就有例子嘛
2009-8-30 21:11
0
雪    币: 71
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
我试了啊
再卸载函数前

KeInitializeEvent(&ThreadCloseOK,SynchronizationEvent,TRUE);
        Thread_RunSign =FALSE;
        KeWaitForSingleObject(&ThreadCloseOK,Executive,KernelMode,0,0);

线程最后
KeSetEvent(&ThreadCloseOK,0,TRUE);
PsTerminateSystemThread(STATUS_SUCCESS);

结果还是蓝啊。。
2009-8-30 21:11
0
雪    币: 251
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
Bug Check 0xCE: DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS
The DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS bug check has a value of 0x000000CE. This indicates that a driver failed to cancel pending operations before unloading.

Parameters
The following parameters are displayed on the blue screen.

Parameter Description
1 Memory address referenced
2 0: Read

1: Write


3 Address that referenced memory (if known)
4 Reserved


If the driver responsible for the error can be identified, its name is printed on the blue screen and stored in memory at the location (PUNICODE_STRING) KiBugCheckDriver.

Cause
This driver failed to cancel lookaside lists, DPCs, worker threads, or other such items before unload.

KeSetEvent(&ThreadCloseOK,0,TRUE);
PsTerminateSystemThread(STATUS_SUCCESS);

KeSetEvent(&ThreadCloseOK,0,TRUE)执行后就可能导致线程重新调度
从而再次调度worker thread时 PsTerminateSystemThread(STATUS_SUCCESS);地址已经被释放了
所以应该直接在线程上等待
总结起来,有两点
1.Windows 内核是抢占式的
2.线程也是可等待对象
2009-8-30 21:38
0
雪    币: 71
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
所以应该直接在线程上等待???怎么等待啊??
2009-8-30 21:43
0
雪    币: 71
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
KEVENT ThreadCloseOK;
BOOL        MyThread_RunSign        = FALSE;

VOID MyThread(IN PVOID context)
{
        while(MyThread_RunSign )
         {
                ;
          }
      
       KeSetEvent(&ThreadCloseOK,(KPRIORITY)0,TRUE);
       PsTerminateSystemThread(STATUS_SUCCESS);

}

VOID MyDriverUnload(IN PDRIVER_OBJECT DriverObject)
{
        PDEVICE_OBJECT pdoNextDeviceObj = pdoGlobalDrvObj->DeviceObject;
        //关闭 线程
        KeInitializeEvent(&ThreadCloseOK,SynchronizationEvent,TRUE);
        MyThread_RunSign =FALSE;
        KeWaitForSingleObject(&ThreadCloseOK,Executive,KernelMode,FALSE,0);

}

NTSTATUS DriverEntry(IN OUT PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)

HANDLE        ThreadHandle = 0;
        Thread_RunSign =TRUE;
        PsCreateSystemThread(&ThreadHandle,0L,NULL,NULL,NULL,MyThread,NULL);
        if (ThreadHandle)
        {
         ZwClose(ThreadHandle);
        }
        DriverObject->DriverUnload =MyDriverUnload;
return STATUS_SUCCESS;

大概的代码,逻辑是这样。。请问应该再怎么做?
2009-8-30 22:08
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
8
VOID
ThreadLogger (
    IN PVOID pContext
    )
/*++

Author: WangYu [keenjoy95@GMAIL.COM]
Time : 2008/12/20 [20:12:2008 - 10:16]

Routine Description:

记录日志的线程

--*/
{
    IO_STATUS_BLOCK io_status                        ;
    NTSTATUS        status        = STATUS_SUCCESS    ;
PLOG_DATA        kData        = NULL                ;
PLIST_ENTRY        pListEntry    = NULL                ;
PPROCESS_UNIT    pTemp        = NULL                ;
    PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION)pContext ;

    while( 1 )
    {
        // Wait for data to become available in the queue
        KeWaitForSingleObject(
            &pDeviceExtension->semQueue,
            Executive,
            KernelMode,
            FALSE,
            NULL);

        // 将得到的信息从队列中摘出来
        pListEntry = ExInterlockedRemoveHeadList(&pDeviceExtension->QueueListHead,
            &pDeviceExtension->lockQueue);

        if( TRUE == pDeviceExtension->bThreadTerminate ) {
            PsTerminateSystemThread( STATUS_SUCCESS ); // 这女人..
        }

        kData = CONTAINING_RECORD(pListEntry,LOG_DATA,ListEntry);

        // 不存在我的进程结构,继续等待
if( NULL == g_ProcessUnit ) { continue ; }

        pTemp = g_ProcessUnit ; // 临时指针来操作
        while( pTemp )
        {
            // 拥有日志句柄的进程(也就是样本进程) 产生了事件
            if( kData->PID == pTemp->UniqueProcessId && pTemp->LogFile )
            {
                // 日志之
                status = ZwWriteFile(
                    pTemp->LogFile,
                    NULL,
                    NULL,
                    NULL,
                    &io_status,
                    kData->Logs,
                    strlen(kData->Logs),
                    NULL,
                    NULL);

                if( !NT_SUCCESS(status) ) {
                    dprintf("ThreadLogger() --> ZwWriteFile. Failed [0x%08lx] \n", status) ;
                }

                WriteMumaFile( (ULONG)pTemp->Flags, (ULONG)pTemp->pEprocess, (PVOID)pDeviceExtension ) ;

                ExFreePool( kData ); // 释放内存,要不撑爆了
                break ;
            }

            pTemp = pTemp->Next;
        }

}

    return ;
}

2009-8-30 22:14
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
use Remove Locks
2009-8-30 22:35
0
雪    币: 71
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
use Remove Locks ?能具体点吗?
上面的代码 看着有点晕。。。似乎不完整。。
2009-8-30 22:39
0
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
11
晕,创建系统线程前 记录系统的KThread,在Unload的时候KeWaitForXXX
2009-8-30 22:41
0
雪    币: 71
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
大哥。。代码或例子有吗?
2009-8-30 22:43
0
雪    币: 71
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
哈哈...
最好事件初始化在主函数中,不要用全局变量,用放结构体里
参考我这个看看。http://bbs.pediy.com/showthread.php?t=88954
2009-8-30 22:44
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
14
直接wait线程对象

例如:

PVOID pThread = NULL ;
BOOL KillThread = FALSE ;
VOID SystemThread()
{
...
if (KillThread == TRUE)
PsTerminateSystemThread(0);
}
DrvUnload()
{
KillThread = TRUE ;
KeWaitForSingleObject(pThread...);
}
DriverEntry()
{
....
PsCreateSystemThread(..., &cid , SystemThread);
PsLookupThreadByThreadId(cid.tid , &pThread);
}
2009-8-30 22:51
0
雪    币: 71
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
cid  是什么结构?
2009-8-30 23:42
0
雪    币: 71
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
CLIENT_ID
成功解决啦~~哈哈哈 谢谢

        PsCreateSystemThread(&ThreadHandle,0L,NULL,NULL,&cid,MyThread,NULL);
        if (ThreadHandle)

        {
                PsLookupThreadByThreadId(cid.UniqueThread, (PETHREAD *)&pThread);

                ZwClose(ThreadHandle);
        }

解决啦  感谢~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2009-8-30 23:48
0
雪    币: 376
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
CLIENT_ID ThreadCID;
PETHREAD pEThread;
PsLookupThreadByThreadId ( ThreadCID.UniqueThread , &pEThread );

编译提示:error C4013: 'PsLookupThreadByThreadId' undefined; assuming extern returning int
怎么会这样啊?
2009-10-4 10:51
0
雪    币: 254
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
楼主学习办法真不行。你去探索这个函数的原型不就知道了吗?
2009-10-4 11:15
0
游客
登录 | 注册 方可回帖
返回
//