⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntoskernel.c

📁 ndiswrapper工具
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (thread_waitq->task != current)			ERROR("%p: argh, task %p should be %p", thread_waitq,			      thread_waitq->task, current);#endif//		assert(res < 0 && alertable);		if (res <= 0) {			/* timed out or interrupted; remove from wait list */			for (i = 0; i < count; i++) {				if (!wb[i].thread)					continue;				EVENTTRACE("%p: timedout, deq'ing %p (%p)",					   thread, object[i], wb[i].object);				RemoveEntryList(&wb[i].list);			}			put_thread_event_waitq(thread_waitq);			nt_spin_unlock_irql(&dispatcher_lock, irql);			if (res < 0)				EVENTEXIT(return STATUS_ALERTED);			else				EVENTEXIT(return STATUS_TIMEOUT);		}		/* woken up by wakeup_threads */		for (i = 0; wait_count && i < count; i++) {			if (!wb[i].thread)				continue;			EVENTTRACE("object: %p, %p", object[i], wb[i].object);			if (!wb[i].object) {				EVENTTRACE("not woken for %p", object[i]);				continue;			}			DBG_BLOCK(1) {				if (wb[i].object != object[i]) {					ERROR("argh, event not signalled? "					      "%p, %p", wb[i].object,					      object[i]);					continue;				}			}			wb[i].object = NULL;			wb[i].thread = NULL;			wait_count--;			if (wait_type == WaitAny) {				int j;				/* done; remove from rest of wait list */				for (j = i; j < count; j++)					if (wb[j].thread)						RemoveEntryList(&wb[j].list);				put_thread_event_waitq(thread_waitq);				nt_spin_unlock_irql(&dispatcher_lock, irql);				EVENTEXIT(return STATUS_WAIT_0 + i);			}		}		if (wait_count == 0) {			put_thread_event_waitq(thread_waitq);			nt_spin_unlock_irql(&dispatcher_lock, irql);			EVENTEXIT(return STATUS_SUCCESS);		}		/* this thread is still waiting for more objects, so		 * let it wait for remaining time and those objects */		/* we already set res to 1 if timeout was NULL, so		 * reinitialize wait_jiffies accordingly */		if (timeout)			wait_jiffies = res;		else			wait_jiffies = 0;		nt_spin_unlock_irql(&dispatcher_lock, irql);	}	/* this should never reach, but compiler wants return value */	ERROR("%p: wait_jiffies: %ld", thread, wait_jiffies);	EVENTEXIT(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(KeWaitForSingleObject,5)	(void *object, KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode,	 BOOLEAN alertable, LARGE_INTEGER *timeout){	return KeWaitForMultipleObjects(1, &object, WaitAny, wait_reason,					wait_mode, alertable, timeout, NULL);}wstdcall void WIN_FUNC(KeInitializeEvent,3)	(struct nt_event *nt_event, enum event_type type, BOOLEAN state){	EVENTENTER("event = %p, type = %d, state = %d", nt_event, type, state);	initialize_dh(&nt_event->dh, type, state);	EVENTEXIT(return);}wstdcall LONG WIN_FUNC(KeSetEvent,3)	(struct nt_event *nt_event, KPRIORITY incr, BOOLEAN wait){	LONG old_state;	KIRQL irql;	EVENTENTER("event = %p, type = %d, wait = %d",		   nt_event, nt_event->dh.type, wait);	if (wait == TRUE)		WARNING("wait = %d, not yet implemented", wait);	irql = nt_spin_lock_irql(&dispatcher_lock, DISPATCH_LEVEL);	old_state = nt_event->dh.signal_state;	nt_event->dh.signal_state = 1;	if (old_state == 0)		wakeup_threads(&nt_event->dh);	nt_spin_unlock_irql(&dispatcher_lock, irql);	EVENTEXIT(return old_state);}wstdcall void WIN_FUNC(KeClearEvent,1)	(struct nt_event *nt_event){	EVENTENTER("event = %p", nt_event);	(void)xchg(&nt_event->dh.signal_state, 0);	EVENTEXIT(return);}wstdcall LONG WIN_FUNC(KeResetEvent,1)	(struct nt_event *nt_event){	LONG old_state;	old_state = xchg(&nt_event->dh.signal_state, 0);	EVENTTRACE("old state: %d", old_state);	EVENTEXIT(return old_state);}wstdcall void WIN_FUNC(KeInitializeMutex,2)	(struct nt_mutex *mutex, ULONG level){	KIRQL irql;	EVENTENTER("%p", mutex);	irql = nt_spin_lock_irql(&dispatcher_lock, DISPATCH_LEVEL);	initialize_dh(&mutex->dh, MutexObject, 1);	mutex->dh.size = sizeof(*mutex);	InitializeListHead(&mutex->list);	mutex->abandoned = FALSE;	mutex->apc_disable = 1;	mutex->owner_thread = NULL;	nt_spin_unlock_irql(&dispatcher_lock, irql);	EVENTEXIT(return);}wstdcall LONG WIN_FUNC(KeReleaseMutex,2)	(struct nt_mutex *mutex, BOOLEAN wait){	LONG ret;	KIRQL irql;	struct task_struct *thread;	EVENTENTER("%p, %d, %p", mutex, wait, current);	if (wait == TRUE)		WARNING("wait: %d", wait);	thread = current;	irql = nt_spin_lock_irql(&dispatcher_lock, DISPATCH_LEVEL);	EVENTTRACE("%p, %p, %d", thread, mutex->owner_thread,		   mutex->dh.signal_state);	if ((mutex->owner_thread == thread) && (mutex->dh.signal_state <= 0)) {		if ((ret = mutex->dh.signal_state++) == 0) {			mutex->owner_thread = NULL;			wakeup_threads(&mutex->dh);		}	} else		ret = STATUS_MUTANT_NOT_OWNED;	nt_spin_unlock_irql(&dispatcher_lock, irql);	EVENTTRACE("ret: %08X", ret);	EVENTEXIT(return ret);}wstdcall void WIN_FUNC(KeInitializeSemaphore,3)	(struct nt_semaphore *semaphore, LONG count, LONG limit){	EVENTENTER("%p: %d", semaphore, count);	/* if limit > 1, we need to satisfy as many waits (until count	 * becomes 0); so we keep decrementing count everytime a wait	 * is satisified */	initialize_dh(&semaphore->dh, SemaphoreObject, count);	semaphore->dh.size = sizeof(*semaphore);	semaphore->limit = limit;	EVENTEXIT(return);}wstdcall LONG WIN_FUNC(KeReleaseSemaphore,4)	(struct nt_semaphore *semaphore, KPRIORITY incr, LONG adjustment,	 BOOLEAN wait){	LONG ret;	KIRQL irql;	EVENTENTER("%p", semaphore);	irql = nt_spin_lock_irql(&dispatcher_lock, DISPATCH_LEVEL);	ret = semaphore->dh.signal_state;	assert(ret >= 0);	if (semaphore->dh.signal_state + adjustment <= semaphore->limit)		semaphore->dh.signal_state += adjustment;	else {		WARNING("releasing %d over limit %d", adjustment,			semaphore->limit);		semaphore->dh.signal_state = semaphore->limit;	}	if (semaphore->dh.signal_state > 0)		wakeup_threads(&semaphore->dh);	nt_spin_unlock_irql(&dispatcher_lock, irql);	EVENTEXIT(return ret);}wstdcall NTSTATUS WIN_FUNC(KeDelayExecutionThread,3)	(KPROCESSOR_MODE wait_mode, BOOLEAN alertable, LARGE_INTEGER *interval){	int res;	long timeout;	if (wait_mode != 0)		ERROR("invalid wait_mode %d", wait_mode);	timeout = SYSTEM_TIME_TO_HZ(*interval) + 1;	EVENTTRACE("thread: %p, interval: %Ld, timeout: %ld",		    current, *interval, timeout);	if (timeout <= 0)		EVENTEXIT(return STATUS_SUCCESS);	alertable = TRUE;	if (alertable)		set_current_state(TASK_INTERRUPTIBLE);	else		set_current_state(TASK_UNINTERRUPTIBLE);	res = schedule_timeout(timeout);	EVENTTRACE("thread: %p, res: %d", current, res);	if (res == 0)		EVENTEXIT(return STATUS_SUCCESS);	else		EVENTEXIT(return STATUS_ALERTED);}wstdcall KPRIORITY WIN_FUNC(KeQueryPriorityThread,1)	(struct task_struct *task){	KPRIORITY prio;	EVENTENTER("task: %p", task);	return LOW_REALTIME_PRIORITY;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)	prio = 1;#else	if (rt_task(task))		prio = LOW_REALTIME_PRIORITY;	else		prio = MAXIMUM_PRIORITY;#endif	EVENTEXIT(return prio);}wstdcall ULONGLONG WIN_FUNC(KeQueryInterruptTime,0)	(void){	TRACEEXIT5(return jiffies * TICKSPERSEC / HZ);}wstdcall ULONG WIN_FUNC(KeQueryTimeIncrement,0)	(void){	TRACEEXIT5(return TICKSPERSEC / HZ);}wstdcall void WIN_FUNC(KeQuerySystemTime,1)	(LARGE_INTEGER *time){	*time = ticks_1601();	return;}wstdcall void WIN_FUNC(KeQueryTickCount,1)	(LARGE_INTEGER *j){	*j = jiffies;}wstdcall LARGE_INTEGER WIN_FUNC(KeQueryPerformanceCounter,1)	(LARGE_INTEGER *counter){	if (counter)		*counter = HZ;	return jiffies;}wstdcall struct task_struct *WIN_FUNC(KeGetCurrentThread,0)	(void){	struct task_struct *task = current;	DBGTRACE5("task: %p", task);	return task;}wstdcall KPRIORITY WIN_FUNC(KeSetPriorityThread,2)	(struct task_struct *task, KPRIORITY priority){	KPRIORITY old_prio;	TRACEENTER3("task: %p, priority = %u", task, priority);	return LOW_REALTIME_PRIORITY;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)	/* FIXME: is there a way to set kernel thread prio on 2.4? */	old_prio = LOW_PRIORITY;#else	if (rt_task(task))		old_prio = LOW_REALTIME_PRIORITY;	else		old_prio = MAXIMUM_PRIORITY;#if 0	if (priority == LOW_REALTIME_PRIORITY)		set_user_nice(task, -20);	else		set_user_nice(task, 10);#endif#endif	return old_prio;}struct trampoline_context {	void (*start_routine)(void *) wstdcall;	void *context;	struct nt_thread *thread;};static int thread_trampoline(void *data){	struct trampoline_context ctx;	struct nt_thread *thread;	memcpy(&ctx, data, sizeof(ctx));	kfree(data);	thread = ctx.thread;	thread->task = current;	thread->pid = thread->task->pid;#ifdef PF_NOFREEZE	current->flags |= PF_NOFREEZE;#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)	strncpy(current->comm, "windisdrvr", sizeof(current->comm));	current->comm[sizeof(current->comm)-1] = 0;#endif	DBGTRACE2("thread: %p, task: %p (%d)", thread, thread->task,		  thread->pid);	LIN2WIN1(ctx.start_routine, ctx.context);	DBGTRACE2("thread: %p, task: %p (%d)", thread, thread->task,		  thread->pid);	return 0;}static struct nt_thread *create_nt_thread(struct task_struct *task){	struct nt_thread *thread;	thread = allocate_object(sizeof(*thread), OBJECT_TYPE_NT_THREAD, NULL);	if (!thread) {		ERROR("couldn't allocate thread object");		return NULL;	}	thread->task = task;	if (task)		thread->pid = task->pid;	else		thread->pid = 0;	nt_spin_lock_init(&thread->lock);	InitializeListHead(&thread->irps);	initialize_dh(&thread->dh, ThreadObject, 0);	thread->dh.size = sizeof(*thread);	DBGTRACE2("thread: %p, task: %p, pid: %d",		  thread, thread->task, thread->pid);	return thread;}static void remove_nt_thread(struct nt_thread *thread){	struct nt_list *ent;	KIRQL irql;	if (!thread) {		ERROR("invalid thread");		return;	}	DBGTRACE1("terminating thread: %p, task: %p, pid: %d",		  thread, thread->task, thread->task->pid);	/* TODO: make sure waitqueue is empty and destroy it */	while (1) {		struct irp *irp;		irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);		ent = RemoveHeadList(&thread->irps);		nt_spin_unlock_irql(&thread->lock, irql);		if (!ent)			break;		irp = container_of(ent, struct irp, threads);		IoCancelIrp(irp);	}	ObDereferenceObject(thread);}struct nt_thread *get_current_nt_thread(void){	struct task_struct *task = current;	struct nt_thread *ret;	struct common_object_header *header;	KIRQL irql;	DBGTRACE5("task: %p", task);	ret = NULL;	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	nt_list_for_each_entry(header, &object_list, list) {		struct nt_thread *thread;		DBGTRACE5("header: %p, type: %d", header, header->type);		if (header->type != OBJECT_TYPE_NT_THREAD)			break;		thread = HEADER_TO_OBJECT(header);		DBGTRACE5("thread: %p, task: %p", thread, thread->task);		if (thread->task == task) {			ret = thread;			break;		}	}	nt_spin_unlock_irql(&ntoskernel_lock, irql);	if (ret == NULL)		DBGTRACE3("couldn't find thread for task %p, %d",			  task, current->pid);	DBGTRACE5("current thread = %p", ret);	return ret;}wstdcall NTSTATUS WIN_FUNC(PsCreateSystemThread,7)	(void **phandle, ULONG access, void *obj_attr, void *process,	 void *client_id, void (*start_routine)(void *) wstdcall, void *context){	struct trampoline_context *ctx;	struct nt_thread *thread;	struct task_struct *task;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)	int pid;#endif	TRACEENTER2("phandle = %p, access = %u, obj_attr = %p, process = %p, "	            "client_id = %p, start_routine = %p, context = %p",	            phandle, access, obj_attr, process, client_id,	            start_routine, context);	ctx = kmalloc(sizeof(struct trampoline_context), GFP_KERNEL);	if (!ctx)		TRACEEXIT2(return STATUS_RESOURCES);	ctx->start_routine = start_routine;	ctx->context = context;	thread = create_nt_thread(NULL);	if (!thread) {		kfree(ctx);		TRACEEXIT2(return STATUS_RESOURCES);	}	ctx->thread = thread;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)	pid = kernel_thread(thread_trampoline, ctx,			    CLONE_FS | CLONE_FILES | CLONE_SIGHAND);	DBGTRACE2("pid = %d", pid);	if (pid < 0) {		kfree(ctx);		free_object(thread);		TRACEEXIT2(return STATUS_FAILURE);	}	task = NULL;	DBGTRACE2("created task: %p (%d)", task, pid);#else	task = KTHREAD_RUN(thread_trampoline, ctx, "windisdrvr");	if (IS_ERR(task)) {		kfree(ctx);		free_object(thread);		TRACEEXIT2(return STATUS_FAILURE);	}	DBGTRACE2("created task: %p (%d)", task, task->pid);#endif	*phandle = OBJECT_TO_HEADER(thread);	DBGTRACE2("created thread: %p, %p", thread, *phandle);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -