/*- * Copyright (c) 2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: head/sys/compat/ndis/ntoskrnl_var.h 140827 2005-01-25 17:00:54Z wpaul $ */ #ifndef _NTOSKRNL_VAR_H_ #define _NTOSKRNL_VAR_H_ /* * us_buf is really a wchar_t *, but it's inconvenient to include * all the necessary header goop needed to define it, and it's a * pointer anyway, so for now, just make it a uint16_t *. */ struct unicode_string { uint16_t us_len; uint16_t us_maxlen; uint16_t *us_buf; }; typedef struct unicode_string unicode_string; /* * Windows memory descriptor list. In Windows, it's possible for * buffers to be passed between user and kernel contexts without * copying. Buffers may also be allocated in either paged or * non-paged memory regions. An MDL describes the pages of memory * used to contain a particular buffer. Note that a single MDL * may describe a buffer that spans multiple pages. An array of * page addresses appears immediately after the MDL structure itself. * MDLs are therefore implicitly variably sized, even though they * don't look it. * * Note that in FreeBSD, we can take many shortcuts in the way * we handle MDLs because: * * - We are only concerned with pages in kernel context. This means * we will only ever use the kernel's memory map, and remapping * of buffers is never needed. * * - Kernel pages can never be paged out, so we don't have to worry * about whether or not a page is actually mapped before going to * touch it. */ struct mdl { struct mdl *mdl_next; uint16_t mdl_size; uint16_t mdl_flags; void *mdl_process; void *mdl_mappedsystemva; void *mdl_startva; uint32_t mdl_bytecount; uint32_t mdl_byteoffset; }; typedef struct mdl mdl, ndis_buffer; /* MDL flags */ #define MDL_MAPPED_TO_SYSTEM_VA 0x0001 #define MDL_PAGES_LOCKED 0x0002 #define MDL_SOURCE_IS_NONPAGED_POOL 0x0004 #define MDL_ALLOCATED_FIXED_SIZE 0x0008 #define MDL_PARTIAL 0x0010 #define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020 #define MDL_IO_PAGE_READ 0x0040 #define MDL_WRITE_OPERATION 0x0080 #define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100 #define MDL_FREE_EXTRA_PTES 0x0200 #define MDL_IO_SPACE 0x0800 #define MDL_NETWORK_HEADER 0x1000 #define MDL_MAPPING_CAN_FAIL 0x2000 #define MDL_ALLOCATED_MUST_SUCCEED 0x4000 /* Note: assumes x86 page size of 4K. */ #if PAGE_SIZE == 4096 #define PAGE_SHIFT 12 #elif PAGE_SIZE == 8192 #define PAGE_SHIFT 13 #else #error PAGE_SHIFT undefined! #endif #define SPAN_PAGES(ptr, len) \ ((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) + \ (len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)) #define PAGE_ALIGN(ptr) \ ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1))) #define BYTE_OFFSET(ptr) \ ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1))) #define MDL_PAGES(m) (vm_offset_t *)(m + 1) #define MmInitializeMdl(b, baseva, len) \ (b)->mdl_next = NULL; \ (b)->mdl_size = (uint16_t)(sizeof(mdl) + \ (sizeof(uint32_t) * SPAN_PAGES((baseva), (len)))); \ (b)->mdl_flags = 0; \ (b)->mdl_startva = (void *)PAGE_ALIGN((baseva)); \ (b)->mdl_byteoffset = BYTE_OFFSET((baseva)); \ (b)->mdl_bytecount = (uint32_t)(len); #define MmGetMdlByteOffset(mdl) ((mdl)->mdl_byteoffset) #define MmGetMdlByteCount(mdl) ((mdl)->mdl_bytecount) #define MmGetMdlVirtualAddress(mdl) \ ((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset)) #define MmGetMdlStartVa(mdl) ((mdl)->mdl_startva) #define MmGetMdlPfnArray(mdl) MDL_PAGES(mdl) #define WDM_MAJOR 1 #define WDM_MINOR_WIN98 0x00 #define WDM_MINOR_WINME 0x05 #define WDM_MINOR_WIN2000 0x10 #define WDM_MINOR_WINXP 0x20 #define WDM_MINOR_WIN2003 0x30 /*- * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows. * According to the Windows DDK header files, KSPIN_LOCK is defined like this: * typedef ULONG_PTR KSPIN_LOCK; * * From basetsd.h (SDK, Feb. 2003): * typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR; * typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; * typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR; * * The keyword __int3264 specifies an integral type that has the following * properties: * + It is 32-bit on 32-bit platforms * + It is 64-bit on 64-bit platforms * + It is 32-bit on the wire for backward compatibility. * It gets truncated on the sending side and extended appropriately * (signed or unsigned) on the receiving side. * * Thus register_t seems the proper mapping onto FreeBSD for spin locks. */ typedef register_t kspin_lock; struct slist_entry { struct slist_entry *sl_next; }; typedef struct slist_entry slist_entry; union slist_header { uint64_t slh_align; struct { struct slist_entry *slh_next; uint16_t slh_depth; uint16_t slh_seq; } slh_list; }; typedef union slist_header slist_header; struct list_entry { struct list_entry *nle_flink; struct list_entry *nle_blink; }; typedef struct list_entry list_entry; #define INIT_LIST_HEAD(l) \ l->nle_flink = l->nle_blink = l #define REMOVE_LIST_ENTRY(e) \ do { \ list_entry *b; \ list_entry *f; \ \ f = e->nle_flink; \ b = e->nle_blink; \ b->nle_flink = f; \ f->nle_blink = b; \ } while (0) #define REMOVE_LIST_HEAD(l) \ do { \ list_entry *f; \ list_entry *e; \ \ e = l->nle_flink; \ f = e->nle_flink; \ l->nle_flink = f; \ f->nle_blink = l; \ } while (0) #define REMOVE_LIST_TAIL(l) \ do { \ list_entry *b; \ list_entry *e; \ \ e = l->nle_blink; \ b = e->nle_blink; \ l->nle_blink = b; \ b->nle_flink = l; \ } while (0) #define INSERT_LIST_TAIL(l, e) \ do { \ list_entry *b; \ \ b = l->nle_blink; \ e->nle_flink = l; \ e->nle_blink = b; \ b->nle_flink = e; \ l->nle_blink = e; \ } while (0) #define INSERT_LIST_HEAD(l, e) \ do { \ list_entry *f; \ \ f = l->nle_flink; \ e->nle_flink = f; \ e->nle_blink = l; \ f->nle_blink = e; \ l->nle_flink = e; \ } while (0) struct nt_dispatch_header { uint8_t dh_type; uint8_t dh_abs; uint8_t dh_size; uint8_t dh_inserted; uint32_t dh_sigstate; list_entry dh_waitlisthead; }; typedef struct nt_dispatch_header nt_dispatch_header; #define OTYPE_EVENT 0 #define OTYPE_MUTEX 1 #define OTYPE_THREAD 2 #define OTYPE_TIMER 3 /* Windows dispatcher levels. */ #define PASSIVE_LEVEL 0 #define LOW_LEVEL 0 #define APC_LEVEL 1 #define DISPATCH_LEVEL 2 #define DEVICE_LEVEL (DISPATCH_LEVEL + 1) #define PROFILE_LEVEL 27 #define CLOCK1_LEVEL 28 #define CLOCK2_LEVEL 28 #define IPI_LEVEL 29 #define POWER_LEVEL 30 #define HIGH_LEVEL 31 #define SYNC_LEVEL_UP DISPATCH_LEVEL #define SYNC_LEVEL_MP (IPI_LEVEL - 1) #define AT_PASSIVE_LEVEL(td) \ ((td)->td_proc->p_flag & P_KTHREAD == FALSE) #define AT_DISPATCH_LEVEL(td) \ ((td)->td_base_pri == PI_REALTIME) #define AT_DIRQL_LEVEL(td) \ ((td)->td_priority <= PI_NET) #define AT_HIGH_LEVEL(td) \ ((td)->td_critnest != 0) struct nt_objref { nt_dispatch_header no_dh; void *no_obj; TAILQ_ENTRY(nt_objref) link; }; TAILQ_HEAD(nt_objref_head, nt_objref); typedef struct nt_objref nt_objref; #define EVENT_TYPE_NOTIFY 0 #define EVENT_TYPE_SYNC 1 /* * We need to use the timeout()/untimeout() API for ktimers * since timers can be initialized, but not destroyed (so * malloc()ing our own callout structures would mean a leak, * since there'd be no way to free() them). This means we * need to use struct callout_handle, which is really just a * pointer. To make it easier to deal with, we use a union * to overlay the callout_handle over the k_timerlistentry. * The latter is a list_entry, which is two pointers, so * there's enough space available to hide a callout_handle * there. */ struct ktimer { nt_dispatch_header k_header; uint64_t k_duetime; union { list_entry k_timerlistentry; struct callout_handle k_handle; } u; void *k_dpc; uint32_t k_period; }; #define k_timerlistentry u.k_timerlistentry #define k_handle u.k_handle typedef struct ktimer ktimer; struct nt_kevent { nt_dispatch_header k_header; }; typedef struct nt_kevent nt_kevent; /* Kernel defered procedure call (i.e. timer callback) */ struct kdpc; typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *); struct kdpc { uint16_t k_type; uint8_t k_num; uint8_t k_importance; list_entry k_dpclistentry; void *k_deferedfunc; void *k_deferredctx; void *k_sysarg1; void *k_sysarg2; register_t k_lock; }; typedef struct kdpc kdpc; /* * Note: the acquisition count is BSD-specific. The Microsoft * documentation says that mutexes can be acquired recursively * by a given thread, but that you must release the mutex as * many times as you acquired it before it will be set to the * signalled state (i.e. before any other threads waiting on * the object will be woken up). However the Windows KMUTANT * structure has no field for keeping track of the number of * acquisitions, so we need to add one ourselves. As long as * driver code treats the mutex as opaque, we should be ok. */ struct kmutant { nt_dispatch_header km_header; union { list_entry km_listentry; uint32_t km_acquirecnt; } u; void *km_ownerthread; uint8_t km_abandoned; uint8_t km_apcdisable; }; #define km_listentry u.km_listentry #define km_acquirecnt u.km_acquirecnt typedef struct kmutant kmutant; #define LOOKASIDE_DEPTH 256 struct general_lookaside { slist_header gl_listhead; uint16_t gl_depth; uint16_t gl_maxdepth; uint32_t gl_totallocs; union { uint32_t gl_allocmisses; uint32_t gl_allochits; } u_a; uint32_t gl_totalfrees; union { uint32_t gl_freemisses; uint32_t gl_freehits; } u_m; uint32_t gl_type; uint32_t gl_tag; uint32_t gl_size; void *gl_allocfunc; void *gl_freefunc; list_entry gl_listent; uint32_t gl_lasttotallocs; union { uint32_t gl_lastallocmisses; uint32_t gl_lastallochits; } u_l; uint32_t gl_rsvd[2]; }; typedef struct general_lookaside general_lookaside; struct npaged_lookaside_list { general_lookaside nll_l; kspin_lock nll_obsoletelock; }; typedef struct npaged_lookaside_list npaged_lookaside_list; typedef struct npaged_lookaside_list paged_lookaside_list; typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t); typedef void (*lookaside_free_func)(void *); struct irp; struct kdevice_qentry { list_entry kqe_devlistent; uint32_t kqe_sortkey; uint8_t kqe_inserted; }; typedef struct kdevice_qentry kdevice_qentry; struct kdevice_queue { uint16_t kq_type; uint16_t kq_size; list_entry kq_devlisthead; kspin_lock kq_lock; uint8_t kq_busy; }; typedef struct kdevice_queue kdevice_queue; struct wait_ctx_block { kdevice_qentry wcb_waitqueue; void *wcb_devfunc; void *wcb_devctx; uint32_t wcb_mapregcnt; void *wcb_devobj; void *wcb_curirp; void *wcb_bufchaindpc; }; typedef struct wait_ctx_block wait_ctx_block; struct wait_block { list_entry wb_waitlist; void *wb_kthread; nt_dispatch_header *wb_object; struct wait_block *wb_next; uint16_t wb_waitkey; uint16_t wb_waittype; }; typedef struct wait_block wait_block; #define THREAD_WAIT_OBJECTS 3 #define MAX_WAIT_OBJECTS 64 #define WAITTYPE_ALL 0 #define WAITTYPE_ANY 1 struct thread_context { void *tc_thrctx; void *tc_thrfunc; }; typedef struct thread_context thread_context; /* Forward declaration */ struct driver_object; struct devobj_extension; struct driver_extension { struct driver_object *dre_driverobj; void *dre_adddevicefunc; uint32_t dre_reinitcnt; unicode_string dre_srvname; }; typedef struct driver_extension driver_extension; /* * In Windows, there are Physical Device Objects (PDOs) and * Functional Device Objects (FDOs). Physical Device Objects are * created and maintained by bus drivers. For example, the PCI * bus driver might detect two PCI ethernet cards on a given * bus. The PCI bus driver will then allocate two device_objects * for its own internal bookeeping purposes. This is analagous * to the device_t that the FreeBSD PCI code allocates and passes * into each PCI driver's probe and attach routines. * * When an ethernet driver claims one of the ethernet cards * on the bus, it will create its own device_object. This is * the Functional Device Object. This object is analagous to the * device-specific softc structure. */ struct device_object { uint16_t do_type; uint16_t do_size; uint32_t do_refcnt; struct device_object *do_drvobj; struct device_object *do_nextdev; struct device_object *do_attacheddev; struct irp *do_currirp; void *do_iotimer; uint32_t do_flags; uint32_t do_characteristics; void *do_vpb; void *do_devext; uint8_t do_stacksize; union { list_entry do_listent; wait_ctx_block do_wcb; } queue; uint32_t do_alignreq; kdevice_queue do_devqueue; struct kdpc do_dpc; uint32_t do_activethreads; void *do_securitydesc; struct nt_kevent do_devlock; uint16_t do_sectorsz; uint16_t do_spare1; struct devobj_extension *do_devobj_ext; void *do_rsvd; }; typedef struct device_object device_object; struct devobj_extension { uint16_t dve_type; uint16_t dve_size; device_object *dve_devobj; }; typedef struct devobj_extension devobj_extension; #define IO_NO_INCREMENT 0 #define IO_CD_ROM_INCREMENT 1 #define IO_DISK_INCREMENT 1 #define IO_KEYBOARD_INCREMENT 6 #define IO_MAILSLOT_INCREMENT 2 #define IO_MOUSE_INCREMENT 6 #define IO_NAMED_PIPE_INCREMENT 2 #define IO_NETWORK_INCREMENT 2 #define IO_PARALLEL_INCREMENT 1 #define IO_SERIAL_INCREMENT 2 #define IO_SOUND_INCREMENT 8 #define IO_VIDEO_INCREMENT 1 /* IRP major codes */ #define IRP_MJ_CREATE 0x00 #define IRP_MJ_CREATE_NAMED_PIPE 0x01 #define IRP_MJ_CLOSE 0x02 #define IRP_MJ_READ 0x03 #define IRP_MJ_WRITE 0x04 #define IRP_MJ_QUERY_INFORMATION 0x05 #define IRP_MJ_SET_INFORMATION 0x06 #define IRP_MJ_QUERY_EA 0x07 #define IRP_MJ_SET_EA 0x08 #define IRP_MJ_FLUSH_BUFFERS 0x09 #define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a #define IRP_MJ_SET_VOLUME_INFORMATION 0x0b #define IRP_MJ_DIRECTORY_CONTROL 0x0c #define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d #define IRP_MJ_DEVICE_CONTROL 0x0e #define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f #define IRP_MJ_SHUTDOWN 0x10 #define IRP_MJ_LOCK_CONTROL 0x11 #define IRP_MJ_CLEANUP 0x12 #define IRP_MJ_CREATE_MAILSLOT 0x13 #define IRP_MJ_QUERY_SECURITY 0x14 #define IRP_MJ_SET_SECURITY 0x15 #define IRP_MJ_POWER 0x16 #define IRP_MJ_SYSTEM_CONTROL 0x17 #define IRP_MJ_DEVICE_CHANGE 0x18 #define IRP_MJ_QUERY_QUOTA 0x19 #define IRP_MJ_SET_QUOTA 0x1a #define IRP_MJ_PNP 0x1b #define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete.... #define IRP_MJ_MAXIMUM_FUNCTION 0x1b #define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL /* IRP minor codes */ #define IRP_MN_QUERY_DIRECTORY 0x01 #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 #define IRP_MN_USER_FS_REQUEST 0x00 #define IRP_MN_MOUNT_VOLUME 0x01 #define IRP_MN_VERIFY_VOLUME 0x02 #define IRP_MN_LOAD_FILE_SYSTEM 0x03 #define IRP_MN_TRACK_LINK 0x04 // To be obsoleted soon #define IRP_MN_KERNEL_CALL 0x04 #define IRP_MN_LOCK 0x01 #define IRP_MN_UNLOCK_SINGLE 0x02 #define IRP_MN_UNLOCK_ALL 0x03 #define IRP_MN_UNLOCK_ALL_BY_KEY 0x04 #define IRP_MN_NORMAL 0x00 #define IRP_MN_DPC 0x01 #define IRP_MN_MDL 0x02 #define IRP_MN_COMPLETE 0x04 #define IRP_MN_COMPRESSED 0x08 #define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC) #define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL) #define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC) #define IRP_MN_SCSI_CLASS 0x01 #define IRP_MN_START_DEVICE 0x00 #define IRP_MN_QUERY_REMOVE_DEVICE 0x01 #define IRP_MN_REMOVE_DEVICE 0x02 #define IRP_MN_CANCEL_REMOVE_DEVICE 0x03 #define IRP_MN_STOP_DEVICE 0x04 #define IRP_MN_QUERY_STOP_DEVICE 0x05 #define IRP_MN_CANCEL_STOP_DEVICE 0x06 #define IRP_MN_QUERY_DEVICE_RELATIONS 0x07 #define IRP_MN_QUERY_INTERFACE 0x08 #define IRP_MN_QUERY_CAPABILITIES 0x09 #define IRP_MN_QUERY_RESOURCES 0x0A #define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B #define IRP_MN_QUERY_DEVICE_TEXT 0x0C #define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D #define IRP_MN_READ_CONFIG 0x0F #define IRP_MN_WRITE_CONFIG 0x10 #define IRP_MN_EJECT 0x11 #define IRP_MN_SET_LOCK 0x12 #define IRP_MN_QUERY_ID 0x13 #define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14 #define IRP_MN_QUERY_BUS_INFORMATION 0x15 #define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16 #define IRP_MN_SURPRISE_REMOVAL 0x17 #define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18 #define IRP_MN_WAIT_WAKE 0x00 #define IRP_MN_POWER_SEQUENCE 0x01 #define IRP_MN_SET_POWER 0x02 #define IRP_MN_QUERY_POWER 0x03 #define IRP_MN_QUERY_ALL_DATA 0x00 #define IRP_MN_QUERY_SINGLE_INSTANCE 0x01 #define IRP_MN_CHANGE_SINGLE_INSTANCE 0x02 #define IRP_MN_CHANGE_SINGLE_ITEM 0x03 #define IRP_MN_ENABLE_EVENTS 0x04 #define IRP_MN_DISABLE_EVENTS 0x05 #define IRP_MN_ENABLE_COLLECTION 0x06 #define IRP_MN_DISABLE_COLLECTION 0x07 #define IRP_MN_REGINFO 0x08 #define IRP_MN_EXECUTE_METHOD 0x09 #define IRP_MN_REGINFO_EX 0x0b /* IRP flags */ #define IRP_NOCACHE 0x00000001 #define IRP_PAGING_IO 0x00000002 #define IRP_MOUNT_COMPLETION 0x00000002 #define IRP_SYNCHRONOUS_API 0x00000004 #define IRP_ASSOCIATED_IRP 0x00000008 #define IRP_BUFFERED_IO 0x00000010 #define IRP_DEALLOCATE_BUFFER 0x00000020 #define IRP_INPUT_OPERATION 0x00000040 #define IRP_SYNCHRONOUS_PAGING_IO 0x00000040 #define IRP_CREATE_OPERATION 0x00000080 #define IRP_READ_OPERATION 0x00000100 #define IRP_WRITE_OPERATION 0x00000200 #define IRP_CLOSE_OPERATION 0x00000400 #define IRP_DEFER_IO_COMPLETION 0x00000800 #define IRP_OB_QUERY_NAME 0x00001000 #define IRP_HOLD_DEVICE_QUEUE 0x00002000 #define IRP_RETRY_IO_COMPLETION 0x00004000 #define IRP_CLASS_CACHE_OPERATION 0x00008000 #define IRP_SET_USER_EVENT IRP_CLOSE_OPERATION /* IRP I/O control flags */ #define IRP_QUOTA_CHARGED 0x01 #define IRP_ALLOCATED_MUST_SUCCEED 0x02 #define IRP_ALLOCATED_FIXED_SIZE 0x04 #define IRP_LOOKASIDE_ALLOCATION 0x08 struct io_status_block { union { uint32_t isb_status; void *isb_ptr; } u; register_t isb_info; }; typedef struct io_status_block io_status_block; struct kapc { uint16_t apc_type; uint16_t apc_size; uint32_t apc_spare0; void *apc_thread; list_entry apc_list; void *apc_kernfunc; void *apc_rundownfunc; void *apc_normalfunc; void *apc_normctx; void *apc_sysarg1; void *apc_sysarg2; uint8_t apc_stateidx; uint8_t apc_cpumode; uint8_t apc_inserted; }; typedef struct kapc kapc; struct io_stack_location { uint8_t isl_major; uint8_t isl_minor; uint8_t isl_flags; uint8_t isl_ctl; /* * There's a big-ass union here in the actual Windows * definition of the stucture, but it contains stuff * that doesn't really apply to BSD, and defining it * all properly would require duplicating over a dozen * other structures that we'll never use. Since the * io_stack_location structure is opaque to drivers * anyway, I'm not going to bother with the extra crap. */ union { struct { void *isl_arg1; void *isl_arg2; void *isl_arg3; void *isl_arg4; } isl_others; } isl_parameters; void *isl_devobj; void *isl_fileobj; void *isl_completionfunc; void *isl_completionctx; }; typedef struct io_stack_location io_stack_location; /* Stack location control flags */ #define SL_PENDING_RETURNED 0x01 #define SL_INVOKE_ON_CANCEL 0x20 #define SL_INVOKE_ON_SUCCESS 0x40 #define SL_INVOKE_ON_ERROR 0x80 struct irp { uint16_t irp_type; uint16_t irp_size; mdl *irp_mdl; uint32_t irp_flags; union { struct irp *irp_master; uint32_t irp_irpcnt; void *irp_sysbuf; } irp_assoc; list_entry irp_thlist; io_status_block irp_iostat; uint8_t irp_reqmode; uint8_t irp_pendingreturned; uint8_t irp_stackcnt; uint8_t irp_currentstackloc; uint8_t irp_cancel; uint8_t irp_cancelirql; uint8_t irp_apcenv; uint8_t irp_allocflags; io_status_block *irp_usriostat; nt_kevent irp_userevent; union { struct { void *irp_apcfunc; void *irp_apcctx; } irp_asyncparms; uint64_t irp_allocsz; } irp_overlay; void *irp_cancelfunc; void *irp_userbuf; /* Windows kernel info */ union { struct { union { kdevice_qentry irp_dqe; struct { void *irp_drvctx[4]; } s1; } u1; void *irp_thread; char *irp_auxbuf; struct { list_entry irp_list; union { io_stack_location *irp_csl; uint32_t irp_pkttype; } u2; } s2; void *irp_fileobj; } irp_overlay; kapc irp_apc; void *irp_compkey; } irp_tail; }; #define irp_csl s2.u2.irp_csl #define irp_pkttype s2.u2.irp_pkttype typedef struct irp irp; #define IoGetCurrentIrpStackLocation(irp) \ (irp)->irp_tail.irp_overlay.irp_csl #define IoGetNextIrpStackLocation(irp) \ ((irp)->irp_tail.irp_overlay.irp_csl - 1) #define IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel) \ do { \ io_stack_location *s; \ s = IoGetNextIrpStackLocation((irp)); \ s->isl_completionfunc = (func); \ s->isl_completionctx = (ctx); \ s->isl_ctl = 0; \ if (ok) irp->ctl = SL_INVOKE_ON_SUCCESS; \ if (err) irp->ctl |= SL_INVOKE_ON_ERROR; \ if (cancel) irp->ctl |= SL_INVOKE_ON_CANCEL; \ } while(0) #define IoMarkIrpPending(irp) \ IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED #define IoSizeOfIrp(s) \ ((uint16_t) (sizeof(itp) + ((s) * (sizeof(io_stack_location))))) #define IoCopyCurrentIrpStackLocationToNext(irp) \ do { \ io_stack_location *src, *dst; \ src = IoGetCurrentIrpStackLocation(irp); \ dst = IoGetNextIrpStackLocation(irp); \ bcopy((char *)src, (char *)dst, \ offsetof(io_stack_location, isl_completionfunc)); \ } while(0) #define IoSkipCurrentIrpStackLocation(irp) \ do { \ (irp)->irp_currentstackloc++; \ (irp)->irp_tail.irp_overlay.irp_csl++; \ } while(0) typedef uint32_t (*driver_dispatch)(device_object *, irp *); /* * The driver_object is allocated once for each driver that's loaded * into the system. A new one is allocated for each driver and * populated a bit via the driver's DriverEntry function. * In general, a Windows DriverEntry() function will provide a pointer * to its AddDevice() method and set up the dispatch table. * For NDIS drivers, this is all done behind the scenes in the * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines. */ struct driver_object { uint16_t dro_type; uint16_t dro_size; device_object *dro_devobj; uint32_t dro_flags; void *dro_driverstart; uint32_t dro_driversize; void *dro_driversection; driver_extension dro_driverext; unicode_string dro_drivername; unicode_string *dro_hwdb; void *dro_pfastiodispatch; void *dro_driverinitfunc; void *dro_driverstartiofunc; void *dro_driverunloadfunc; void *dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1]; }; typedef struct driver_object driver_object; #define DEVPROP_DEVICE_DESCRIPTION 0x00000000 #define DEVPROP_HARDWARE_ID 0x00000001 #define DEVPROP_COMPATIBLE_IDS 0x00000002 #define DEVPROP_BOOTCONF 0x00000003 #define DEVPROP_BOOTCONF_TRANSLATED 0x00000004 #define DEVPROP_CLASS_NAME 0x00000005 #define DEVPROP_CLASS_GUID 0x00000006 #define DEVPROP_DRIVER_KEYNAME 0x00000007 #define DEVPROP_MANUFACTURER 0x00000008 #define DEVPROP_FRIENDLYNAME 0x00000009 #define DEVPROP_LOCATION_INFO 0x0000000A #define DEVPROP_PHYSDEV_NAME 0x0000000B #define DEVPROP_BUSTYPE_GUID 0x0000000C #define DEVPROP_LEGACY_BUSTYPE 0x0000000D #define DEVPROP_BUS_NUMBER 0x0000000E #define DEVPROP_ENUMERATOR_NAME 0x0000000F #define DEVPROP_ADDRESS 0x00000010 #define DEVPROP_UINUMBER 0x00000011 #define DEVPROP_INSTALL_STATE 0x00000012 #define DEVPROP_REMOVAL_POLICY 0x00000013 #define STATUS_SUCCESS 0x00000000 #define STATUS_USER_APC 0x000000C0 #define STATUS_KERNEL_APC 0x00000100 #define STATUS_ALERTED 0x00000101 #define STATUS_TIMEOUT 0x00000102 #define STATUS_INVALID_PARAMETER 0xC000000D #define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 #define STATUS_BUFFER_TOO_SMALL 0xC0000023 #define STATUS_MUTANT_NOT_OWNED 0xC0000046 #define STATUS_INVALID_PARAMETER_2 0xC00000F0 #define STATUS_WAIT_0 0x00000000 /* * FreeBSD's kernel stack is 2 pages in size by default. The * Windows stack is larger, so we need to give our threads more * stack pages. 4 should be enough, we use 8 just to extra safe. */ #define NDIS_KSTACK_PAGES 8 extern image_patch_table ntoskrnl_functbl[]; __BEGIN_DECLS extern int ntoskrnl_libinit(void); extern int ntoskrnl_libfini(void); __stdcall extern void KeInitializeDpc(kdpc *, void *, void *); __stdcall extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *); __stdcall extern uint8_t KeRemoveQueueDpc(kdpc *); __stdcall extern void KeInitializeTimer(ktimer *); __stdcall extern void KeInitializeTimerEx(ktimer *, uint32_t); __stdcall extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *); __stdcall extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *); __stdcall extern uint8_t KeCancelTimer(ktimer *); __stdcall extern uint8_t KeReadStateTimer(ktimer *); __stdcall extern uint32_t KeWaitForSingleObject(nt_dispatch_header *, uint32_t, uint32_t, uint8_t, int64_t *); __stdcall extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t); __stdcall extern void KeClearEvent(nt_kevent *); __stdcall extern uint32_t KeReadStateEvent(nt_kevent *); __stdcall extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t); __stdcall extern uint32_t KeResetEvent(nt_kevent *); __fastcall extern void KefAcquireSpinLockAtDpcLevel(REGARGS1(kspin_lock *)); __fastcall extern void KefReleaseSpinLockFromDpcLevel(REGARGS1(kspin_lock *)); __stdcall extern void KeInitializeSpinLock(kspin_lock *); __fastcall extern uint32_t IofCallDriver(REGARGS2(device_object *, irp *)); __fastcall extern void IofCompleteRequest(REGARGS2(irp *, uint8_t)); #define IoCallDriver(a, b) FASTCALL2(IofCallDriver, a, b) #define IoCompleteRequest(a, b) FASTCALL2(IofCompleteRequest, a, b) /* * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock() * routines live in the HAL. We try to imitate this behavior. */ #ifdef __i386__ #define KeAcquireSpinLock(a, b) *(b) = FASTCALL1(KfAcquireSpinLock, a) #define KeReleaseSpinLock(a, b) FASTCALL2(KfReleaseSpinLock, a, b) #define KeRaiseIrql(a) FASTCALL1(KfRaiseIrql, a) #define KeLowerIrql(a) FASTCALL1(KfLowerIrql, a) #endif /* __i386__ */ __END_DECLS #endif /* _NTOSKRNL_VAR_H_ */