ntoskrnl_var.h revision 141980
1/*-
2 * Copyright (c) 2003
3 *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * $FreeBSD: head/sys/compat/ndis/ntoskrnl_var.h 141980 2005-02-16 18:18:30Z wpaul $
33 */
34
35#ifndef _NTOSKRNL_VAR_H_
36#define _NTOSKRNL_VAR_H_
37
38/*
39 * us_buf is really a wchar_t *, but it's inconvenient to include
40 * all the necessary header goop needed to define it, and it's a
41 * pointer anyway, so for now, just make it a uint16_t *.
42 */
43struct unicode_string {
44	uint16_t		us_len;
45	uint16_t		us_maxlen;
46	uint16_t		*us_buf;
47};
48
49typedef struct unicode_string unicode_string;
50
51/*
52 * Windows memory descriptor list. In Windows, it's possible for
53 * buffers to be passed between user and kernel contexts without
54 * copying. Buffers may also be allocated in either paged or
55 * non-paged memory regions. An MDL describes the pages of memory
56 * used to contain a particular buffer. Note that a single MDL
57 * may describe a buffer that spans multiple pages. An array of
58 * page addresses appears immediately after the MDL structure itself.
59 * MDLs are therefore implicitly variably sized, even though they
60 * don't look it.
61 *
62 * Note that in FreeBSD, we can take many shortcuts in the way
63 * we handle MDLs because:
64 *
65 * - We are only concerned with pages in kernel context. This means
66 *   we will only ever use the kernel's memory map, and remapping
67 *   of buffers is never needed.
68 *
69 * - Kernel pages can never be paged out, so we don't have to worry
70 *   about whether or not a page is actually mapped before going to
71 *   touch it.
72 */
73
74struct mdl {
75        struct mdl		*mdl_next;
76	uint16_t		mdl_size;
77	uint16_t		mdl_flags;
78	void			*mdl_process;
79	void			*mdl_mappedsystemva;
80	void			*mdl_startva;
81	uint32_t		mdl_bytecount;
82	uint32_t		mdl_byteoffset;
83};
84
85typedef struct mdl mdl, ndis_buffer;
86
87/* MDL flags */
88
89#define MDL_MAPPED_TO_SYSTEM_VA		0x0001
90#define MDL_PAGES_LOCKED		0x0002
91#define MDL_SOURCE_IS_NONPAGED_POOL	0x0004
92#define MDL_ALLOCATED_FIXED_SIZE	0x0008
93#define MDL_PARTIAL			0x0010
94#define MDL_PARTIAL_HAS_BEEN_MAPPED	0x0020
95#define MDL_IO_PAGE_READ		0x0040
96#define MDL_WRITE_OPERATION		0x0080
97#define MDL_PARENT_MAPPED_SYSTEM_VA	0x0100
98#define MDL_FREE_EXTRA_PTES		0x0200
99#define MDL_IO_SPACE			0x0800
100#define MDL_NETWORK_HEADER		0x1000
101#define MDL_MAPPING_CAN_FAIL		0x2000
102#define MDL_ALLOCATED_MUST_SUCCEED	0x4000
103
104/* Note: assumes x86 page size of 4K. */
105
106#if PAGE_SIZE == 4096
107#define PAGE_SHIFT	12
108#elif PAGE_SIZE == 8192
109#define PAGE_SHIFT	13
110#else
111#error PAGE_SHIFT undefined!
112#endif
113
114#define SPAN_PAGES(ptr, len)					\
115	((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) +	\
116	(len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
117
118#define PAGE_ALIGN(ptr)						\
119	((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
120
121#define BYTE_OFFSET(ptr)					\
122	((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
123
124#define MDL_PAGES(m)	(vm_offset_t *)(m + 1)
125
126#define MmInitializeMdl(b, baseva, len)					\
127	(b)->mdl_next = NULL;						\
128	(b)->mdl_size = (uint16_t)(sizeof(mdl) +			\
129		(sizeof(uint32_t) * SPAN_PAGES((baseva), (len))));	\
130	(b)->mdl_flags = 0;						\
131	(b)->mdl_startva = (void *)PAGE_ALIGN((baseva));		\
132	(b)->mdl_byteoffset = BYTE_OFFSET((baseva));			\
133	(b)->mdl_bytecount = (uint32_t)(len);
134
135#define MmGetMdlByteOffset(mdl)		((mdl)->mdl_byteoffset)
136#define MmGetMdlByteCount(mdl)		((mdl)->mdl_bytecount)
137#define MmGetMdlVirtualAddress(mdl)					\
138	((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset))
139#define MmGetMdlStartVa(mdl)		((mdl)->mdl_startva)
140#define MmGetMdlPfnArray(mdl)		MDL_PAGES(mdl)
141
142#define WDM_MAJOR		1
143#define WDM_MINOR_WIN98		0x00
144#define WDM_MINOR_WINME		0x05
145#define WDM_MINOR_WIN2000	0x10
146#define WDM_MINOR_WINXP		0x20
147#define WDM_MINOR_WIN2003	0x30
148
149/*-
150 * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
151 * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
152 *	typedef ULONG_PTR KSPIN_LOCK;
153 *
154 * From basetsd.h (SDK, Feb. 2003):
155 * 	typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
156 * 	typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
157 * 	typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
158 *
159 * The keyword __int3264 specifies an integral type that has the following
160 * properties:
161 *	+ It is 32-bit on 32-bit platforms
162 *	+ It is 64-bit on 64-bit platforms
163 *	+ It is 32-bit on the wire for backward compatibility.
164 *	  It gets truncated on the sending side and extended appropriately
165 *	  (signed or unsigned) on the receiving side.
166 *
167 * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
168 */
169
170typedef register_t kspin_lock;
171
172struct slist_entry {
173	struct slist_entry	*sl_next;
174};
175
176typedef struct slist_entry slist_entry;
177
178union slist_header {
179	uint64_t		slh_align;
180	struct {
181		struct slist_entry	*slh_next;
182		uint16_t		slh_depth;
183		uint16_t		slh_seq;
184	} slh_list;
185};
186
187typedef union slist_header slist_header;
188
189struct list_entry {
190        struct list_entry *nle_flink;
191        struct list_entry *nle_blink;
192};
193
194typedef struct list_entry list_entry;
195
196#define INIT_LIST_HEAD(l)	\
197	(l)->nle_flink = (l)->nle_blink = (l)
198
199#define REMOVE_LIST_ENTRY(e)			\
200	do {					\
201		list_entry		*b;	\
202		list_entry		*f;	\
203						\
204		f = e->nle_flink;		\
205		b = e->nle_blink;		\
206		b->nle_flink = f;		\
207		f->nle_blink = b;		\
208	} while (0)
209
210#define REMOVE_LIST_HEAD(l)			\
211	do {					\
212		list_entry		*f;	\
213		list_entry		*e;	\
214						\
215		e = l->nle_flink;		\
216		f = e->nle_flink;		\
217		l->nle_flink = f;		\
218		f->nle_blink = l;		\
219	} while (0)
220
221#define REMOVE_LIST_TAIL(l)			\
222	do {					\
223		list_entry		*b;	\
224		list_entry		*e;	\
225						\
226		e = l->nle_blink;		\
227		b = e->nle_blink;		\
228		l->nle_blink = b;		\
229		b->nle_flink = l;		\
230	} while (0)
231
232#define INSERT_LIST_TAIL(l, e)			\
233	do {					\
234		list_entry		*b;	\
235						\
236		b = l->nle_blink;		\
237		e->nle_flink = l;		\
238		e->nle_blink = b;		\
239		b->nle_flink = (e);		\
240		l->nle_blink = (e);		\
241	} while (0)
242
243#define INSERT_LIST_HEAD(l, e)			\
244	do {					\
245		list_entry		*f;	\
246						\
247		f = l->nle_flink;		\
248		e->nle_flink = f;		\
249		e->nle_blink = l;		\
250		f->nle_blink = e;		\
251		l->nle_flink = e;		\
252	} while (0)
253
254struct nt_dispatch_header {
255	uint8_t			dh_type;
256	uint8_t			dh_abs;
257	uint8_t			dh_size;
258	uint8_t			dh_inserted;
259	uint32_t		dh_sigstate;
260	list_entry		dh_waitlisthead;
261};
262
263typedef struct nt_dispatch_header nt_dispatch_header;
264
265#define OTYPE_EVENT		0
266#define OTYPE_MUTEX		1
267#define OTYPE_THREAD		2
268#define OTYPE_TIMER		3
269
270/* Windows dispatcher levels. */
271
272#define PASSIVE_LEVEL		0
273#define LOW_LEVEL		0
274#define APC_LEVEL		1
275#define DISPATCH_LEVEL		2
276#define DEVICE_LEVEL		(DISPATCH_LEVEL + 1)
277#define PROFILE_LEVEL		27
278#define CLOCK1_LEVEL		28
279#define CLOCK2_LEVEL		28
280#define IPI_LEVEL		29
281#define POWER_LEVEL		30
282#define HIGH_LEVEL		31
283
284#define SYNC_LEVEL_UP		DISPATCH_LEVEL
285#define SYNC_LEVEL_MP		(IPI_LEVEL - 1)
286
287#define AT_PASSIVE_LEVEL(td)		\
288	((td)->td_proc->p_flag & P_KTHREAD == FALSE)
289
290#define AT_DISPATCH_LEVEL(td)		\
291	((td)->td_base_pri == PI_REALTIME)
292
293#define AT_DIRQL_LEVEL(td)		\
294	((td)->td_priority <= PI_NET)
295
296#define AT_HIGH_LEVEL(td)		\
297	((td)->td_critnest != 0)
298
299struct nt_objref {
300	nt_dispatch_header	no_dh;
301	void			*no_obj;
302	TAILQ_ENTRY(nt_objref)	link;
303};
304
305TAILQ_HEAD(nt_objref_head, nt_objref);
306
307typedef struct nt_objref nt_objref;
308
309#define EVENT_TYPE_NOTIFY	0
310#define EVENT_TYPE_SYNC		1
311
312/*
313 * We need to use the timeout()/untimeout() API for ktimers
314 * since timers can be initialized, but not destroyed (so
315 * malloc()ing our own callout structures would mean a leak,
316 * since there'd be no way to free() them). This means we
317 * need to use struct callout_handle, which is really just a
318 * pointer. To make it easier to deal with, we use a union
319 * to overlay the callout_handle over the k_timerlistentry.
320 * The latter is a list_entry, which is two pointers, so
321 * there's enough space available to hide a callout_handle
322 * there.
323 */
324
325struct ktimer {
326	nt_dispatch_header	k_header;
327	uint64_t		k_duetime;
328	union {
329		list_entry		k_timerlistentry;
330		struct callout_handle	k_handle;
331	} u;
332	void			*k_dpc;
333	uint32_t		k_period;
334};
335
336#define k_timerlistentry	u.k_timerlistentry
337#define k_handle		u.k_handle
338
339typedef struct ktimer ktimer;
340
341struct nt_kevent {
342	nt_dispatch_header	k_header;
343};
344
345typedef struct nt_kevent nt_kevent;
346
347/* Kernel defered procedure call (i.e. timer callback) */
348
349struct kdpc;
350typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
351
352struct kdpc {
353	uint16_t		k_type;
354	uint8_t			k_num;
355	uint8_t			k_importance;
356	list_entry		k_dpclistentry;
357	void			*k_deferedfunc;
358	void			*k_deferredctx;
359	void			*k_sysarg1;
360	void			*k_sysarg2;
361	register_t		k_lock;
362};
363
364typedef struct kdpc kdpc;
365
366/*
367 * Note: the acquisition count is BSD-specific. The Microsoft
368 * documentation says that mutexes can be acquired recursively
369 * by a given thread, but that you must release the mutex as
370 * many times as you acquired it before it will be set to the
371 * signalled state (i.e. before any other threads waiting on
372 * the object will be woken up). However the Windows KMUTANT
373 * structure has no field for keeping track of the number of
374 * acquisitions, so we need to add one ourselves. As long as
375 * driver code treats the mutex as opaque, we should be ok.
376 */
377struct kmutant {
378	nt_dispatch_header	km_header;
379	union {
380		list_entry		km_listentry;
381		uint32_t		km_acquirecnt;
382	} u;
383	void			*km_ownerthread;
384	uint8_t			km_abandoned;
385	uint8_t			km_apcdisable;
386};
387
388#define km_listentry		u.km_listentry
389#define km_acquirecnt		u.km_acquirecnt
390
391typedef struct kmutant kmutant;
392
393#define LOOKASIDE_DEPTH 256
394
395struct general_lookaside {
396	slist_header		gl_listhead;
397	uint16_t		gl_depth;
398	uint16_t		gl_maxdepth;
399	uint32_t		gl_totallocs;
400	union {
401		uint32_t		gl_allocmisses;
402		uint32_t		gl_allochits;
403	} u_a;
404	uint32_t		gl_totalfrees;
405	union {
406		uint32_t		gl_freemisses;
407		uint32_t		gl_freehits;
408	} u_m;
409	uint32_t		gl_type;
410	uint32_t		gl_tag;
411	uint32_t		gl_size;
412	void			*gl_allocfunc;
413	void			*gl_freefunc;
414	list_entry		gl_listent;
415	uint32_t		gl_lasttotallocs;
416	union {
417		uint32_t		gl_lastallocmisses;
418		uint32_t		gl_lastallochits;
419	} u_l;
420	uint32_t		gl_rsvd[2];
421};
422
423typedef struct general_lookaside general_lookaside;
424
425struct npaged_lookaside_list {
426	general_lookaside	nll_l;
427	kspin_lock		nll_obsoletelock;
428};
429
430typedef struct npaged_lookaside_list npaged_lookaside_list;
431typedef struct npaged_lookaside_list paged_lookaside_list;
432
433typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
434typedef void (*lookaside_free_func)(void *);
435
436struct irp;
437
438struct kdevice_qentry {
439	list_entry		kqe_devlistent;
440	uint32_t		kqe_sortkey;
441	uint8_t			kqe_inserted;
442};
443
444typedef struct kdevice_qentry kdevice_qentry;
445
446struct kdevice_queue {
447	uint16_t		kq_type;
448	uint16_t		kq_size;
449	list_entry		kq_devlisthead;
450	kspin_lock		kq_lock;
451	uint8_t			kq_busy;
452};
453
454typedef struct kdevice_queue kdevice_queue;
455
456struct wait_ctx_block {
457	kdevice_qentry		wcb_waitqueue;
458	void			*wcb_devfunc;
459	void			*wcb_devctx;
460	uint32_t		wcb_mapregcnt;
461	void			*wcb_devobj;
462	void			*wcb_curirp;
463	void			*wcb_bufchaindpc;
464};
465
466typedef struct wait_ctx_block wait_ctx_block;
467
468struct wait_block {
469	list_entry		wb_waitlist;
470	void			*wb_kthread;
471	nt_dispatch_header	*wb_object;
472	struct wait_block	*wb_next;
473	uint16_t		wb_waitkey;
474	uint16_t		wb_waittype;
475};
476
477typedef struct wait_block wait_block;
478
479#define THREAD_WAIT_OBJECTS	3
480#define MAX_WAIT_OBJECTS	64
481
482#define WAITTYPE_ALL		0
483#define WAITTYPE_ANY		1
484
485struct thread_context {
486	void			*tc_thrctx;
487	void			*tc_thrfunc;
488};
489
490typedef struct thread_context thread_context;
491
492/* Forward declaration */
493struct driver_object;
494struct devobj_extension;
495
496struct driver_extension {
497	struct driver_object	*dre_driverobj;
498	void			*dre_adddevicefunc;
499	uint32_t		dre_reinitcnt;
500	unicode_string		dre_srvname;
501
502	/*
503	 * Drivers are allowed to add one or more custom extensions
504	 * to the driver object, but there's no special pointer
505	 * for them. Hang them off here for now.
506	 */
507
508	list_entry		dre_usrext;
509};
510
511typedef struct driver_extension driver_extension;
512
513struct custom_extension {
514	list_entry		ce_list;
515	void			*ce_clid;
516};
517
518typedef struct custom_extension custom_extension;
519
520/*
521 * In Windows, there are Physical Device Objects (PDOs) and
522 * Functional Device Objects (FDOs). Physical Device Objects are
523 * created and maintained by bus drivers. For example, the PCI
524 * bus driver might detect two PCI ethernet cards on a given
525 * bus. The PCI bus driver will then allocate two device_objects
526 * for its own internal bookeeping purposes. This is analagous
527 * to the device_t that the FreeBSD PCI code allocates and passes
528 * into each PCI driver's probe and attach routines.
529 *
530 * When an ethernet driver claims one of the ethernet cards
531 * on the bus, it will create its own device_object. This is
532 * the Functional Device Object. This object is analagous to the
533 * device-specific softc structure.
534 */
535
536struct device_object {
537	uint16_t		do_type;
538	uint16_t		do_size;
539	uint32_t		do_refcnt;
540	struct driver_object	*do_drvobj;
541	struct device_object	*do_nextdev;
542	struct device_object	*do_attacheddev;
543	struct irp		*do_currirp;
544	void			*do_iotimer;
545	uint32_t		do_flags;
546	uint32_t		do_characteristics;
547	void			*do_vpb;
548	void			*do_devext;
549	uint32_t		do_devtype;
550	uint8_t			do_stacksize;
551	union {
552		list_entry		do_listent;
553		wait_ctx_block		do_wcb;
554	} queue;
555	uint32_t		do_alignreq;
556	kdevice_queue		do_devqueue;
557	struct kdpc		do_dpc;
558	uint32_t		do_activethreads;
559	void			*do_securitydesc;
560	struct nt_kevent	do_devlock;
561	uint16_t		do_sectorsz;
562	uint16_t		do_spare1;
563	struct devobj_extension	*do_devobj_ext;
564	void			*do_rsvd;
565};
566
567typedef struct device_object device_object;
568
569struct devobj_extension {
570	uint16_t		dve_type;
571	uint16_t		dve_size;
572	device_object		*dve_devobj;
573};
574
575typedef struct devobj_extension devobj_extension;
576
577#define IO_NO_INCREMENT			0
578#define IO_CD_ROM_INCREMENT		1
579#define IO_DISK_INCREMENT		1
580#define IO_KEYBOARD_INCREMENT		6
581#define IO_MAILSLOT_INCREMENT		2
582#define IO_MOUSE_INCREMENT		6
583#define IO_NAMED_PIPE_INCREMENT		2
584#define IO_NETWORK_INCREMENT		2
585#define IO_PARALLEL_INCREMENT		1
586#define IO_SERIAL_INCREMENT		2
587#define IO_SOUND_INCREMENT		8
588#define IO_VIDEO_INCREMENT		1
589
590/* IRP major codes */
591
592#define IRP_MJ_CREATE                   0x00
593#define IRP_MJ_CREATE_NAMED_PIPE        0x01
594#define IRP_MJ_CLOSE                    0x02
595#define IRP_MJ_READ                     0x03
596#define IRP_MJ_WRITE                    0x04
597#define IRP_MJ_QUERY_INFORMATION        0x05
598#define IRP_MJ_SET_INFORMATION          0x06
599#define IRP_MJ_QUERY_EA                 0x07
600#define IRP_MJ_SET_EA                   0x08
601#define IRP_MJ_FLUSH_BUFFERS            0x09
602#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
603#define IRP_MJ_SET_VOLUME_INFORMATION   0x0b
604#define IRP_MJ_DIRECTORY_CONTROL        0x0c
605#define IRP_MJ_FILE_SYSTEM_CONTROL      0x0d
606#define IRP_MJ_DEVICE_CONTROL           0x0e
607#define IRP_MJ_INTERNAL_DEVICE_CONTROL  0x0f
608#define IRP_MJ_SHUTDOWN                 0x10
609#define IRP_MJ_LOCK_CONTROL             0x11
610#define IRP_MJ_CLEANUP                  0x12
611#define IRP_MJ_CREATE_MAILSLOT          0x13
612#define IRP_MJ_QUERY_SECURITY           0x14
613#define IRP_MJ_SET_SECURITY             0x15
614#define IRP_MJ_POWER                    0x16
615#define IRP_MJ_SYSTEM_CONTROL           0x17
616#define IRP_MJ_DEVICE_CHANGE            0x18
617#define IRP_MJ_QUERY_QUOTA              0x19
618#define IRP_MJ_SET_QUOTA                0x1a
619#define IRP_MJ_PNP                      0x1b
620#define IRP_MJ_PNP_POWER                IRP_MJ_PNP      // Obsolete....
621#define IRP_MJ_MAXIMUM_FUNCTION         0x1b
622#define IRP_MJ_SCSI                     IRP_MJ_INTERNAL_DEVICE_CONTROL
623
624/* IRP minor codes */
625
626#define IRP_MN_QUERY_DIRECTORY          0x01
627#define IRP_MN_NOTIFY_CHANGE_DIRECTORY  0x02
628#define IRP_MN_USER_FS_REQUEST          0x00
629
630#define IRP_MN_MOUNT_VOLUME             0x01
631#define IRP_MN_VERIFY_VOLUME            0x02
632#define IRP_MN_LOAD_FILE_SYSTEM         0x03
633#define IRP_MN_TRACK_LINK               0x04    // To be obsoleted soon
634#define IRP_MN_KERNEL_CALL              0x04
635
636#define IRP_MN_LOCK                     0x01
637#define IRP_MN_UNLOCK_SINGLE            0x02
638#define IRP_MN_UNLOCK_ALL               0x03
639#define IRP_MN_UNLOCK_ALL_BY_KEY        0x04
640
641#define IRP_MN_NORMAL                   0x00
642#define IRP_MN_DPC                      0x01
643#define IRP_MN_MDL                      0x02
644#define IRP_MN_COMPLETE                 0x04
645#define IRP_MN_COMPRESSED               0x08
646
647#define IRP_MN_MDL_DPC                  (IRP_MN_MDL | IRP_MN_DPC)
648#define IRP_MN_COMPLETE_MDL             (IRP_MN_COMPLETE | IRP_MN_MDL)
649#define IRP_MN_COMPLETE_MDL_DPC         (IRP_MN_COMPLETE_MDL | IRP_MN_DPC)
650
651#define IRP_MN_SCSI_CLASS               0x01
652
653#define IRP_MN_START_DEVICE                 0x00
654#define IRP_MN_QUERY_REMOVE_DEVICE          0x01
655#define IRP_MN_REMOVE_DEVICE                0x02
656#define IRP_MN_CANCEL_REMOVE_DEVICE         0x03
657#define IRP_MN_STOP_DEVICE                  0x04
658#define IRP_MN_QUERY_STOP_DEVICE            0x05
659#define IRP_MN_CANCEL_STOP_DEVICE           0x06
660
661#define IRP_MN_QUERY_DEVICE_RELATIONS       0x07
662#define IRP_MN_QUERY_INTERFACE              0x08
663#define IRP_MN_QUERY_CAPABILITIES           0x09
664#define IRP_MN_QUERY_RESOURCES              0x0A
665#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS  0x0B
666#define IRP_MN_QUERY_DEVICE_TEXT            0x0C
667#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
668
669#define IRP_MN_READ_CONFIG                  0x0F
670#define IRP_MN_WRITE_CONFIG                 0x10
671#define IRP_MN_EJECT                        0x11
672#define IRP_MN_SET_LOCK                     0x12
673#define IRP_MN_QUERY_ID                     0x13
674#define IRP_MN_QUERY_PNP_DEVICE_STATE       0x14
675#define IRP_MN_QUERY_BUS_INFORMATION        0x15
676#define IRP_MN_DEVICE_USAGE_NOTIFICATION    0x16
677#define IRP_MN_SURPRISE_REMOVAL             0x17
678#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
679
680#define IRP_MN_WAIT_WAKE                    0x00
681#define IRP_MN_POWER_SEQUENCE               0x01
682#define IRP_MN_SET_POWER                    0x02
683#define IRP_MN_QUERY_POWER                  0x03
684
685#define IRP_MN_QUERY_ALL_DATA               0x00
686#define IRP_MN_QUERY_SINGLE_INSTANCE        0x01
687#define IRP_MN_CHANGE_SINGLE_INSTANCE       0x02
688#define IRP_MN_CHANGE_SINGLE_ITEM           0x03
689#define IRP_MN_ENABLE_EVENTS                0x04
690#define IRP_MN_DISABLE_EVENTS               0x05
691#define IRP_MN_ENABLE_COLLECTION            0x06
692#define IRP_MN_DISABLE_COLLECTION           0x07
693#define IRP_MN_REGINFO                      0x08
694#define IRP_MN_EXECUTE_METHOD               0x09
695#define IRP_MN_REGINFO_EX                   0x0b
696
697/* IRP flags */
698
699#define IRP_NOCACHE                     0x00000001
700#define IRP_PAGING_IO                   0x00000002
701#define IRP_MOUNT_COMPLETION            0x00000002
702#define IRP_SYNCHRONOUS_API             0x00000004
703#define IRP_ASSOCIATED_IRP              0x00000008
704#define IRP_BUFFERED_IO                 0x00000010
705#define IRP_DEALLOCATE_BUFFER           0x00000020
706#define IRP_INPUT_OPERATION             0x00000040
707#define IRP_SYNCHRONOUS_PAGING_IO       0x00000040
708#define IRP_CREATE_OPERATION            0x00000080
709#define IRP_READ_OPERATION              0x00000100
710#define IRP_WRITE_OPERATION             0x00000200
711#define IRP_CLOSE_OPERATION             0x00000400
712#define IRP_DEFER_IO_COMPLETION         0x00000800
713#define IRP_OB_QUERY_NAME               0x00001000
714#define IRP_HOLD_DEVICE_QUEUE           0x00002000
715#define IRP_RETRY_IO_COMPLETION         0x00004000
716#define IRP_CLASS_CACHE_OPERATION       0x00008000
717#define IRP_SET_USER_EVENT              IRP_CLOSE_OPERATION
718
719/* IRP I/O control flags */
720
721#define IRP_QUOTA_CHARGED               0x01
722#define IRP_ALLOCATED_MUST_SUCCEED      0x02
723#define IRP_ALLOCATED_FIXED_SIZE        0x04
724#define IRP_LOOKASIDE_ALLOCATION        0x08
725
726struct io_status_block {
727	union {
728		uint32_t		isb_status;
729		void			*isb_ptr;
730	} u;
731	register_t		isb_info;
732};
733#define isb_status		u.isb_status
734#define isb_ptr			u.isb_ptr
735
736typedef struct io_status_block io_status_block;
737
738struct kapc {
739	uint16_t		apc_type;
740	uint16_t		apc_size;
741	uint32_t		apc_spare0;
742	void			*apc_thread;
743	list_entry		apc_list;
744	void			*apc_kernfunc;
745	void			*apc_rundownfunc;
746	void			*apc_normalfunc;
747	void			*apc_normctx;
748	void			*apc_sysarg1;
749	void			*apc_sysarg2;
750	uint8_t			apc_stateidx;
751	uint8_t			apc_cpumode;
752	uint8_t			apc_inserted;
753};
754
755typedef struct kapc kapc;
756
757typedef __stdcall uint32_t (*completion_func)(device_object *,
758	struct irp *, void *);
759
760struct io_stack_location {
761	uint8_t			isl_major;
762	uint8_t			isl_minor;
763	uint8_t			isl_flags;
764	uint8_t			isl_ctl;
765
766	/*
767	 * There's a big-ass union here in the actual Windows
768	 * definition of the stucture, but it contains stuff
769	 * that doesn't really apply to BSD, and defining it
770	 * all properly would require duplicating over a dozen
771	 * other structures that we'll never use. Since the
772	 * io_stack_location structure is opaque to drivers
773	 * anyway, I'm not going to bother with the extra crap.
774	 */
775
776	union {
777		struct {
778			void			*isl_arg1;
779			void			*isl_arg2;
780			void			*isl_arg3;
781			void			*isl_arg4;
782		} isl_others;
783	} isl_parameters;
784
785	void			*isl_devobj;
786	void			*isl_fileobj;
787	completion_func		isl_completionfunc;
788	void			*isl_completionctx;
789};
790
791typedef struct io_stack_location io_stack_location;
792
793/* Stack location control flags */
794
795#define SL_PENDING_RETURNED		0x01
796#define SL_INVOKE_ON_CANCEL		0x20
797#define SL_INVOKE_ON_SUCCESS		0x40
798#define SL_INVOKE_ON_ERROR		0x80
799
800struct irp {
801	uint16_t		irp_type;
802	uint16_t		irp_size;
803	mdl			*irp_mdl;
804	uint32_t		irp_flags;
805	union {
806		struct irp		*irp_master;
807		uint32_t		irp_irpcnt;
808		void			*irp_sysbuf;
809	} irp_assoc;
810	list_entry		irp_thlist;
811	io_status_block		irp_iostat;
812	uint8_t			irp_reqmode;
813	uint8_t			irp_pendingreturned;
814	uint8_t			irp_stackcnt;
815	uint8_t			irp_currentstackloc;
816	uint8_t			irp_cancel;
817	uint8_t			irp_cancelirql;
818	uint8_t			irp_apcenv;
819	uint8_t			irp_allocflags;
820	io_status_block		*irp_usriostat;
821	nt_kevent		*irp_usrevent;
822	union {
823		struct {
824			void			*irp_apcfunc;
825			void			*irp_apcctx;
826		} irp_asyncparms;
827		uint64_t			irp_allocsz;
828	} irp_overlay;
829	void			*irp_cancelfunc;
830	void			*irp_userbuf;
831
832	/* Windows kernel info */
833
834	union {
835		struct {
836			union {
837				kdevice_qentry			irp_dqe;
838				struct {
839					void 			*irp_drvctx[4];
840				} s1;
841			} u1;
842			void			*irp_thread;
843			char			*irp_auxbuf;
844			struct {
845				list_entry			irp_list;
846				union {
847					io_stack_location	*irp_csl;
848					uint32_t		irp_pkttype;
849				} u2;
850			} s2;
851			void			*irp_fileobj;
852		} irp_overlay;
853		kapc			irp_apc;
854		void			*irp_compkey;
855	} irp_tail;
856};
857
858#define irp_csl			s2.u2.irp_csl
859#define irp_pkttype		s2.u2.irp_pkttype
860
861typedef struct irp irp;
862
863#define IoSizeOfIrp(ssize)						\
864	((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location)))))
865
866
867#define IoGetCurrentIrpStackLocation(irp)				\
868	(irp)->irp_tail.irp_overlay.irp_csl
869
870#define IoGetNextIrpStackLocation(irp)					\
871	((irp)->irp_tail.irp_overlay.irp_csl - 1)
872
873#define IoSetNextIrpStackLocation(irp)					\
874	do {								\
875		irp->irp_currentstackloc--;				\
876		irp->irp_tail.irp_overlay.irp_csl--;			\
877	} while(0)
878
879#define IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel)		\
880	do {								\
881		io_stack_location		*s;			\
882		s = IoGetNextIrpStackLocation((irp));			\
883		s->isl_completionfunc = (func);				\
884		s->isl_completionctx = (ctx);				\
885		s->isl_ctl = 0;						\
886		if (ok) s->isl_ctl = SL_INVOKE_ON_SUCCESS;		\
887		if (err) s->isl_ctl |= SL_INVOKE_ON_ERROR;		\
888		if (cancel) s->isl_ctl |= SL_INVOKE_ON_CANCEL;		\
889	} while(0)
890
891#define IoMarkIrpPending(irp)						\
892	IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED
893
894#define IoCopyCurrentIrpStackLocationToNext(irp)			\
895	do {								\
896		io_stack_location *src, *dst;				\
897		src = IoGetCurrentIrpStackLocation(irp);		\
898		dst = IoGetNextIrpStackLocation(irp);			\
899		bcopy((char *)src, (char *)dst,				\
900		    offsetof(io_stack_location, isl_completionfunc));	\
901	} while(0)
902
903#define IoSkipCurrentIrpStackLocation(irp)				\
904	do {								\
905		(irp)->irp_currentstackloc++;				\
906		(irp)->irp_tail.irp_overlay.irp_csl++;			\
907	} while(0)
908
909typedef __stdcall uint32_t (*driver_dispatch)(device_object *, irp *);
910
911/*
912 * The driver_object is allocated once for each driver that's loaded
913 * into the system. A new one is allocated for each driver and
914 * populated a bit via the driver's DriverEntry function.
915 * In general, a Windows DriverEntry() function will provide a pointer
916 * to its AddDevice() method and set up the dispatch table.
917 * For NDIS drivers, this is all done behind the scenes in the
918 * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines.
919 */
920
921struct driver_object {
922	uint16_t		dro_type;
923	uint16_t		dro_size;
924	device_object		*dro_devobj;
925	uint32_t		dro_flags;
926	void			*dro_driverstart;
927	uint32_t		dro_driversize;
928	void			*dro_driversection;
929	driver_extension	*dro_driverext;
930	unicode_string		dro_drivername;
931	unicode_string		*dro_hwdb;
932	void			*dro_pfastiodispatch;
933	void			*dro_driverinitfunc;
934	void			*dro_driverstartiofunc;
935	void			*dro_driverunloadfunc;
936	driver_dispatch		dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1];
937};
938
939typedef struct driver_object driver_object;
940
941#define DEVPROP_DEVICE_DESCRIPTION	0x00000000
942#define DEVPROP_HARDWARE_ID		0x00000001
943#define DEVPROP_COMPATIBLE_IDS		0x00000002
944#define DEVPROP_BOOTCONF		0x00000003
945#define DEVPROP_BOOTCONF_TRANSLATED	0x00000004
946#define DEVPROP_CLASS_NAME		0x00000005
947#define DEVPROP_CLASS_GUID		0x00000006
948#define DEVPROP_DRIVER_KEYNAME		0x00000007
949#define DEVPROP_MANUFACTURER		0x00000008
950#define DEVPROP_FRIENDLYNAME		0x00000009
951#define DEVPROP_LOCATION_INFO		0x0000000A
952#define DEVPROP_PHYSDEV_NAME		0x0000000B
953#define DEVPROP_BUSTYPE_GUID		0x0000000C
954#define DEVPROP_LEGACY_BUSTYPE		0x0000000D
955#define DEVPROP_BUS_NUMBER		0x0000000E
956#define DEVPROP_ENUMERATOR_NAME		0x0000000F
957#define DEVPROP_ADDRESS			0x00000010
958#define DEVPROP_UINUMBER		0x00000011
959#define DEVPROP_INSTALL_STATE		0x00000012
960#define DEVPROP_REMOVAL_POLICY		0x00000013
961
962/* Various supported device types (used with IoCreateDevice()) */
963
964#define FILE_DEVICE_BEEP		0x00000001
965#define FILE_DEVICE_CD_ROM		0x00000002
966#define FILE_DEVICE_CD_ROM_FILE_SYSTEM	0x00000003
967#define FILE_DEVICE_CONTROLLER		0x00000004
968#define FILE_DEVICE_DATALINK		0x00000005
969#define FILE_DEVICE_DFS			0x00000006
970#define FILE_DEVICE_DISK		0x00000007
971#define FILE_DEVICE_DISK_FILE_SYSTEM	0x00000008
972#define FILE_DEVICE_FILE_SYSTEM		0x00000009
973#define FILE_DEVICE_INPORT_PORT		0x0000000A
974#define FILE_DEVICE_KEYBOARD		0x0000000B
975#define FILE_DEVICE_MAILSLOT		0x0000000C
976#define FILE_DEVICE_MIDI_IN		0x0000000D
977#define FILE_DEVICE_MIDI_OUT		0x0000000E
978#define FILE_DEVICE_MOUSE		0x0000000F
979#define FILE_DEVICE_MULTI_UNC_PROVIDER	0x00000010
980#define FILE_DEVICE_NAMED_PIPE		0x00000011
981#define FILE_DEVICE_NETWORK		0x00000012
982#define FILE_DEVICE_NETWORK_BROWSER	0x00000013
983#define FILE_DEVICE_NETWORK_FILE_SYSTEM	0x00000014
984#define FILE_DEVICE_NULL		0x00000015
985#define FILE_DEVICE_PARALLEL_PORT	0x00000016
986#define FILE_DEVICE_PHYSICAL_NETCARD	0x00000017
987#define FILE_DEVICE_PRINTER		0x00000018
988#define FILE_DEVICE_SCANNER		0x00000019
989#define FILE_DEVICE_SERIAL_MOUSE_PORT	0x0000001A
990#define FILE_DEVICE_SERIAL_PORT		0x0000001B
991#define FILE_DEVICE_SCREEN		0x0000001C
992#define FILE_DEVICE_SOUND		0x0000001D
993#define FILE_DEVICE_STREAMS		0x0000001E
994#define FILE_DEVICE_TAPE		0x0000001F
995#define FILE_DEVICE_TAPE_FILE_SYSTEM	0x00000020
996#define FILE_DEVICE_TRANSPORT		0x00000021
997#define FILE_DEVICE_UNKNOWN		0x00000022
998#define FILE_DEVICE_VIDEO		0x00000023
999#define FILE_DEVICE_VIRTUAL_DISK	0x00000024
1000#define FILE_DEVICE_WAVE_IN		0x00000025
1001#define FILE_DEVICE_WAVE_OUT		0x00000026
1002#define FILE_DEVICE_8042_PORT		0x00000027
1003#define FILE_DEVICE_NETWORK_REDIRECTOR	0x00000028
1004#define FILE_DEVICE_BATTERY		0x00000029
1005#define FILE_DEVICE_BUS_EXTENDER	0x0000002A
1006#define FILE_DEVICE_MODEM		0x0000002B
1007#define FILE_DEVICE_VDM			0x0000002C
1008#define FILE_DEVICE_MASS_STORAGE	0x0000002D
1009#define FILE_DEVICE_SMB			0x0000002E
1010#define FILE_DEVICE_KS			0x0000002F
1011#define FILE_DEVICE_CHANGER		0x00000030
1012#define FILE_DEVICE_SMARTCARD		0x00000031
1013#define FILE_DEVICE_ACPI		0x00000032
1014#define FILE_DEVICE_DVD			0x00000033
1015#define FILE_DEVICE_FULLSCREEN_VIDEO	0x00000034
1016#define FILE_DEVICE_DFS_FILE_SYSTEM	0x00000035
1017#define FILE_DEVICE_DFS_VOLUME		0x00000036
1018#define FILE_DEVICE_SERENUM		0x00000037
1019#define FILE_DEVICE_TERMSRV		0x00000038
1020#define FILE_DEVICE_KSEC		0x00000039
1021#define FILE_DEVICE_FIPS		0x0000003A
1022
1023/* Device characteristics */
1024
1025#define FILE_REMOVABLE_MEDIA		0x00000001
1026#define FILE_READ_ONLY_DEVICE		0x00000002
1027#define FILE_FLOPPY_DISKETTE		0x00000004
1028#define FILE_WRITE_ONCE_MEDIA		0x00000008
1029#define FILE_REMOTE_DEVICE		0x00000010
1030#define FILE_DEVICE_IS_MOUNTED		0x00000020
1031#define FILE_VIRTUAL_VOLUME		0x00000040
1032#define FILE_AUTOGENERATED_DEVICE_NAME	0x00000080
1033#define FILE_DEVICE_SECURE_OPEN		0x00000100
1034
1035/* Status codes */
1036
1037#define STATUS_SUCCESS			0x00000000
1038#define STATUS_USER_APC			0x000000C0
1039#define STATUS_KERNEL_APC		0x00000100
1040#define STATUS_ALERTED			0x00000101
1041#define STATUS_TIMEOUT			0x00000102
1042#define STATUS_INVALID_PARAMETER	0xC000000D
1043#define STATUS_INVALID_DEVICE_REQUEST	0xC0000010
1044#define STATUS_MORE_PROCESSING_REQUIRED	0xC0000016
1045#define STATUS_BUFFER_TOO_SMALL		0xC0000023
1046#define STATUS_MUTANT_NOT_OWNED		0xC0000046
1047#define STATUS_INVALID_PARAMETER_2	0xC00000F0
1048#define STATUS_INSUFFICIENT_RESOURCES	0xC000009A
1049
1050#define STATUS_WAIT_0			0x00000000
1051
1052/* Memory pool types, for ExAllocatePoolWithTag() */
1053
1054#define NonPagedPool			0x00000000
1055#define PagedPool			0x00000001
1056#define NonPagedPoolMustSucceed		0x00000002
1057#define DontUseThisType			0x00000003
1058#define NonPagedPoolCacheAligned	0x00000004
1059#define PagedPoolCacheAligned		0x00000005
1060#define NonPagedPoolCacheAlignedMustS	0x00000006
1061#define MaxPoolType			0x00000007
1062
1063/*
1064 * FreeBSD's kernel stack is 2 pages in size by default. The
1065 * Windows stack is larger, so we need to give our threads more
1066 * stack pages. 4 should be enough, we use 8 just to extra safe.
1067 */
1068#define NDIS_KSTACK_PAGES	8
1069
1070extern image_patch_table ntoskrnl_functbl[];
1071typedef void (*funcptr)(void);
1072
1073__BEGIN_DECLS
1074extern int windrv_libinit(void);
1075extern int windrv_libfini(void);
1076extern driver_object *windrv_lookup(vm_offset_t);
1077extern int windrv_load(module_t, vm_offset_t, int);
1078extern int windrv_unload(module_t, vm_offset_t, int);
1079extern int windrv_create_pdo(driver_object *, device_t);
1080extern void windrv_destroy_pdo(driver_object *, device_t);
1081extern device_object *windrv_find_pdo(driver_object *, device_t);
1082extern int windrv_bus_attach(driver_object *, char *);
1083extern int windrv_wrap(funcptr, funcptr *);
1084extern int windrv_unwrap(funcptr);
1085
1086extern int ntoskrnl_libinit(void);
1087extern int ntoskrnl_libfini(void);
1088__stdcall extern void KeInitializeDpc(kdpc *, void *, void *);
1089__stdcall extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *);
1090__stdcall extern uint8_t KeRemoveQueueDpc(kdpc *);
1091__stdcall extern void KeInitializeTimer(ktimer *);
1092__stdcall extern void KeInitializeTimerEx(ktimer *, uint32_t);
1093__stdcall extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *);
1094__stdcall extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *);
1095__stdcall extern uint8_t KeCancelTimer(ktimer *);
1096__stdcall extern uint8_t KeReadStateTimer(ktimer *);
1097__stdcall extern uint32_t KeWaitForSingleObject(nt_dispatch_header *, uint32_t,
1098	uint32_t, uint8_t, int64_t *);
1099__stdcall extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t);
1100__stdcall extern void KeClearEvent(nt_kevent *);
1101__stdcall extern uint32_t KeReadStateEvent(nt_kevent *);
1102__stdcall extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t);
1103__stdcall extern uint32_t KeResetEvent(nt_kevent *);
1104__fastcall extern void KefAcquireSpinLockAtDpcLevel(REGARGS1(kspin_lock *));
1105__fastcall extern void KefReleaseSpinLockFromDpcLevel(REGARGS1(kspin_lock *));
1106__stdcall extern void KeInitializeSpinLock(kspin_lock *);
1107__stdcall extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
1108__stdcall extern void ExFreePool(void *);
1109__stdcall extern uint32_t IoAllocateDriverObjectExtension(driver_object *,
1110	void *, uint32_t, void **);
1111__stdcall extern void *IoGetDriverObjectExtension(driver_object *, void *);
1112__stdcall extern uint32_t IoCreateDevice(driver_object *, uint32_t,
1113	unicode_string *, uint32_t, uint32_t, uint8_t, device_object **);
1114__stdcall extern void IoDeleteDevice(device_object *);
1115__stdcall extern device_object *IoGetAttachedDevice(device_object *);
1116__fastcall extern uint32_t IofCallDriver(REGARGS2(device_object *, irp *));
1117__fastcall extern void IofCompleteRequest(REGARGS2(irp *, uint8_t));
1118__stdcall extern void IoDetachDevice(device_object *);
1119__stdcall extern device_object *IoAttachDeviceToDeviceStack(device_object *,
1120	device_object *);
1121__stdcall mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *);
1122__stdcall void IoFreeMdl(mdl *);
1123
1124#define IoCallDriver(a, b)		FASTCALL2(IofCallDriver, a, b)
1125#define IoCompleteRequest(a, b)		FASTCALL2(IofCompleteRequest, a, b)
1126
1127/*
1128 * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
1129 * routines live in the HAL. We try to imitate this behavior.
1130 */
1131#ifdef __i386__
1132#define KeAcquireSpinLock(a, b)	*(b) = FASTCALL1(KfAcquireSpinLock, a)
1133#define KeReleaseSpinLock(a, b)	FASTCALL2(KfReleaseSpinLock, a, b)
1134#define KeRaiseIrql(a)		FASTCALL1(KfRaiseIrql, a)
1135#define KeLowerIrql(a)		FASTCALL1(KfLowerIrql, a)
1136#endif /* __i386__ */
1137
1138#ifdef __amd64__
1139#define KeAcquireSpinLock(a, b)	*(b) = KfAcquireSpinLock(a)
1140#define KeReleaseSpinLock(a, b)	KfReleaseSpinLock(a, b)
1141
1142/*
1143 * These may need to be redefined later;
1144 * not sure where they live on amd64 yet.
1145 */
1146#define KeRaiseIrql(a)		KfRaiseIrql(a)
1147#define KeLowerIrql(a)		KfLowerIrql(a)
1148#endif /* __amd64__ */
1149
1150__END_DECLS
1151
1152#endif /* _NTOSKRNL_VAR_H_ */
1153