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

📄 ntoskernel.c

📁 ndiswrapper工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *  GNU General Public License for more details. * */#include "ntoskernel.h"#include "ndis.h"#include "usb.h"#include "pnp.h"#include "loader.h"/* MDLs describe a range of virtual address with an array of physical * pages right after the header. For different ranges of virtual * addresses, the number of entries of physical pages may be different * (depending on number of entries required). If we want to allocate * MDLs from a pool, the size has to be constant. So we assume that * maximum range used by a driver is CACHE_MDL_PAGES; if a driver * requests an MDL for a bigger region, we allocate it with kmalloc; * otherwise, we allocate from the pool */#define CACHE_MDL_PAGES 3#define CACHE_MDL_SIZE (sizeof(struct mdl) + \			(sizeof(PFN_NUMBER) * CACHE_MDL_PAGES))struct wrap_mdl {	struct nt_list list;	struct mdl mdl[0];};struct thread_event_waitq {	wait_queue_head_t head;	BOOLEAN done;#ifdef EVENT_DEBUG	struct task_struct *task;#endif	struct thread_event_waitq *next;};/* everything here is for all drivers/devices - not per driver/device */static NT_SPIN_LOCK dispatcher_lock;static struct thread_event_waitq *thread_event_waitq_pool;NT_SPIN_LOCK ntoskernel_lock;static kmem_cache_t *mdl_cache;static struct nt_list wrap_mdl_list;/* use tasklet instead worker to execute kdpc's */#define KDPC_TASKLET 1#ifdef KDPC_TASKLETstatic struct tasklet_struct kdpc_work;static void kdpc_worker(unsigned long dummy);#elsestatic struct work_struct kdpc_work;static void kdpc_worker(void *data);#endifstatic struct nt_list kdpc_list;static NT_SPIN_LOCK kdpc_list_lock;static struct nt_list callback_objects;struct nt_list object_list;struct bus_driver {	struct nt_list list;	char name[MAX_DRIVER_NAME_LEN];	struct driver_object drv_obj;};static struct nt_list bus_driver_list;static struct work_struct ntos_work_item_work;static struct nt_list ntos_work_item_list;static NT_SPIN_LOCK ntos_work_item_list_lock;static void ntos_work_item_worker(void *data);NT_SPIN_LOCK irp_cancel_lock;extern struct nt_list wrap_drivers;static struct nt_list wrap_timer_list;NT_SPIN_LOCK timer_lock;/* compute ticks (100ns) since 1601 until when system booted into * wrap_ticks_to_boot */u64 wrap_ticks_to_boot;#if defined(CONFIG_X86_64)static struct timer_list shared_data_timer;struct kuser_shared_data kuser_shared_data;static void update_user_shared_data_proc(unsigned long data);#endifstatic int add_bus_driver(const char *name);static BOOLEAN queue_kdpc(struct kdpc *kdpc);WIN_SYMBOL_MAP("KeTickCount", &jiffies)WIN_SYMBOL_MAP("NlsMbCodePageTag", FALSE)#ifdef USE_OWN_NTOS_WORKQUEUEstruct workqueue_struct *ntos_wq;#endifint ntoskernel_init(void){	struct timeval now;	nt_spin_lock_init(&dispatcher_lock);	nt_spin_lock_init(&ntoskernel_lock);	nt_spin_lock_init(&ntos_work_item_list_lock);	nt_spin_lock_init(&kdpc_list_lock);	nt_spin_lock_init(&irp_cancel_lock);	InitializeListHead(&wrap_mdl_list);	InitializeListHead(&kdpc_list);	InitializeListHead(&callback_objects);	InitializeListHead(&bus_driver_list);	InitializeListHead(&object_list);	InitializeListHead(&ntos_work_item_list);#ifdef KDPC_TASKLET	tasklet_init(&kdpc_work, kdpc_worker, 0);#else	INIT_WORK(&kdpc_work, kdpc_worker, NULL);#endif	INIT_WORK(&ntos_work_item_work, ntos_work_item_worker, NULL);	nt_spin_lock_init(&timer_lock);	InitializeListHead(&wrap_timer_list);	thread_event_waitq_pool = NULL;	do_gettimeofday(&now);	wrap_ticks_to_boot = (u64)now.tv_sec * TICKSPERSEC;	wrap_ticks_to_boot += now.tv_usec * 10;	wrap_ticks_to_boot -= jiffies * TICKSPERSEC / HZ;	wrap_ticks_to_boot += TICKS_1601_TO_1970;#ifdef USE_OWN_NTOS_WORKQUEUE	ntos_wq = create_singlethread_workqueue("ntos_wq");#endif	if (add_bus_driver("PCI")#ifdef CONFIG_USB	    || add_bus_driver("USB")#endif		) {		ntoskernel_exit();		return -ENOMEM;	}	mdl_cache = kmem_cache_create("wrap_mdl",				      sizeof(struct wrap_mdl) + CACHE_MDL_SIZE,				      0, 0, NULL, NULL);	DBGTRACE2("%p", mdl_cache);	if (!mdl_cache) {		ERROR("couldn't allocate MDL cache");		ntoskernel_exit();		return -ENOMEM;	}#if defined(CONFIG_X86_64)	memset(&kuser_shared_data, 0, sizeof(kuser_shared_data));	init_timer(&shared_data_timer);	shared_data_timer.function = update_user_shared_data_proc;#endif	return 0;}int ntoskernel_init_device(struct wrap_device *wd){#if defined(CONFIG_X86_64)	*((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601();	shared_data_timer.data = (unsigned long)0;	/* don't use add_timer - to avoid creating more than one	 * timer */	mod_timer(&shared_data_timer, jiffies + 1);#endif	return 0;}void ntoskernel_exit_device(struct wrap_device *wd){	TRACEENTER2("");	KeFlushQueuedDpcs();	TRACEEXIT2(return);}void ntoskernel_exit(void){	struct nt_list *cur;	KIRQL irql;	TRACEENTER2("");#ifdef KDPC_TASKLET	tasklet_kill(&kdpc_work);#endif	/* free kernel (Ke) timers */	DBGTRACE2("freeing timers");	while (1) {		struct wrap_timer *wrap_timer;		irql = nt_spin_lock_irql(&timer_lock, DISPATCH_LEVEL);		cur = RemoveTailList(&wrap_timer_list);		nt_spin_unlock_irql(&timer_lock, irql);		if (!cur)			break;		wrap_timer = container_of(cur, struct wrap_timer, list);		if (del_timer_sync(&wrap_timer->timer))			WARNING("Buggy Windows driver left timer %p running",				&wrap_timer->timer);		memset(wrap_timer, 0, sizeof(*wrap_timer));		slack_kfree(wrap_timer);	}	DBGTRACE2("freeing MDLs");	if (mdl_cache) {		irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);		if (!IsListEmpty(&wrap_mdl_list))			ERROR("Windows driver didn't free all MDLs; "			      "freeing them now");		while ((cur = RemoveHeadList(&wrap_mdl_list))) {			struct wrap_mdl *wrap_mdl;			wrap_mdl = container_of(cur, struct wrap_mdl, list);			if (wrap_mdl->mdl->flags & MDL_CACHE_ALLOCATED)				kmem_cache_free(mdl_cache, wrap_mdl);			else				kfree(wrap_mdl);		}		nt_spin_unlock_irql(&ntoskernel_lock, irql);		kmem_cache_destroy(mdl_cache);		mdl_cache = NULL;	}	DBGTRACE2("freeing callbacks");	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	while ((cur = RemoveHeadList(&callback_objects))) {		struct callback_object *object;		struct nt_list *ent;		object = container_of(cur, struct callback_object, list);		while ((ent = RemoveHeadList(&object->callback_funcs))) {			struct callback_func *f;			f = container_of(ent, struct callback_func, list);			kfree(f);		}		kfree(object);	}	nt_spin_unlock_irql(&ntoskernel_lock, irql);	irql = nt_spin_lock_irql(&dispatcher_lock, DISPATCH_LEVEL);	DBGTRACE2("freeing thread event pool");	while (thread_event_waitq_pool) {		struct thread_event_waitq *next;		next = thread_event_waitq_pool->next;		kfree(thread_event_waitq_pool);		thread_event_waitq_pool = next;	}	nt_spin_unlock_irql(&dispatcher_lock, irql);	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	while ((cur = RemoveHeadList(&bus_driver_list))) {		struct bus_driver *bus_driver;		bus_driver = container_of(cur, struct bus_driver, list);		/* TODO: make sure all all drivers are shutdown/removed */		kfree(bus_driver);	}	nt_spin_unlock_irql(&ntoskernel_lock, irql);	TRACEENTER2("freeing objects");	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	while ((cur = RemoveHeadList(&object_list))) {		struct common_object_header *hdr;		hdr = container_of(cur, struct common_object_header, list);		WARNING("object %p type %d was not freed, freeing it now",			HEADER_TO_OBJECT(hdr), hdr->type);		ExFreePool(hdr);	}	nt_spin_unlock_irql(&ntoskernel_lock, irql);#if defined(CONFIG_X86_64)	del_timer_sync(&shared_data_timer);#endif#ifdef USE_OWN_NTOS_WORKQUEUE	if (ntos_wq)		destroy_workqueue(ntos_wq);#endif	TRACEEXIT2(return);}#if defined(CONFIG_X86_64)static void update_user_shared_data_proc(unsigned long data){	/* timer is supposed to be scheduled every 10ms, but bigger	 * intervals seem to work (tried upto 50ms) */	*((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601();	*((ULONG64 *)&kuser_shared_data.interrupt_time) =		jiffies * TICKSPERSEC / HZ;	*((ULONG64 *)&kuser_shared_data.tick) = jiffies;	shared_data_timer.expires += 30 * HZ / 1000 + 1;	add_timer(&shared_data_timer);}#endifvoid *allocate_object(ULONG size, enum common_object_type type,		      struct unicode_string *name){	struct common_object_header *hdr;	void *body;	KIRQL irql;	/* we pad header as prefix to body */	hdr = ExAllocatePoolWithTag(NonPagedPool, OBJECT_SIZE(size), 0);	if (!hdr) {		WARNING("couldn't allocate memory");		return NULL;	}	memset(hdr, 0, OBJECT_SIZE(size));	if (name) {		hdr->name.buf = ExAllocatePoolWithTag(NonPagedPool,						      name->max_length, 0);		if (!hdr->name.buf) {			ExFreePool(hdr);			return NULL;		}		memcpy(hdr->name.buf, name->buf, name->max_length);		hdr->name.length = name->length;		hdr->name.max_length = name->max_length;	}	hdr->type = type;	hdr->ref_count = 1;	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	/* threads are looked up often (in KeWaitForXXX), so optimize	 * for fast lookups of threads */	if (type == OBJECT_TYPE_NT_THREAD)		InsertHeadList(&object_list, &hdr->list);	else		InsertTailList(&object_list, &hdr->list);	nt_spin_unlock_irql(&ntoskernel_lock, irql);	body = HEADER_TO_OBJECT(hdr);	DBGTRACE3("allocated hdr: %p, body: %p", hdr, body);	return body;}void free_object(void *object){	struct common_object_header *hdr;	KIRQL irql;	hdr = OBJECT_TO_HEADER(object);	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	RemoveEntryList(&hdr->list);	nt_spin_unlock_irql(&ntoskernel_lock, irql);	DBGTRACE3("freed hdr: %p, body: %p", hdr, object);	if (hdr->name.buf)		ExFreePool(hdr->name.buf);	ExFreePool(hdr);}static int add_bus_driver(const char *name){	struct bus_driver *bus_driver;	KIRQL irql;	bus_driver = kmalloc(sizeof(*bus_driver), GFP_KERNEL);	if (!bus_driver) {		ERROR("couldn't allocate memory");		return -ENOMEM;	}	memset(bus_driver, 0, sizeof(*bus_driver));	strncpy(bus_driver->name, name, sizeof(bus_driver->name));	bus_driver->name[sizeof(bus_driver->name)-1] = 0;	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	InsertTailList(&bus_driver_list, &bus_driver->list);	nt_spin_unlock_irql(&ntoskernel_lock, irql);	DBGTRACE1("bus driver %s is at %p", name, &bus_driver->drv_obj);	return STATUS_SUCCESS;}struct driver_object *find_bus_driver(const char *name){	struct bus_driver *bus_driver;	struct driver_object *drv_obj;	KIRQL irql;	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	drv_obj = NULL;	nt_list_for_each_entry(bus_driver, &bus_driver_list, list) {		if (strcmp(bus_driver->name, name) == 0)			drv_obj = &bus_driver->drv_obj;	}	nt_spin_unlock_irql(&ntoskernel_lock, irql);	return drv_obj;}wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertHeadList,3)	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock){	struct nt_list *first;	unsigned long flags;	TRACEENTER5("head = %p, entry = %p", head, entry);	nt_spin_lock_irqsave(lock, flags);	first = InsertHeadList(head, entry);	nt_spin_unlock_irqrestore(lock, flags);	DBGTRACE5("head = %p, old = %p", head, first);	return first;}wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertHeadList,3)	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock){	TRACEENTER5("%p", head);	return ExfInterlockedInsertHeadList(head, entry, lock);}wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertTailList,3)	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock){	struct nt_list *last;	unsigned long flags;	TRACEENTER5("head = %p, entry = %p", head, entry);	nt_spin_lock_irqsave(lock, flags);	last = InsertTailList(head, entry);	nt_spin_unlock_irqrestore(lock, flags);	DBGTRACE5("head = %p, old = %p", head, last);	return last;}wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertTailList,3)	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock){	TRACEENTER5("%p", head);	return ExfInterlockedInsertTailList(head, entry, lock);}wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveHeadList,2)	(struct nt_list *head, NT_SPIN_LOCK *lock){	struct nt_list *ret;	unsigned long flags;	TRACEENTER5("head = %p", head);	nt_spin_lock_irqsave(lock, flags);	ret = RemoveHeadList(head);	nt_spin_unlock_irqrestore(lock, flags);	DBGTRACE5("head = %p, ret = %p", head, ret);	return ret;}wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveHeadList,2)	(struct nt_list *head, NT_SPIN_LOCK *lock){	TRACEENTER5("%p", head);	return ExfInterlockedRemoveHeadList(head, lock);}wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveTailList,2)	(struct nt_list *head, NT_SPIN_LOCK *lock){	struct nt_list *ret;	unsigned long flags;	TRACEENTER5("head = %p", head);	nt_spin_lock_irqsave(lock, flags);	ret = RemoveTailList(head);	nt_spin_unlock_irqrestore(lock, flags);	DBGTRACE5("head = %p, ret = %p", head, ret);	return ret;}wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveTailList,2)

⌨️ 快捷键说明

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