📄 ntoskernel.c
字号:
/* 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); TRACE2("%p, %d, %p", hdr, hdr->ref_count, object); return ret;}int dereference_object(void *object){ struct common_object_header *hdr; int ref_count; ENTER2("object: %p", object); hdr = OBJECT_TO_HEADER(object); TRACE2("hdr: %p", hdr); ref_count = post_atomic_add(hdr->ref_count, -1); TRACE2("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){ TRACE2("%p", 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; EXIT2(return STATUS_SUCCESS); } } nt_spin_unlock_irql(&ntoskernel_lock, irql); if (RtlUnicodeStringToAnsiString(&ansi, obj_attr->name, TRUE) != STATUS_SUCCESS) EXIT2(return STATUS_INSUFFICIENT_RESOURCES); file_basename = strrchr(ansi.buf, '\\'); if (file_basename) file_basename++; else file_basename = ansi.buf; TRACE2("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; EXIT2(return STATUS_FAILURE); } coh = OBJECT_TO_HEADER(fo); bin_file = get_bin_file(file_basename); if (bin_file) { TRACE2("%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; RtlFreeAnsiString(&ansi); if (!bin_file) { iosb->status = FILE_DOES_NOT_EXIST; iosb->info = 0; free_object(fo); EXIT2(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; TRACE2("handle: %p", *handle); status = STATUS_SUCCESS; EXIT2(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; TRACE2("%p", handle); coh = handle; if (coh->type != OBJECT_TYPE_FILE) { ERROR("handle %p is invalid: %d", handle, coh->type); EXIT2(return STATUS_FAILURE); } fo = HANDLE_TO_OBJECT(coh); file = fo->wrap_bin_file; TRACE2("file: %s (%zu)", 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); TRACE2("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; EXIT2(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(ZwWriteFile,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; struct wrap_bin_file *file; unsigned long offset; KIRQL irql; TRACE2("%p", handle); coh = handle; if (coh->type != OBJECT_TYPE_FILE) { ERROR("handle %p is invalid: %d", handle, coh->type); EXIT2(return STATUS_FAILURE); } fo = HANDLE_TO_OBJECT(coh); file = fo->wrap_bin_file; TRACE2("file: %zu, %u", file->size, length); irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL); if (byte_offset) offset = *byte_offset; else offset = fo->current_byte_offset; if (length + offset > file->size) { WARNING("%lu, %u", length + offset, (unsigned int)file->size); /* TODO: implement writing past end of current size */ iosb->status = STATUS_FAILURE; iosb->info = 0; } else { memcpy(file->data + offset, buffer, length); iosb->status = STATUS_SUCCESS; iosb->info = length; fo->current_byte_offset = offset + length; } nt_spin_unlock_irql(&ntoskernel_lock, irql); EXIT2(return iosb->status);}wstdcall NTSTATUS WIN_FUNC(ZwClose,1) (void *handle){ struct common_object_header *coh; TRACE2("%p", handle); if (handle == NULL) { TRACE1(""); EXIT2(return STATUS_SUCCESS); } coh = handle; if (coh->type == OBJECT_TYPE_FILE) { struct file_object *fo; struct wrap_bin_file *bin_file; typeof(fo->flags) flags; fo = HANDLE_TO_OBJECT(handle); flags = fo->flags; bin_file = fo->wrap_bin_file; if (dereference_object(fo)) { if (flags == FILE_CREATED) { vfree(bin_file->data); kfree(bin_file); } else free_bin_file(bin_file); } } else if (coh->type == OBJECT_TYPE_NT_THREAD) { struct nt_thread *thread = HANDLE_TO_OBJECT(handle); TRACE2("thread: %p (%p)", thread, handle); ObDereferenceObject(thread); } else { /* TODO: can we just dereference object here? */ WARNING("closing handle 0x%x not implemented", coh->type); } EXIT2(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(ZwQueryInformationFile,5) (void *handle, struct io_status_block *iosb, void *info, ULONG length, enum file_info_class class){ struct file_object *fo; struct file_name_info *fni; struct file_std_info *fsi; struct wrap_bin_file *file; struct common_object_header *coh; ENTER2("%p", handle); coh = handle; if (coh->type != OBJECT_TYPE_FILE) { ERROR("handle %p is invalid: %d", coh, coh->type); EXIT2(return STATUS_FAILURE); } fo = HANDLE_TO_OBJECT(handle); TRACE2("fo: %p, %d", fo, class); switch (class) { case FileNameInformation: fni = info; fni->length = min(length, (typeof(length))coh->name.length); memcpy(fni->name, coh->name.buf, fni->length); iosb->status = STATUS_SUCCESS; iosb->info = fni->length; break; case FileStandardInformation: fsi = info; file = fo->wrap_bin_file; fsi->alloc_size = file->size; fsi->eof = file->size; fsi->num_links = 1; fsi->delete_pending = FALSE; fsi->dir = FALSE; iosb->status = STATUS_SUCCESS; iosb->info = 0; break; default: WARNING("type %d not implemented yet", class); iosb->status = STATUS_FAILURE; iosb->info = 0; break; } EXIT2(return iosb->status);}wstdcall NTSTATUS WIN_FUNC(ZwCreateKey,7) (void **handle, ACCESS_MASK desired_access, struct object_attr *attr, ULONG title_index, struct unicode_string *class, ULONG create_options, ULONG *disposition){ struct ansi_string ansi; if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) == STATUS_SUCCESS) { TRACE1("key: %s", ansi.buf); RtlFreeAnsiString(&ansi); } *handle = NULL; return STATUS_SUCCESS;}wstdcall NTSTATUS WIN_FUNC(ZwOpenKey,3) (void **handle, ACCESS_MASK desired_access, struct object_attr *attr){ struct ansi_string ansi; if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) == STATUS_SUCCESS) { TRACE1("key: %s", ansi.buf); RtlFreeAnsiString(&ansi); } *handle = NULL; return STATUS_SUCCESS;}wstdcall NTSTATUS WIN_FUNC(ZwSetValueKey,6) (void *handle, struct unicode_string *name, ULONG title_index, ULONG type, void *data, ULONG data_size){ struct ansi_string ansi; if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) == STATUS_SUCCESS) { TRACE1("key: %s", ansi.buf); RtlFreeAnsiString(&ansi); } return STATUS_SUCCESS;}wstdcall NTSTATUS WIN_FUNC(ZwQueryValueKey,6) (void *handle, struct unicode_string *name, enum key_value_information_class class, void *info, ULONG length, ULONG *res_length){ struct ansi_string ansi; if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) == STATUS_SUCCESS) { TRACE1("key: %s", ansi.buf); RtlFreeAnsiString(&ansi); } TODO(); return STATUS_INVALID_PARAMETER;}wstdcall NTSTATUS WIN_FUNC(ZwDeleteKey,1) (void *handle){ ENTER2("%p", handle); return STATUS_SUCCESS;}wstdcall NTSTATUS WIN_FUNC(WmiSystemControl,4) (struct wmilib_context *info, struct device_object *dev_obj, struct irp *irp, void *irp_disposition){ TODO(); return STATUS_SUCCESS;}wstdcall NTSTATUS WIN_FUNC(WmiCompleteRequest,5) (struct device_object *dev_obj, struct irp *irp, NTSTATUS status, ULONG buffer_used, CCHAR priority_boost){ TODO(); return STATUS_SUCCESS;}noregparm NTSTATUS WIN_FUNC(WmiTraceMessage,12) (void *tracehandle, ULONG message_flags, void *message_guid, USHORT message_no, ...){ TODO(); EXIT2(return STATUS_SUCCESS);}wstdcall NTSTATUS WIN_FUNC(WmiQueryTraceInformation,4) (enum trace_information_class trace_info_class, void *trace_info, ULONG *req_length, void *buf){ TODO(); EXIT2(return STATUS_SUCCESS);}/* this function can't be wstdcall as it takes variable number of args */noregparm ULONG WIN_FUNC(DbgPrint,12) (char *format, ...){#ifdef DEBUG va_list args; static char buf[100]; va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); printk(KERN_DEBUG "%s (%s): %s", DRIVER_NAME, __FUNCTION__, buf); va_end(args);#endif return STATUS_SUCCESS;}wstdcall void WIN_FUNC(KeBugCheckEx,5) (ULONG code, ULONG_PTR param1, ULONG_PTR param2, ULONG_PTR param3, ULONG_PTR param4){ TODO(); return;}wstdcall void WIN_FUNC(ExSystemTimeToLocalTime,2) (LARGE_INTEGER *system_time, LARGE_INTEGER *local_time){ *local_time = *system_time;}wstdcall ULONG WIN_FUNC(ExSetTimerResolution,2) (ULONG time, BOOLEAN set){ /* why a driver should change system wide timer resolution is * beyond me */ return time;}wstdcall void WIN_FUNC(DbgBreakPoint,0) (void){ TODO();}wstdcall void WIN_FUNC(_except_handler3,0) (void){ TODO();}wstdcall void WIN_FUNC(__C_specific_handler,0) (void){ TODO();}void WIN_FUNC(_purecall,0) (void){ TODO();}#include "ntoskernel_exports.h"int ntoskernel_init(void){ struct timeval now; nt_spin_lock_init(&dispatcher_lock); nt_spin_lock_init(&ntoskernel_lock); nt_spin_lock_init(&ntos_work_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_list); initialize_work(&kdpc_work, kdpc_worker, NULL); initialize_work(&ntos_work, ntos_work_worker, NULL); nt_spin_lock_init(&timer_lock); InitializeListHead(&wrap_timer_list); do_gettimeofday(&now); wrap_ticks_to_boot = TICKS_1601_TO_1970; wrap_ticks_to_boot += (u64)now.tv_sec * TICKSPERSEC; wrap_ticks_to_boot += now.tv_usec * 10; wrap_ticks_to_boot -= jiffies * TICKSPERJIFFY; TRACE2("%Lu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -