📄 ntoskernel_io.c
字号:
interrupt->shareable = shareable; interrupt->floating_save = floating_save; interrupt->service_routine = service_routine; interrupt->service_context = service_context; InitializeListHead(&interrupt->list); interrupt->irql = irql; interrupt->synch_irql = synch_irql; interrupt->interrupt_mode = interrupt_mode; if (request_irq(vector, io_irq_isr, shareable ? IRQF_SHARED : 0, "io_irq", interrupt)) { WARNING("request for irq %d failed", vector); kfree(interrupt); IOEXIT(return STATUS_INSUFFICIENT_RESOURCES); } *kinterrupt = interrupt; IOEXIT(return STATUS_SUCCESS);}wstdcall void WIN_FUNC(IoDisconnectInterrupt,1) (struct kinterrupt *interrupt){ free_irq(interrupt->vector, interrupt); kfree(interrupt);}wstdcall struct mdl *WIN_FUNC(IoAllocateMdl,5) (void *virt, ULONG length, BOOLEAN second_buf, BOOLEAN charge_quota, struct irp *irp){ struct mdl *mdl; mdl = allocate_init_mdl(virt, length); if (!mdl) return NULL; if (irp) { if (second_buf == TRUE) { struct mdl *last; last = irp->mdl; while (last->next) last = last->next; last->next = mdl; } else irp->mdl = mdl; } IOTRACE("%p", mdl); return mdl;}wstdcall void WIN_FUNC(IoFreeMdl,1) (struct mdl *mdl){ IOTRACE("%p", mdl); free_mdl(mdl);}wstdcall struct io_workitem *WIN_FUNC(IoAllocateWorkItem,1) (struct device_object *dev_obj){ struct io_workitem *io_workitem; IOENTER("%p", dev_obj); io_workitem = kmalloc(sizeof(*io_workitem), gfp_irql()); if (!io_workitem) IOEXIT(return NULL); io_workitem->dev_obj = dev_obj; IOEXIT(return io_workitem);}wstdcall void WIN_FUNC(IoFreeWorkItem,1) (struct io_workitem *io_workitem){ kfree(io_workitem); IOEXIT(return);}wstdcall void WIN_FUNC(IoQueueWorkItem,4) (struct io_workitem *io_workitem, void *func, enum work_queue_type queue_type, void *context){ IOENTER("%p, %p", io_workitem, io_workitem->dev_obj); io_workitem->worker_routine = func; io_workitem->context = context; schedule_ntos_work_item(func, io_workitem->dev_obj, context); IOEXIT(return);}wstdcall void WIN_FUNC(ExQueueWorkItem,2) (struct io_workitem *io_workitem, enum work_queue_type queue_type){ IOENTER("%p", io_workitem); schedule_ntos_work_item(io_workitem->worker_routine, io_workitem->dev_obj, io_workitem->context);}wstdcall NTSTATUS WIN_FUNC(IoAllocateDriverObjectExtension,4) (struct driver_object *drv_obj, void *client_id, ULONG extlen, void **ext){ struct custom_ext *ce; KIRQL irql; IOENTER("%p, %p", drv_obj, client_id); ce = kmalloc(sizeof(*ce) + extlen, gfp_irql()); if (ce == NULL) return STATUS_INSUFFICIENT_RESOURCES; IOTRACE("custom_ext: %p", ce); ce->client_id = client_id; irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); InsertTailList(&drv_obj->drv_ext->custom_ext, &ce->list); nt_spin_unlock_irql(&ntoskernel_lock, irql); *ext = (void *)ce + sizeof(*ce); IOTRACE("ext: %p", *ext); IOEXIT(return STATUS_SUCCESS);}wstdcall void *WIN_FUNC(IoGetDriverObjectExtension,2) (struct driver_object *drv_obj, void *client_id){ struct custom_ext *ce; void *ret; KIRQL irql; IOENTER("drv_obj: %p, client_id: %p", drv_obj, client_id); ret = NULL; irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); nt_list_for_each_entry(ce, &drv_obj->drv_ext->custom_ext, list) { if (ce->client_id == client_id) { ret = (void *)ce + sizeof(*ce); break; } } nt_spin_unlock_irql(&ntoskernel_lock, irql); IOENTER("ret: %p", ret); IOEXIT(return ret);}void free_custom_extensions(struct driver_extension *drv_ext){ struct nt_list *ent; KIRQL irql; IOENTER("%p", drv_ext); irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); while ((ent = RemoveHeadList(&drv_ext->custom_ext))) kfree(ent); nt_spin_unlock_irql(&ntoskernel_lock, irql); IOEXIT(return);}wstdcall NTSTATUS WIN_FUNC(IoCreateDevice,7) (struct driver_object *drv_obj, ULONG dev_ext_length, struct unicode_string *dev_name, DEVICE_TYPE dev_type, ULONG dev_chars, BOOLEAN exclusive, struct device_object **newdev){ struct device_object *dev; struct dev_obj_ext *dev_obj_ext; int size; IOENTER("%p, %u, %p", drv_obj, dev_ext_length, dev_name); size = sizeof(*dev) + dev_ext_length + sizeof(*dev_obj_ext); dev = allocate_object(size, OBJECT_TYPE_DEVICE, dev_name); if (!dev) IOEXIT(return STATUS_INSUFFICIENT_RESOURCES); if (dev_ext_length) dev->dev_ext = dev + 1; else dev->dev_ext = NULL; dev_obj_ext = ((void *)(dev + 1)) + dev_ext_length; dev_obj_ext->dev_obj = dev; dev_obj_ext->size = 0; dev_obj_ext->type = IO_TYPE_DEVICE; dev->dev_obj_ext = dev_obj_ext; dev->type = dev_type; dev->flags = 0; dev->size = sizeof(*dev) + dev_ext_length; dev->ref_count = 1; dev->attached = NULL; dev->stack_count = 1; dev->drv_obj = drv_obj; dev->next = drv_obj->dev_obj; drv_obj->dev_obj = dev; dev->align_req = 1; dev->characteristics = dev_chars; dev->io_timer = NULL; KeInitializeEvent(&dev->lock, SynchronizationEvent, TRUE); dev->vpb = NULL; IOTRACE("dev: %p, ext: %p", dev, dev->dev_ext); *newdev = dev; IOEXIT(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(IoCreateUnprotectedSymbolicLink,2) (struct unicode_string *link, struct unicode_string *dev_name){ struct ansi_string ansi; IOENTER("%p, %p", dev_name, link); if (dev_name && (RtlUnicodeStringToAnsiString(&ansi, dev_name, TRUE) == STATUS_SUCCESS)) { IOTRACE("dev_name: %s", ansi.buf); RtlFreeAnsiString(&ansi); } if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) == STATUS_SUCCESS)) { IOTRACE("link: %s", ansi.buf); RtlFreeAnsiString(&ansi); }// TODO(); IOEXIT(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(IoCreateSymbolicLink,2) (struct unicode_string *link, struct unicode_string *dev_name){ IOEXIT(return IoCreateUnprotectedSymbolicLink(link, dev_name));}wstdcall NTSTATUS WIN_FUNC(IoDeleteSymbolicLink,1) (struct unicode_string *link){ struct ansi_string ansi; IOENTER("%p", link); if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) == STATUS_SUCCESS)) { IOTRACE("dev_name: %s", ansi.buf); RtlFreeAnsiString(&ansi); } IOEXIT(return STATUS_SUCCESS);}wstdcall void WIN_FUNC(IoDeleteDevice,1) (struct device_object *dev){ IOENTER("%p", dev); if (dev == NULL) IOEXIT(return); IOTRACE("drv_obj: %p", dev->drv_obj); if (dev->drv_obj) { struct device_object *prev; prev = dev->drv_obj->dev_obj; IOTRACE("dev_obj: %p", prev); if (prev == dev) dev->drv_obj->dev_obj = dev->next; else if (prev) { while (prev->next != dev) prev = prev->next; prev->next = dev->next; } } ObDereferenceObject(dev); IOEXIT(return);}wstdcall void WIN_FUNC(IoDetachDevice,1) (struct device_object *tgt){ struct device_object *tail; KIRQL irql; IOENTER("%p", tgt); if (!tgt) IOEXIT(return); tail = tgt->attached; if (!tail) IOEXIT(return); IOTRACE("tail: %p", tail); irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); tgt->attached = tail->attached; IOTRACE("attached:%p", tgt->attached); for ( ; tail; tail = tail->attached) { IOTRACE("tail:%p", tail); tail->stack_count--; } nt_spin_unlock_irql(&ntoskernel_lock, irql); IOEXIT(return);}wstdcall struct device_object *WIN_FUNC(IoGetAttachedDevice,1) (struct device_object *dev){ KIRQL irql; IOENTER("%p", dev); if (!dev) IOEXIT(return NULL); irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); while (dev->attached) dev = dev->attached; nt_spin_unlock_irql(&ntoskernel_lock, irql); IOEXIT(return dev);}wstdcall struct device_object *WIN_FUNC(IoGetAttachedDeviceReference,1) (struct device_object *dev){ IOENTER("%p", dev); if (!dev) IOEXIT(return NULL); dev = IoGetAttachedDevice(dev); ObReferenceObject(dev); IOEXIT(return dev);}wstdcall struct device_object *WIN_FUNC(IoAttachDeviceToDeviceStack,2) (struct device_object *src, struct device_object *tgt){ struct device_object *attached; struct dev_obj_ext *src_dev_ext; KIRQL irql; IOENTER("%p, %p", src, tgt); attached = IoGetAttachedDevice(tgt); IOTRACE("%p", attached); src_dev_ext = src->dev_obj_ext; irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); if (attached) attached->attached = src; src->attached = NULL; src->stack_count = attached->stack_count + 1; src_dev_ext->attached_to = attached; nt_spin_unlock_irql(&ntoskernel_lock, irql); IOTRACE("stack_count: %d -> %d", attached->stack_count, src->stack_count); IOEXIT(return attached);}wstdcall NTSTATUS WIN_FUNC(IoGetDeviceProperty,5) (struct device_object *pdo, enum device_registry_property dev_property, ULONG buffer_len, void *buffer, ULONG *result_len){ struct ansi_string ansi; struct unicode_string unicode; struct wrap_device *wd; ULONG need; IOENTER("dev_obj = %p, dev_property = %d, buffer_len = %u, " "buffer = %p, result_len = %p", pdo, dev_property, buffer_len, buffer, result_len); wd = pdo->reserved; switch (dev_property) { case DevicePropertyDeviceDescription: case DevicePropertyFriendlyName: case DevicePropertyDriverKeyName: if (wrap_is_pci_bus(wd->dev_bus)) RtlInitAnsiString(&ansi, "PCI"); else // if (wrap_is_usb_bus(wd->dev_bus)) RtlInitAnsiString(&ansi, "USB"); need = sizeof(wchar_t) * (ansi.max_length + 1); if (buffer_len < need) { *result_len = need; IOEXIT(return STATUS_BUFFER_TOO_SMALL); } unicode.max_length = buffer_len; unicode.buf = buffer; if (RtlAnsiStringToUnicodeString(&unicode, &ansi, FALSE) != STATUS_SUCCESS) { *result_len = unicode.length; IOEXIT(return STATUS_BUFFER_TOO_SMALL); } IOEXIT(return STATUS_SUCCESS); default: WARNING("%d not implemented", dev_property); IOEXIT(return STATUS_INVALID_PARAMETER_2); }}wstdcall NTSTATUS WIN_FUNC(IoGetDeviceObjectPointer,4) (struct unicode_string *name, ACCESS_MASK desired_access, void *file_obj, struct device_object *dev_obj){ KIRQL irql; struct common_object_header *coh; dev_obj = NULL; /* TODO: access is not checked and file_obj is set to NULL */ file_obj = NULL; irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); nt_list_for_each_entry(coh, &object_list, list) { TRACE5("header: %p, type: %d", coh, coh->type); if (coh->type != OBJECT_TYPE_DEVICE) continue; if (!RtlCompareUnicodeString(&coh->name, name, TRUE)) { dev_obj = HEADER_TO_OBJECT(coh); TRACE5("dev_obj: %p", dev_obj); break; } } nt_spin_unlock_irql(&ntoskernel_lock, irql); if (dev_obj) IOEXIT(return STATUS_SUCCESS); else IOEXIT(return STATUS_OBJECT_NAME_INVALID);}/* NOTE: Make sure to compile with -freg-struct-return, so gcc will * return union in register, like Windows */wstdcall union power_state WIN_FUNC(PoSetPowerState,3) (struct device_object *dev_obj, enum power_state_type type, union power_state state){ IOEXIT(return state);}wstdcall NTSTATUS WIN_FUNC(PoCallDriver,2) (struct device_object *dev_obj, struct irp *irp){ return IoCallDriver(dev_obj, irp);}wstdcall NTSTATUS WIN_FUNC(PoRequestPowerIrp,6) (struct device_object *dev_obj, UCHAR minor_fn, union power_state power_state, void *completion_func, void *context, struct irp **pirp){ struct irp *irp; struct io_stack_location *irp_sl; TRACE1("%p, %d, %p", dev_obj, dev_obj->stack_count, dev_obj->drv_obj); irp = IoAllocateIrp(dev_obj->stack_count, FALSE); if (!irp) return STATUS_INSUFFICIENT_RESOURCES; irp_sl = IoGetNextIrpStackLocation(irp); irp_sl->major_fn = IRP_MJ_POWER; irp_sl->minor_fn = minor_fn; if (minor_fn == IRP_MN_WAIT_WAKE) irp_sl->params.power.type = SystemPowerState; else irp_sl->params.power.type = DevicePowerState; irp_sl->params.power.state = power_state; irp_sl->completion_routine = completion_func; irp->io_status.status = STATUS_NOT_SUPPORTED; *pirp = irp; return PoCallDriver(dev_obj, irp);}wstdcall void WIN_FUNC(PoStartNextPowerIrp,1) (struct irp *irp){ IOENTER("irp = %p", irp); IOEXIT(return);}wstdcall void WIN_FUNC(IoInitializeRemoveLockEx,5) (struct io_remove_lock *lock, ULONG alloc_tag, ULONG max_locked_min, ULONG high_mark, ULONG lock_size){ TODO();}wstdcall void *WIN_FUNC(IoAllocateErrorLogEntry,2) (void *io_object, UCHAR entry_size){ /* not implemented fully */ void *ret = kmalloc(sizeof(struct io_error_log_packet) + entry_size, gfp_irql()); TRACE2("%p", ret); if (ret) return ret + sizeof(struct io_error_log_packet); else return NULL;}wstdcall void WIN_FUNC(IoWriteErrorLogEntry,1) (void *entry){ /* TODO: log error with codes and message */ ERROR("");}wstdcall void WIN_FUNC(IoFreeErrorLogEntry,1) (void *entry){ TRACE2("%p", entry); kfree(entry - sizeof(struct io_error_log_packet));}wstdcall NTSTATUS WIN_FUNC(IoAcquireRemoveLockEx,5) (struct io_remove_lock lock, void *tag, char *file, ULONG line, ULONG lock_size){ TODO(); IOEXIT(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(IoReleaseRemoveLockEx,3) (struct io_remove_lock lock, void *tag, ULONG lock_size){ TODO(); IOEXIT(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(IoRegisterDeviceInterface,4) (struct device_object *pdo, struct guid *guid_class, struct unicode_string *reference, struct unicode_string *link){ struct ansi_string ansi; /* TODO: check if pdo is valid */ RtlInitAnsiString(&ansi, "ndis"); ENTER1("pdo: %p, ref: %p, link: %p, %x, %x, %x", pdo, reference, link, guid_class->data1, guid_class->data2, guid_class->data3); return RtlAnsiStringToUnicodeString(link, &ansi, TRUE);}wstdcall NTSTATUS WIN_FUNC(IoSetDeviceInterfaceState,2) (struct unicode_string *link, BOOLEAN enable){ ENTER1("link: %p, enable: %d", link, enable); return STATUS_SUCCESS;}wstdcall NTSTATUS WIN_FUNC(IoOpenDeviceRegistryKey,4) (struct device_object *dev_obj, ULONG type, ACCESS_MASK mask, void **handle){ ENTER1("dev_obj: %p", dev_obj); *handle = dev_obj; return STATUS_SUCCESS;}wstdcall NTSTATUS WIN_FUNC(IoWMIRegistrationControl,2) (struct device_object *dev_obj, ULONG action){ ENTER2("%p, %d", dev_obj, action); EXIT2(return STATUS_SUCCESS);}wstdcall void WIN_FUNC(IoInvalidateDeviceRelations,2) (struct device_object *dev_obj, enum device_relation_type type){ INFO("%p, %d", dev_obj, type); TODO();}wstdcall void WIN_FUNC(IoInvalidateDeviceState,1) (struct device_object *pdo){ INFO("%p", pdo); TODO();}#include "ntoskernel_io_exports.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -