📄 ntoskernel.c
字号:
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 + -