📄 ntoskernel.c
字号:
TRACEEXIT2(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(PsTerminateSystemThread,1) (NTSTATUS status){ struct nt_thread *thread; DBGTRACE2("%p, %08X", current, status); thread = get_current_nt_thread(); if (thread) { DBGTRACE2("setting event for thread: %p", thread); KeSetEvent((struct nt_event *)&thread->dh, 0, FALSE); DBGTRACE2("set event for thread: %p", thread); remove_nt_thread(thread); complete_and_exit(NULL, status); ERROR("oops: %p, %d", thread->task, thread->pid); } else ERROR("couldn't find thread for task: %p", current); return STATUS_FAILURE;}wstdcall BOOLEAN WIN_FUNC(KeRemoveEntryDeviceQueue,2) (struct kdevice_queue *dev_queue, struct kdevice_queue_entry *entry){ struct kdevice_queue_entry *e; KIRQL irql; irql = nt_spin_lock_irql(&dev_queue->lock, DISPATCH_LEVEL); nt_list_for_each_entry(e, &dev_queue->list, list) { if (e == entry) { RemoveEntryList(&e->list); nt_spin_unlock_irql(&dev_queue->lock, irql); return TRUE; } } nt_spin_unlock_irql(&dev_queue->lock, irql); return FALSE;}wstdcall BOOLEAN WIN_FUNC(KeSynchronizeExecution,3) (struct kinterrupt *interrupt, PKSYNCHRONIZE_ROUTINE synch_routine, void *synch_context){ NT_SPIN_LOCK *spinlock; BOOLEAN ret; unsigned long flags; if (interrupt->actual_lock) spinlock = interrupt->actual_lock; else spinlock = &interrupt->lock; nt_spin_lock_irqsave(spinlock, flags); ret = synch_routine(synch_context); nt_spin_unlock_irqrestore(spinlock, flags); return ret;}wstdcall void *WIN_FUNC(MmAllocateContiguousMemorySpecifyCache,5) (SIZE_T size, PHYSICAL_ADDRESS lowest, PHYSICAL_ADDRESS highest, PHYSICAL_ADDRESS boundary, enum memory_caching_type cache_type){ void *addr; size_t page_length = ((size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; DBGTRACE2("%lu, %u, %Lu, %Lu, %Lu, %d", size, page_length, lowest, highest, boundary, cache_type); addr = ExAllocatePoolWithTag(NonPagedPool, page_length, 0); DBGTRACE2("%p", addr); return addr;}wstdcall void WIN_FUNC(MmFreeContiguousMemorySpecifyCache,3) (void *base, SIZE_T size, enum memory_caching_type cache_type){ DBGTRACE2("%p", base); ExFreePool(base);}wstdcall PHYSICAL_ADDRESS WIN_FUNC(MmGetPhysicalAddress,1) (void *base){ DBGTRACE2("%p", base); return virt_to_phys(base);}/* Atheros card with pciid 168C:0014 calls this function with 0xf0000 * and 0xf6ef0 address, and then check for things that seem to be * related to ACPI: "_SM_" and "_DMI_". This may be the hack they do * to check if this card is installed in IBM thinkpads; we can * probably get this device to work if we create a buffer with the * strings as required by the driver and return virtual address for * that address instead */wstdcall void *WIN_FUNC(MmMapIoSpace,3) (PHYSICAL_ADDRESS phys_addr, SIZE_T size, enum memory_caching_type cache){ void *virt; TRACEENTER1("cache type: %d", cache); if (cache == MmCached) virt = ioremap(phys_addr, size); else virt = ioremap_nocache(phys_addr, size); DBGTRACE1("%Lx, %lu, %p", phys_addr, size, virt); return virt;}wstdcall void WIN_FUNC(MmUnmapIoSpace,2) (void *addr, SIZE_T size){ TRACEENTER1("%p, %lu", addr, size); iounmap(addr); return;}wstdcall ULONG WIN_FUNC(MmSizeOfMdl,2) (void *base, ULONG length){ return (sizeof(struct mdl) + (sizeof(PFN_NUMBER) * SPAN_PAGES(base, length)));}struct mdl *allocate_init_mdl(void *virt, ULONG length){ struct wrap_mdl *wrap_mdl; struct mdl *mdl; int mdl_size = MmSizeOfMdl(virt, length); KIRQL irql; if (mdl_size <= CACHE_MDL_SIZE) { wrap_mdl = kmem_cache_alloc(mdl_cache, gfp_irql()); if (!wrap_mdl) return NULL; irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); InsertHeadList(&wrap_mdl_list, &wrap_mdl->list); nt_spin_unlock_irql(&ntoskernel_lock, irql); mdl = wrap_mdl->mdl; DBGTRACE3("allocated mdl from cache: %p(%p), %p(%d)", wrap_mdl, mdl, virt, length); memset(mdl, 0, CACHE_MDL_SIZE); MmInitializeMdl(mdl, virt, length); /* mark the MDL as allocated from cache pool so when * it is freed, we free it back to the pool */ mdl->flags = MDL_CACHE_ALLOCATED; } else { wrap_mdl = kmalloc(sizeof(*wrap_mdl) + mdl_size, gfp_irql()); if (!wrap_mdl) return NULL; mdl = wrap_mdl->mdl; DBGTRACE3("allocated mdl from memory: %p(%p), %p(%d)", wrap_mdl, mdl, virt, length); irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); InsertHeadList(&wrap_mdl_list, &wrap_mdl->list); nt_spin_unlock_irql(&ntoskernel_lock, irql); memset(mdl, 0, mdl_size); MmInitializeMdl(mdl, virt, length); } return mdl;}void free_mdl(struct mdl *mdl){ KIRQL irql; /* A driver may allocate Mdl with NdisAllocateBuffer and free * with IoFreeMdl (e.g., 64-bit Broadcom). Since we need to * treat buffers allocated with Ndis calls differently, we * must call NdisFreeBuffer if it is allocated with Ndis * function. We set 'pool' field in Ndis functions. */ if (!mdl) return; if (mdl->pool) NdisFreeBuffer(mdl); else { struct wrap_mdl *wrap_mdl = (struct wrap_mdl *) ((char *)mdl - offsetof(struct wrap_mdl, mdl)); irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); RemoveEntryList(&wrap_mdl->list); nt_spin_unlock_irql(&ntoskernel_lock, irql); if (mdl->flags & MDL_CACHE_ALLOCATED) { DBGTRACE3("freeing mdl cache: %p, %p, %p", wrap_mdl, mdl, mdl->mappedsystemva); kmem_cache_free(mdl_cache, wrap_mdl); } else { DBGTRACE3("freeing mdl: %p, %p, %p", wrap_mdl, mdl, mdl->mappedsystemva); kfree(wrap_mdl); } } return;}wstdcall void WIN_FUNC(IoBuildPartialMdl,4) (struct mdl *source, struct mdl *target, void *virt, ULONG length){ MmInitializeMdl(target, virt, length); target->flags |= MDL_PARTIAL;}wstdcall void WIN_FUNC(MmBuildMdlForNonPagedPool,1) (struct mdl *mdl){ PFN_NUMBER *mdl_pages; int i, n; TRACEENTER4("%p", mdl); /* already mapped */// mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl); mdl->flags |= MDL_SOURCE_IS_NONPAGED_POOL; DBGTRACE4("%p, %p, %p, %d, %d", mdl, mdl->mappedsystemva, mdl->startva, mdl->byteoffset, mdl->bytecount); n = SPAN_PAGES(MmGetSystemAddressForMdl(mdl), MmGetMdlByteCount(mdl)); if (n > CACHE_MDL_PAGES) WARNING("%p, %d, %d", MmGetSystemAddressForMdl(mdl), MmGetMdlByteCount(mdl), n); mdl_pages = MmGetMdlPfnArray(mdl); for (i = 0; i < n; i++) mdl_pages[i] = (ULONG_PTR)mdl->startva + (i * PAGE_SIZE); TRACEEXIT4(return);}wstdcall void *WIN_FUNC(MmMapLockedPages,2) (struct mdl *mdl, KPROCESSOR_MODE access_mode){ /* already mapped */// mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl); mdl->flags |= MDL_MAPPED_TO_SYSTEM_VA; /* what is the need for MDL_PARTIAL_HAS_BEEN_MAPPED? */ if (mdl->flags & MDL_PARTIAL) mdl->flags |= MDL_PARTIAL_HAS_BEEN_MAPPED; return mdl->mappedsystemva;}wstdcall void *WIN_FUNC(MmMapLockedPagesSpecifyCache,6) (struct mdl *mdl, KPROCESSOR_MODE access_mode, enum memory_caching_type cache_type, void *base_address, ULONG bug_check, enum mm_page_priority priority){ return MmMapLockedPages(mdl, access_mode);}wstdcall void WIN_FUNC(MmUnmapLockedPages,2) (void *base, struct mdl *mdl){ mdl->flags &= ~MDL_MAPPED_TO_SYSTEM_VA; return;}wstdcall void WIN_FUNC(MmProbeAndLockPages,3) (struct mdl *mdl, KPROCESSOR_MODE access_mode, enum lock_operation operation){ /* already locked */ mdl->flags |= MDL_PAGES_LOCKED; return;}wstdcall void WIN_FUNC(MmUnlockPages,1) (struct mdl *mdl){ mdl->flags &= ~MDL_PAGES_LOCKED; return;}wstdcall BOOLEAN WIN_FUNC(MmIsAddressValid,1) (void *virt_addr){ if (virt_addr_valid(virt_addr)) return TRUE; else return FALSE;}wstdcall void *WIN_FUNC(MmLockPagableDataSection,1) (void *address){ return address;}wstdcall void WIN_FUNC(MmUnlockPagableImageSection,1) (void *handle){ return;}wstdcall NTSTATUS WIN_FUNC(ObReferenceObjectByHandle,6) (void *handle, ACCESS_MASK desired_access, void *obj_type, KPROCESSOR_MODE access_mode, void **object, void *handle_info){ struct common_object_header *hdr; DBGTRACE2("%p", handle); hdr = HANDLE_TO_HEADER(handle); atomic_inc_var(hdr->ref_count); *object = HEADER_TO_OBJECT(hdr); DBGTRACE2("%p, %p, %d, %p", hdr, object, hdr->ref_count, *object); return STATUS_SUCCESS;}/* DDK doesn't say if return value should be before incrementing or * after incrementing reference count, but according to #reactos * devels, it should be return value after incrementing */wfastcall LONG WIN_FUNC(ObfReferenceObject,1) (void *object){ struct common_object_header *hdr; LONG ret; hdr = OBJECT_TO_HEADER(object); ret = post_atomic_add(hdr->ref_count, 1); DBGTRACE2("%p, %d, %p", hdr, hdr->ref_count, object); return ret;}int dereference_object(void *object){ struct common_object_header *hdr; int ref_count; TRACEENTER2("object: %p", object); hdr = OBJECT_TO_HEADER(object); DBGTRACE2("hdr: %p", hdr); ref_count = post_atomic_add(hdr->ref_count, -1); DBGTRACE2("object: %p, %d", object, ref_count); if (ref_count < 0) ERROR("invalid object: %p (%d)", object, ref_count); if (ref_count <= 0) { free_object(object); return 1; } else return 0;}wfastcall void WIN_FUNC(ObfDereferenceObject,1) (void *object){ dereference_object(object);}wstdcall NTSTATUS WIN_FUNC(ZwCreateFile,11) (void **handle, ACCESS_MASK access_mask, struct object_attr *obj_attr, struct io_status_block *iosb, LARGE_INTEGER *size, ULONG file_attr, ULONG share_access, ULONG create_disposition, ULONG create_options, void *ea_buffer, ULONG ea_length){ struct common_object_header *coh; struct file_object *fo; struct ansi_string ansi; struct wrap_bin_file *bin_file; char *file_basename; KIRQL irql; NTSTATUS status; irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); nt_list_for_each_entry(coh, &object_list, list) { if (coh->type != OBJECT_TYPE_FILE) continue; /* TODO: check if file is opened in shared mode */ if (!RtlCompareUnicodeString(&coh->name, obj_attr->name, TRUE)) { fo = HEADER_TO_OBJECT(coh); bin_file = fo->wrap_bin_file; *handle = coh; nt_spin_unlock_irql(&ntoskernel_lock, irql); ObReferenceObject(fo); iosb->status = FILE_OPENED; iosb->info = bin_file->size; TRACEEXIT2(return STATUS_SUCCESS); } } nt_spin_unlock_irql(&ntoskernel_lock, irql); if (RtlUnicodeStringToAnsiString(&ansi, obj_attr->name, TRUE) != STATUS_SUCCESS) TRACEEXIT2(return STATUS_INSUFFICIENT_RESOURCES); file_basename = strrchr(ansi.buf, '\\'); if (file_basename) file_basename++; else file_basename = ansi.buf; DBGTRACE2("file: '%s', '%s'", ansi.buf, file_basename); fo = allocate_object(sizeof(struct file_object), OBJECT_TYPE_FILE, obj_attr->name); if (!fo) { RtlFreeAnsiString(&ansi); iosb->status = STATUS_INSUFFICIENT_RESOURCES; iosb->info = 0; TRACEEXIT2(return STATUS_FAILURE); } coh = OBJECT_TO_HEADER(fo); bin_file = get_bin_file(file_basename); if (bin_file) { DBGTRACE2("%s, %s", bin_file->name, file_basename); fo->flags = FILE_OPENED; } else if (access_mask & FILE_WRITE_DATA) { bin_file = kmalloc(sizeof(*bin_file), GFP_KERNEL); if (bin_file) { memset(bin_file, 0, sizeof(*bin_file)); strncpy(bin_file->name, file_basename, sizeof(bin_file->name)); bin_file->name[sizeof(bin_file->name)-1] = 0; bin_file->data = vmalloc(*size); if (bin_file->data) { memset(bin_file->data, 0, *size); bin_file->size = *size; fo->flags = FILE_CREATED; } else { kfree(bin_file); bin_file = NULL; } } } else bin_file = NULL; if (!bin_file) { iosb->status = FILE_DOES_NOT_EXIST; iosb->info = 0; RtlFreeAnsiString(&ansi); free_object(fo); TRACEEXIT2(return STATUS_FAILURE); } fo->wrap_bin_file = bin_file; fo->current_byte_offset = 0; if (access_mask & FILE_READ_DATA) fo->read_access = TRUE; if (access_mask & FILE_WRITE_DATA) fo->write_access = TRUE; iosb->status = FILE_OPENED; iosb->info = bin_file->size; *handle = coh; DBGTRACE2("handle: %p", *handle); status = STATUS_SUCCESS; RtlFreeAnsiString(&ansi); TRACEEXIT2(return status);}wstdcall NTSTATUS WIN_FUNC(ZwReadFile,9) (void *handle, struct nt_event *event, void *apc_routine, void *apc_context, struct io_status_block *iosb, void *buffer, ULONG length, LARGE_INTEGER *byte_offset, ULONG *key){ struct file_object *fo; struct common_object_header *coh; ULONG count; size_t offset; struct wrap_bin_file *file; KIRQL irql; DBGTRACE2("%p", handle); coh = handle; if (coh->type != OBJECT_TYPE_FILE) { ERROR("handle %p is invalid: %d", handle, coh->type); TRACEEXIT2(return STATUS_FAILURE); } fo = HANDLE_TO_OBJECT(coh); file = fo->wrap_bin_file; DBGTRACE2("file: %s (%u)", file->name, file->size); irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); if (byte_offset) offset = *byte_offset; else offset = fo->current_byte_offset; count = min((size_t)length, file->size - offset); DBGTRACE2("count: %u, offset: %zu, length: %u", count, offset, length); memcpy(buffer, ((void *)file->data) + offset, count); fo->current_byte_offset = offset + count; nt_spin_unlock_irql(&ntoskernel_lock, irql); iosb->status = STATUS_SUCCESS; iosb->info = count; TRACEEXIT2(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(ZwWriteFile,9) (void *handle, struct nt_event *event, void *apc_routine,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -