;	Static Name Aliases
;
;	$S280_Name	EQU	Name
;	$S281_Real_Handle	EQU	Real_Handle
	TITLE   emm40.c
	NAME    emm40

	.286p
	.287
_TEXT	SEGMENT  WORD PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT  WORD PUBLIC 'DATA'
_DATA	ENDS
CONST	SEGMENT  WORD PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT  WORD PUBLIC 'BSS'
_BSS	ENDS
DGROUP	GROUP	CONST, _BSS, _DATA
	ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP
EXTRN	__acrtused:ABS
EXTRN	_wcopyb:NEAR
EXTRN	_copyout:NEAR
EXTRN	_Avail_Pages:NEAR
EXTRN	_copyin:NEAR
EXTRN	_get_pages:NEAR
EXTRN	_free_pages:NEAR
EXTRN	_Names_Match:NEAR
EXTRN	_GetUnallocatedPageCount:NEAR
EXTRN	_Get_Key_Val:NEAR
EXTRN	_valid_handle:NEAR
EXTRN	_source_addr:NEAR
EXTRN	_dest_addr:NEAR
EXTRN	_regp:DWORD
EXTRN	_handle_table:BYTE
EXTRN	_Handle_Name_Table:BYTE
EXTRN	_handle_table_size:WORD
EXTRN	_handle_count:WORD
EXTRN	_emm_page:WORD
EXTRN	_total_pages:WORD
EXTRN	_emmpt_start:WORD
EXTRN	_EMMstatus:WORD
EXTRN	_emm40_info:TBYTE
EXTRN	_mappable_pages:BYTE
EXTRN	_mappable_page_count:WORD
EXTRN	_cntxt_bytes:BYTE
EXTRN	_EMM_MPindex:BYTE
EXTRN	_OSEnabled:DWORD
EXTRN	_OSKey:DWORD
_BSS      SEGMENT
$S280_Name	DW 04H DUP (?)
$S281_Real_Handle	DW 01H DUP (?)
_BSS      ENDS
_TEXT      SEGMENT
	ASSUME	CS: _TEXT
;|*** /*******************************************************************************
;|***  * 
;|***  * (C) Copyright Microsoft Corp. 1986
;|***  * 
;|***  *    TITLE:	VDMM
;|***  *
;|***  *    MODULE:	EMM40.C - EMM 4.0 functions code.
;|***  *
;|***  *    VERSION:	0.00
;|***  *
;|***  *    DATE:	Feb 25, 1987
;|***  *
;|***  *******************************************************************************
;|***  *	CHANGE LOG
;|***  *  Date     Version	   Description
;|***  * --------  --------	-------------------------------------------------------
;|***  * 02/25/87	0.00	Orignal
;|***  *
;|***  *******************************************************************************
;|***  *     FUNCTIONAL DESCRIPTION
;|***  *
;|***  * Paged EMM Driver for the iAPX 386.
;|***  * Extra functions defined in the 4.0 spec required by Windows.
;|***  * 
;|***  ******************************************************************************/ 
;|*** 
;|*** /******************************************************************************
;|*** 	INCLUDE FILES
;|***  ******************************************************************************/ 
;|*** #include "emm.h"
;|*** /*#include "mem_mgr.h"*/
;|*** 
;|*** 
;|*** /******************************************************************************
;|*** 	EXTERNAL DATA STRUCTURES
;|***  ******************************************************************************/ 
;|*** /*
;|***  * handle_table
;|***  *	This is an array of handle pointers.
;|***  *	page_index of zero means free
;|***  */
;|*** extern struct handle_ptr handle_table[];
;|*** extern Handle_Name Handle_Name_Table[]; 	/* Handle names */
;|*** extern unsigned short	handle_table_size;	/* number of entries */
;|*** extern unsigned short	handle_count;		/* active handle count */
;|*** 
;|*** /*
;|***  * EMM Page table
;|***  *	this array contains lists of indexes into the 386
;|***  *	Page Table.  Each list is pointed to by a handle
;|***  *	table entry and is sequential/contiguous.  This is
;|***  *	so that maphandlepage doesn't have to scan a list
;|***  *	for the specified entry.
;|***  */
;|*** extern unsigned	short *emm_page;	/* _emm_page array */
;|*** extern int	free_count;		/* current free count */
;|*** extern int	total_pages;		/* number being managed */
;|*** extern unsigned	emmpt_start;		/* next free entry in table */
;|*** 
;|*** /*
;|***  * EMM free table
;|***  *	this array is a stack of available page table entries. 
;|***  *	each entry is an index into the pseudo page table
;|***  */
;|*** /*extern	unsigned free_stack_count;	/* number of entries */
;|*** 
;|*** /*
;|***  * Current status of `HW'. The way this is handled is that
;|***  * when returning status to caller, normal status is reported 
;|***  * via EMMstatus being moved into AX. Persistant errors
;|***  * (such as internal datastructure inconsistancies, etc) are
;|***  * placed in `EMMstatus' as HW failures. All other errors are 
;|***  * transient in nature (out of memory, handles, ...) and are 
;|***  * thus reported by directly setting AX. The EMMstatus variable
;|***  * is provided for expansion and is not currently being
;|***  * set to any other value.
;|***  */
;|*** extern unsigned short EMMstatus;
;|*** 
;|*** /*
;|***  * 4.0 EXTRAS
;|***  */
;|*** 
;|*** extern unsigned short emm40_info[5];		/* hardware information */
;|*** extern struct mappable_page mappable_pages[];	/* mappable segments
;|*** 					           and corresponding pages */
;|*** extern short	mappable_page_count;		/* number of entries in above */
;|*** extern short	page_frame_pages;		/* pages in the page frame */
;|*** extern short	physical_page_count;		/* number of physical pages */
;|*** /*extern char	VM1_cntxt_pages;		/* pages in a VM1 context */
;|*** /*extern char	VMn_cntxt_pages;		/* pages in a VM context */
;|*** /*extern char	VM1_cntxt_bytes;		/* bytes in a VM1 context */
;|*** /*extern char	VMn_cntxt_bytes;		/* bytes in a VM context */
;|*** extern char cntxt_pages;		/* pages in context */
;|*** extern char cntxt_bytes;		/* bytes in context */
;|*** extern unsigned short PF_Base;
;|*** extern unsigned short VM1_EMM_Pages;
;|*** /*extern unsigned short VM1_EMM_Offset;*/
;|*** extern long	page_frame_base[];
;|*** extern char	EMM_MPindex[];
;|*** extern long	OSEnabled;			/* OS/E function flag */
;|*** extern long	OSKey;				/* Key for OS/E function */
;|*** 
;|*** /******************************************************************************
;|*** 	EXTERNAL FUNCTIONS
;|***  ******************************************************************************/ 
;|*** extern	struct handle_ptr	*valid_handle();	/* validate handle */
;|*** extern	unsigned far	*source_addr(); 		/* get DS:SI far ptr */
;|*** extern	unsigned far	*dest_addr();			/* get ES:DI far ptr */
;|*** extern	unsigned	wcopyb();
;|*** extern	unsigned	copyout();
;|*** extern	unsigned short	Avail_Pages();
;|*** 
;|*** 
;|*** /******************************************************************************
;|*** 	ROUTINES
;|***  ******************************************************************************/ 
;|*** 
;|*** /*
;|***  * Reallocate Pages
;|***  *	parameters:
;|***  *		bx    -- new number of pages
;|***  *		dx    -- handle
;|***  *	returns:
;|***  *		bx    -- new number of pages
;|***  *
;|***  * Change the number of pages allocated to a handle.
;|***  *
;|***  * ISP 5/23/88 Updated for MEMM
;|***  */
;|*** ReallocatePages() 
;|*** {
; Line 132
	PUBLIC	_ReallocatePages
_ReallocatePages	PROC NEAR
	*** 000000	c8 0a 00 00 		enter	WORD PTR 10,0
	*** 000004	57 			push	di
	*** 000005	56 			push	si
;	register si = hp
;	hp_save = -4
;	new_size = -2
;	register di = n_pages
;	next = -10
;|*** #define	handle	((unsigned short)regp->hregs.x.rdx)
;|*** 
;|*** 	register struct handle_ptr	*hp;
;|*** 	struct handle_ptr		*hp_save;
;|*** 	unsigned			new_size;
;|*** 	register unsigned 		n_pages;
;|*** 	register unsigned 		next;
;|*** 
;|*** 	if ( (hp = valid_handle(handle)) == NULL_HANDLE )
; Line 141
	*** 000006	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00000a	26 ff 77 14 		push	WORD PTR es:[bx+20]
	*** 00000e	e8 00 00 		call	_valid_handle
	*** 000011	83 c4 02 		add	sp,2
	*** 000014	8b f0 			mov	si,ax
	*** 000016	81 fe ff 0f 		cmp	si,4095
	*** 00001a	75 03 			jne	$JCC26
	*** 00001c	e9 f9 00 		jmp	$I217
					$JCC26:
;|*** 		return;		/* (error code already set) */
; Line 142
	*** 00001f	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000023	a0 00 00 		mov	al,BYTE PTR _EMMstatus
	*** 000026	26 88 47 1d 		mov	BYTE PTR es:[bx+29],al
;|*** 
;|*** 	setAH((unsigned char)EMMstatus);	/* Assume success */
;|*** 	new_size = regp->hregs.x.rbx;
; Line 145
	*** 00002a	26 8b 47 10 		mov	ax,WORD PTR es:[bx+16]
	*** 00002e	89 46 fe 		mov	WORD PTR [bp-2],ax	;new_size
;|*** 	if ( new_size == hp->page_count )
; Line 146
	*** 000031	8b 44 02 		mov	ax,WORD PTR [si+2]
	*** 000034	39 46 fe 		cmp	WORD PTR [bp-2],ax	;new_size
	*** 000037	75 03 			jne	$JCC55
	*** 000039	e9 dc 00 		jmp	$I217
					$JCC55:
;|*** 		return;				/* do nothing... */
; Line 147
	*** 00003c	77 03 			ja	$JCC60
	*** 00003e	e9 c0 00 		jmp	$I204
					$JCC60:
;|*** 
;|*** 	if ( new_size > hp->page_count ) {
;|*** 		if ( new_size > total_pages ) {
; Line 150
	*** 000041	a1 00 00 		mov	ax,_total_pages
	*** 000044	39 46 fe 		cmp	WORD PTR [bp-2],ax	;new_size
	*** 000047	76 09 			jbe	$I205
;|*** 			setAH(NOT_ENOUGH_EXT_MEM);
; Line 151
	*** 000049	26 c6 47 1d 87 		mov	BYTE PTR es:[bx+29],135
;|*** 			return;
; Line 152
	*** 00004e	5e 			pop	si
	*** 00004f	5f 			pop	di
	*** 000050	c9 			leave	
	*** 000051	c3 			ret	
					$I205:
	*** 000052	8b 7e fe 		mov	di,WORD PTR [bp-2]	;new_size
	*** 000055	2b 7c 02 		sub	di,WORD PTR [si+2]
;|*** 		}
;|*** 		n_pages = new_size - hp->page_count;
;|*** 		if ( n_pages > Avail_Pages() ) {
; Line 155
	*** 000058	e8 00 00 		call	_Avail_Pages
	*** 00005b	3b c7 			cmp	ax,di
	*** 00005d	73 0d 			jae	$I206
;|*** 			setAH(NOT_ENOUGH_FREE_MEM);
; Line 156
	*** 00005f	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000063	26 c6 47 1d 88 		mov	BYTE PTR es:[bx+29],136
;|*** 			return;
; Line 157
	*** 000068	5e 			pop	si
	*** 000069	5f 			pop	di
	*** 00006a	c9 			leave	
	*** 00006b	c3 			ret	
					$I206:
	*** 00006c	83 7c 02 00 		cmp	WORD PTR [si+2],0
	*** 000070	75 08 			jne	$I207
;|*** 		}
;|*** 		if ( hp->page_count == 0 )
;|*** 			next = hp->page_index = emmpt_start;
; Line 160
	*** 000072	a1 00 00 		mov	ax,_emmpt_start
	*** 000075	89 04 			mov	WORD PTR [si],ax
	*** 000077	eb 06 			jmp	SHORT $L20001
	*** 000079	90 			nop	
					$I207:
;|*** 		else
;|*** 			next = hp->page_index + hp->page_count;
; Line 162
	*** 00007a	8b 44 02 		mov	ax,WORD PTR [si+2]
	*** 00007d	03 04 			add	ax,WORD PTR [si]
					$L20001:
	*** 00007f	89 46 f6 		mov	WORD PTR [bp-10],ax	;next
;|*** 		hp->page_count = new_size;
; Line 163
	*** 000082	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;new_size
	*** 000085	89 44 02 		mov	WORD PTR [si+2],ax
;|*** 		if ( next != emmpt_start ) {
; Line 164
	*** 000088	a1 00 00 		mov	ax,_emmpt_start
	*** 00008b	39 46 f6 		cmp	WORD PTR [bp-10],ax	;next
	*** 00008e	74 49 			je	$I209
;|*** 				/*
;|*** 				 * Must shuffle emm_page array to make room
;|*** 				 * for the extra pages.  wcopyb correctly
;|*** 				 * handles this case where the destination
;|*** 				 * overlaps the source.
;|*** 				 */
;|*** 			wcopyb(emm_page+next, emm_page+next+n_pages,
;|*** 			       emmpt_start - next);
; Line 172
	*** 000090	2b 46 f6 		sub	ax,WORD PTR [bp-10]	;next
	*** 000093	50 			push	ax
	*** 000094	8b 46 f6 		mov	ax,WORD PTR [bp-10]	;next
	*** 000097	03 c7 			add	ax,di
	*** 000099	d1 e0 			shl	ax,1
	*** 00009b	03 06 00 00 		add	ax,_emm_page
	*** 00009f	50 			push	ax
	*** 0000a0	8b 46 f6 		mov	ax,WORD PTR [bp-10]	;next
	*** 0000a3	d1 e0 			shl	ax,1
	*** 0000a5	03 06 00 00 		add	ax,_emm_page
	*** 0000a9	50 			push	ax
	*** 0000aa	e8 00 00 		call	_wcopyb
	*** 0000ad	83 c4 06 		add	sp,6
;|*** 			/* Now tell other handles where their pages went */
;|*** 			hp_save = hp;
; Line 174
	*** 0000b0	89 76 fc 		mov	WORD PTR [bp-4],si	;hp_save
;|*** 			for ( hp = handle_table;
;|*** 			      hp < &handle_table[handle_table_size]; hp++ )
; Line 176
	*** 0000b3	be 00 00 		mov	si,OFFSET _handle_table
	*** 0000b6	eb 11 			jmp	SHORT $F210
					$FC211:
;|*** 				if ( hp->page_index != NULL_PAGE &&
;|*** 				     hp->page_index >= next )
; Line 178
	*** 0000b8	83 3c ff 		cmp	WORD PTR [si],-1
	*** 0000bb	74 09 			je	$L20002
	*** 0000bd	8b 04 			mov	ax,WORD PTR [si]
	*** 0000bf	39 46 f6 		cmp	WORD PTR [bp-10],ax	;next
	*** 0000c2	77 02 			ja	$L20002
;|*** 					hp->page_index += n_pages;
; Line 179
	*** 0000c4	01 3c 			add	WORD PTR [si],di
;|*** 			hp = hp_save;
; Line 180
					$L20002:
	*** 0000c6	83 c6 04 		add	si,4
					$F210:
	*** 0000c9	a1 00 00 		mov	ax,_handle_table_size
	*** 0000cc	c1 e0 02 		shl	ax,2
	*** 0000cf	05 00 00 		add	ax,OFFSET _handle_table
	*** 0000d2	3b c6 			cmp	ax,si
	*** 0000d4	77 e2 			ja	$FC211
	*** 0000d6	8b 76 fc 		mov	si,WORD PTR [bp-4]	;hp_save
;|*** 		}
; Line 181
;|*** 		emmpt_start += n_pages;
; Line 182
					$I209:
	*** 0000d9	01 3e 00 00 		add	_emmpt_start,di
;|*** 		if ( get_pages(n_pages, next) == NULL_PAGE) { /* strange failure */
; Line 183
	*** 0000dd	ff 76 f6 		push	WORD PTR [bp-10]	;next
	*** 0000e0	57 			push	di
	*** 0000e1	e8 00 00 		call	_get_pages
	*** 0000e4	83 c4 04 		add	sp,4
	*** 0000e7	3d ff ff 		cmp	ax,-1
	*** 0000ea	75 2c 			jne	$I217
;|*** 			setAH(NOT_ENOUGH_FREE_MEM);
; Line 184
	*** 0000ec	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 0000f0	26 c6 47 1d 88 		mov	BYTE PTR es:[bx+29],136
;|*** 			new_size = hp->page_count - n_pages;  /* as it was! */
; Line 185
	*** 0000f5	8b 44 02 		mov	ax,WORD PTR [si+2]
	*** 0000f8	2b c7 			sub	ax,di
	*** 0000fa	89 46 fe 		mov	WORD PTR [bp-2],ax	;new_size
;|*** 			setBX(new_size);
; Line 186
	*** 0000fd	26 89 47 10 		mov	WORD PTR es:[bx+16],ax
;|*** 			goto shrink;			/* and undo damage */
; Line 187
					$I204:
;|*** 		}
;|*** 	} else {
; Line 189
;|*** 		/* Shrinking - make handle point to unwanted pages */
;|*** 	shrink:
;|*** 		hp->page_count -= new_size;
; Line 192
	*** 000101	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;new_size
	*** 000104	29 44 02 		sub	WORD PTR [si+2],ax
;|*** 		hp->page_index += new_size;
; Line 193
	*** 000107	01 04 			add	WORD PTR [si],ax
;|*** 		free_pages(hp);    /* free space in emm_page array */
; Line 194
	*** 000109	56 			push	si
	*** 00010a	e8 00 00 		call	_free_pages
	*** 00010d	83 c4 02 		add	sp,2
;|*** 		/* Undo damage to handle, the index was not changed */
;|*** 		hp->page_count = new_size;
; Line 196
	*** 000110	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;new_size
	*** 000113	89 44 02 		mov	WORD PTR [si+2],ax
;|*** 		hp->page_index -= new_size;
; Line 197
	*** 000116	29 04 			sub	WORD PTR [si],ax
;|*** 	}
; Line 198
					$I217:
;|*** 
;|*** #undef	handle
;|*** }
; Line 201
	*** 000118	5e 			pop	si
	*** 000119	5f 			pop	di
	*** 00011a	c9 			leave	
	*** 00011b	c3 			ret	

_ReallocatePages	ENDP
;|*** 
;|*** /*
;|***  * UndefinedFunction
;|***  *
;|***  * An undefined or unsupported function.
;|***  *
;|***  * 05/10/88  ISP  No update needed
;|***  */
;|*** UndefinedFunction() 
;|*** {
; Line 211
	PUBLIC	_UndefinedFunction
_UndefinedFunction	PROC NEAR
;|*** 	setAH(INVALID_FUNCTION);
; Line 212
	*** 00011c	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000120	26 c6 47 1d 84 		mov	BYTE PTR es:[bx+29],132
;|*** }
; Line 213
	*** 000125	c3 			ret	

_UndefinedFunction	ENDP
;|*** 
;|*** /*
;|***  * Get Mappable Physical Address Array
;|***  *	parameters:
;|***  *		al == 0
;|***  *		es:di -- destination
;|***  *	returns:
;|***  *		cx    -- number of mappable pages
;|***  *
;|***  *	parameters:
;|***  *		al == 1
;|***  *	returns:
;|***  *		cx    -- number of mappable pages
;|***  * 
;|***  * Get the number of mappable pages and the segment address for each
;|***  * physical page.
;|***  *
;|***  * ISP	5/23/88 Updated for MEMM.  u_ptr made into a far pointer.
;|***  */
;|*** GetMappablePAddrArray() 
;|*** {
; Line 234
	PUBLIC	_GetMappablePAddrArray
_GetMappablePAddrArray	PROC NEAR
	*** 000126	c8 0a 00 00 		enter	WORD PTR 10,0
;	u_ptr = -6
;	n_pages = -10
;	i = -2
;	mp = -8
;|*** 	unsigned far *u_ptr;
;|*** 	int	n_pages;
;|*** 	int	i;
;|*** 	struct mappable_page *mp = mappable_pages;
; Line 238
	*** 00012a	c7 46 f8 00 00 		mov	WORD PTR [bp-8],OFFSET _mappable_pages	;mp
;|*** 
;|*** 		n_pages = mappable_page_count;
; Line 240
	*** 00012f	a1 00 00 		mov	ax,_mappable_page_count
	*** 000132	89 46 f6 		mov	WORD PTR [bp-10],ax	;n_pages
;|*** 
;|*** 	if ( regp->hregs.h.ral == 0 ) {
; Line 242
	*** 000135	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000139	26 80 7f 1c 00 		cmp	BYTE PTR es:[bx+28],0
	*** 00013e	75 46 			jne	$I227
;|*** 		if ( n_pages > 0 ) {
; Line 243
	*** 000140	0b c0 			or	ax,ax
	*** 000142	7e 54 			jle	$I234
;|*** 			u_ptr = dest_addr();		/* ES:DI */
; Line 244
	*** 000144	e8 00 00 		call	_dest_addr
	*** 000147	89 46 fa 		mov	WORD PTR [bp-6],ax	;u_ptr
	*** 00014a	89 56 fc 		mov	WORD PTR [bp-4],dx
;|*** 			for (i=0 ; i < 48 ; i++)
; Line 245
	*** 00014d	c7 46 fe 00 00 		mov	WORD PTR [bp-2],0	;i
					$FC230:
;|*** 				if (EMM_MPindex[i] != -1)
; Line 246
	*** 000152	8b 5e fe 		mov	bx,WORD PTR [bp-2]	;i
	*** 000155	80 bf 00 00 ff 		cmp	BYTE PTR _EMM_MPindex[bx],255
	*** 00015a	74 1e 			je	$L20003
;|*** 					copyout(((struct mappable_page far *)u_ptr)++,
;|*** 						mp + EMM_MPindex[i],
;|*** 						sizeof(struct mappable_page) );
; Line 249
	*** 00015c	6a 04 			push	4
	*** 00015e	8a 87 00 00 		mov	al,BYTE PTR _EMM_MPindex[bx]
	*** 000162	98 			cbw	
	*** 000163	c1 e0 02 		shl	ax,2
	*** 000166	03 46 f8 		add	ax,WORD PTR [bp-8]	;mp
	*** 000169	50 			push	ax
	*** 00016a	ff 76 fc 		push	WORD PTR [bp-4]
	*** 00016d	ff 76 fa 		push	WORD PTR [bp-6]	;u_ptr
	*** 000170	83 46 fa 04 		add	WORD PTR [bp-6],4	;u_ptr
	*** 000174	e8 00 00 		call	_copyout
	*** 000177	83 c4 08 		add	sp,8
;|*** 		}
; Line 250
					$L20003:
	*** 00017a	ff 46 fe 		inc	WORD PTR [bp-2]	;i
	*** 00017d	83 7e fe 30 		cmp	WORD PTR [bp-2],48	;i
	*** 000181	7c cf 			jl	$FC230
;|*** 	} else if ( regp->hregs.h.ral != 1 ) {
; Line 251
	*** 000183	eb 13 			jmp	SHORT $I234
	*** 000185	90 			nop	
					$I227:
	*** 000186	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00018a	26 80 7f 1c 01 		cmp	BYTE PTR es:[bx+28],1
	*** 00018f	74 07 			je	$I234
;|*** 		setAH(INVALID_SUBFUNCTION);
; Line 252
	*** 000191	26 c6 47 1d 8f 		mov	BYTE PTR es:[bx+29],143
;|*** 		return;
; Line 253
	*** 000196	c9 			leave	
	*** 000197	c3 			ret	
					$I234:
	*** 000198	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00019c	8b 46 f6 		mov	ax,WORD PTR [bp-10]	;n_pages
	*** 00019f	26 89 47 18 		mov	WORD PTR es:[bx+24],ax
;|*** 	}
;|*** 	setCX(n_pages);
;|*** 	setAH((unsigned char)EMMstatus);
; Line 256
	*** 0001a3	a0 00 00 		mov	al,BYTE PTR _EMMstatus
	*** 0001a6	26 88 47 1d 		mov	BYTE PTR es:[bx+29],al
;|*** }
; Line 257
	*** 0001aa	c9 			leave	
	*** 0001ab	c3 			ret	

_GetMappablePAddrArray	ENDP
;|*** 
;|*** /*
;|***  * Get Expanded Memory Hardware Information
;|***  *	parameters:
;|***  *		al == 0
;|***  *		es:di -- user array
;|***  *	returns:
;|***  *		es:di[0] = raw page size in paragraphs
;|***  *		es:di[2] = number of EXTRA fast register sets
;|***  *		es:di[4] = number of bytes needed to save a context 
;|***  *		es:di[6] = number of settable DMA channels
;|***  *
;|***  *	parameters:
;|***  *		al == 1
;|***  *	returns:
;|***  *		bx = number of free raw pages
;|***  *		dx = total number of raw pages
;|***  *		
;|***  * ISP	5/23/88 Updated for MEMM. Made u_ptr into far ptr.
;|***  */
;|*** GetInformation() 
;|*** {
; Line 279
	PUBLIC	_GetInformation
_GetInformation	PROC NEAR
	*** 0001ac	c8 06 00 00 		enter	WORD PTR 6,0
;	u_ptr = -6
;	pages = -2
;|*** 	unsigned far *u_ptr;
;|*** 	unsigned pages;
;|*** 
;|*** 	if ( OSEnabled >= OS_DISABLED ) {
; Line 283
	*** 0001b0	83 3e 02 00 00 		cmp	WORD PTR _OSEnabled+2,0
	*** 0001b5	7c 15 			jl	$I239
	*** 0001b7	7f 07 			jg	$L20000
	*** 0001b9	83 3e 00 00 02 		cmp	WORD PTR _OSEnabled,2
	*** 0001be	72 0c 			jb	$I239
					$L20000:
;|*** 		setAH(ACCESS_DENIED);		/* Denied by operating system */
; Line 284
	*** 0001c0	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 0001c4	26 c6 47 1d a4 		mov	BYTE PTR es:[bx+29],164
;|*** 		return;
; Line 285
	*** 0001c9	c9 			leave	
	*** 0001ca	c3 			ret	
	*** 0001cb	90 			nop	
					$I239:
	*** 0001cc	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 0001d0	26 80 7f 1c 00 		cmp	BYTE PTR es:[bx+28],0
	*** 0001d5	75 2d 			jne	$I240
;|*** 	}
;|*** 
;|*** 	if ( regp->hregs.h.ral == 0 ) {
;|*** 		u_ptr = dest_addr();		/* ES:DI */
; Line 289
	*** 0001d7	e8 00 00 		call	_dest_addr
	*** 0001da	89 46 fa 		mov	WORD PTR [bp-6],ax	;u_ptr
	*** 0001dd	89 56 fc 		mov	WORD PTR [bp-4],dx
;|*** 		emm40_info[2] = (short)cntxt_bytes;	/* update size */
; Line 290
	*** 0001e0	a0 00 00 		mov	al,_cntxt_bytes
	*** 0001e3	98 			cbw	
	*** 0001e4	a3 04 00 		mov	WORD PTR _emm40_info+4,ax
;|*** 		copyout(u_ptr, emm40_info, sizeof(emm40_info));
; Line 291
	*** 0001e7	6a 0a 			push	10
	*** 0001e9	68 00 00 		push	OFFSET _emm40_info
	*** 0001ec	52 			push	dx
	*** 0001ed	ff 76 fa 		push	WORD PTR [bp-6]	;u_ptr
	*** 0001f0	e8 00 00 		call	_copyout
	*** 0001f3	83 c4 08 		add	sp,8
;|*** 		setAH((unsigned char)EMMstatus);
; Line 292
	*** 0001f6	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 0001fa	a0 00 00 		mov	al,BYTE PTR _EMMstatus
	*** 0001fd	26 88 47 1d 		mov	BYTE PTR es:[bx+29],al
;|*** 	} else if ( regp->hregs.h.ral == 1 ) {
; Line 293
	*** 000201	c9 			leave	
	*** 000202	c3 			ret	
	*** 000203	90 			nop	
					$I240:
	*** 000204	26 80 7f 1c 01 		cmp	BYTE PTR es:[bx+28],1
	*** 000209	75 05 			jne	$I242
;|*** 		GetUnallocatedPageCount();	/* Use existing code */
; Line 294
	*** 00020b	e8 00 00 		call	_GetUnallocatedPageCount
;|*** 	} else
; Line 295
	*** 00020e	c9 			leave	
	*** 00020f	c3 			ret	
					$I242:
;|*** 		setAH(INVALID_SUBFUNCTION);
; Line 296
	*** 000210	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000214	26 c6 47 1d 8f 		mov	BYTE PTR es:[bx+29],143
;|*** }
; Line 297
	*** 000219	c9 			leave	
	*** 00021a	c3 			ret	
	*** 00021b	90 			nop	

_GetInformation	ENDP
;|*** 
;|*** /*
;|***  * GetSetHandleAttribute
;|***  *
;|***  *	parameters:
;|***  *		al == 0
;|***  *	returns:
;|***  *		al == 0 -- volatile handles
;|***  *
;|***  *	parameters:
;|***  *		al == 1
;|***  *	returns:
;|***  *		ah = 91h -- Feature not supported
;|***  *
;|***  *	parameters:
;|***  *		al == 2
;|***  *	returns:
;|***  *		al == 0 -- Supports ONLY volatile handles
;|***  *
;|***  * 05/09/88 ISP No update needed
;|***  */
;|*** GetSetHandleAttribute()
;|*** {
; Line 320
	PUBLIC	_GetSetHandleAttribute
_GetSetHandleAttribute	PROC NEAR
;|*** #define	handle	((unsigned short)regp->hregs.x.rdx)
;|*** 
;|*** 	if ( regp->hregs.h.ral == 0 ) {
; Line 323
	*** 00021c	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000220	26 80 7f 1c 00 		cmp	BYTE PTR es:[bx+28],0
	*** 000225	75 1f 			jne	$I247
;|*** 		if (valid_handle(handle) == NULL_HANDLE)
; Line 324
	*** 000227	26 ff 77 14 		push	WORD PTR es:[bx+20]
	*** 00022b	e8 00 00 		call	_valid_handle
	*** 00022e	83 c4 02 		add	sp,2
	*** 000231	3d ff 0f 		cmp	ax,4095
	*** 000234	74 2e 			je	$I253
;|*** 			return;						/* (error code already set) */
; Line 325
	*** 000236	c4 1e 00 00 		les	bx,DWORD PTR _regp
					$L20004:
	*** 00023a	8a 26 00 00 		mov	ah,BYTE PTR _EMMstatus
	*** 00023e	2a c0 			sub	al,al
	*** 000240	26 89 47 1c 		mov	WORD PTR es:[bx+28],ax
;|*** 		setAX(EMMstatus << 8);		/* AL = 0 [volatile attribute] */
;|*** 	} else if ( regp->hregs.h.ral == 1 ) {
; Line 327
	*** 000244	c3 			ret	
	*** 000245	90 			nop	
					$I247:
	*** 000246	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00024a	26 80 7f 1c 01 		cmp	BYTE PTR es:[bx+28],1
	*** 00024f	75 07 			jne	$I250
;|*** 		setAH(FEATURE_NOT_SUPPORTED);
; Line 328
	*** 000251	26 c6 47 1d 91 		mov	BYTE PTR es:[bx+29],145
;|*** 	} else if ( regp->hregs.h.ral == 2 ) {
; Line 329
	*** 000256	c3 			ret	
	*** 000257	90 			nop	
					$I250:
	*** 000258	26 80 7f 1c 02 		cmp	BYTE PTR es:[bx+28],2
	*** 00025d	74 db 			je	$L20004
;|*** 		setAX(EMMstatus << 8);		/* AL = 0 [volatile attribute] */
;|*** 	} else
;|*** 		setAH(INVALID_SUBFUNCTION);
; Line 332
	*** 00025f	26 c6 47 1d 8f 		mov	BYTE PTR es:[bx+29],143
					$I253:
;|*** 
;|*** #undef	handle
;|*** }
; Line 335
	*** 000264	c3 			ret	
	*** 000265	90 			nop	

_GetSetHandleAttribute	ENDP
;|*** 
;|*** 
;|*** 
;|*** 
;|*** /*
;|***  * GetSetHandleName
;|***  *
;|***  *  Subfunction 0 Gets the name of a given handle
;|***  *  Subfunction 1 Sets a new name for handle
;|***  *
;|***  *	parameters:
;|***  *		al == 0
;|***  *		es:di == Data area to copy handle name to
;|***  *		dx    -- handle
;|***  *	returns:
;|***  *		[es:di] == Name of DX handle
;|***  *
;|***  *	parameters:
;|***  *		al == 1
;|***  *		ds:si == new handle name
;|***  *		dx    -- handle
;|***  *	returns:
;|***  *		ah = Status
;|***  *
;|***  * ISP 5/23/88 Updated for MEMM. Name made into far *. Copyin routine used
;|***  *	       to copy name in into handle name table.
;|***  */
;|*** GetSetHandleName()
;|*** {
; Line 364
	PUBLIC	_GetSetHandleName
_GetSetHandleName	PROC NEAR
	*** 000266	c8 06 00 00 		enter	WORD PTR 6,0
	*** 00026a	56 			push	si
;	register si = handle
;	Name = -4
;|*** 	register unsigned short handle = ((unsigned short)regp->hregs.x.rdx);
; Line 365
	*** 00026b	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00026f	26 8b 77 14 		mov	si,WORD PTR es:[bx+20]
;|*** 	register char far *Name;
;|*** 
;|***     /* Validate subfunction */
;|*** 	if ( (regp->hregs.h.ral != 0) && (regp->hregs.h.ral != 1) ) {
; Line 369
	*** 000273	26 80 7f 1c 00 		cmp	BYTE PTR es:[bx+28],0
	*** 000278	74 0a 			je	$I258
	*** 00027a	26 80 7f 1c 01 		cmp	BYTE PTR es:[bx+28],1
	*** 00027f	74 03 			je	$JCC639
	*** 000281	e9 9a 00 		jmp	$L20005
					$JCC639:
					$I258:
	*** 000284	56 			push	si
	*** 000285	e8 00 00 		call	_valid_handle
	*** 000288	83 c4 02 		add	sp,2
	*** 00028b	3d ff 0f 		cmp	ax,4095
	*** 00028e	75 03 			jne	$JCC654
	*** 000290	e9 90 00 		jmp	$I273
					$JCC654:
;|*** 		setAH(INVALID_SUBFUNCTION);
;|*** 		return;
;|*** 	}
;|*** 
;|***     /* Validate handle */
;|*** 
;|*** 	if ( valid_handle(handle) == NULL_HANDLE )
;|*** 		return; 	/* (error code already set) */
; Line 377
	*** 000293	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000297	26 80 7f 1c 00 		cmp	BYTE PTR es:[bx+28],0
	*** 00029c	75 2e 			jne	$I260
;|*** 
;|***     /* Implement subfunctions 0 and 1 */
;|*** 	if ( regp->hregs.h.ral == 0 ) {
;|*** 		Name = (char far *)dest_addr(); 	   /* ES:DI */
; Line 381
	*** 00029e	e8 00 00 		call	_dest_addr
	*** 0002a1	89 46 fc 		mov	WORD PTR [bp-4],ax	;Name
	*** 0002a4	89 56 fe 		mov	WORD PTR [bp-2],dx
;|*** 		copyout(Name, Handle_Name_Table[handle & 0xFF], Handle_Name_Len);
; Line 382
	*** 0002a7	6a 08 			push	8
	*** 0002a9	8b c6 			mov	ax,si
	*** 0002ab	2a e4 			sub	ah,ah
	*** 0002ad	c1 e0 03 		shl	ax,3
	*** 0002b0	05 00 00 		add	ax,OFFSET _Handle_Name_Table
	*** 0002b3	50 			push	ax
	*** 0002b4	52 			push	dx
	*** 0002b5	ff 76 fc 		push	WORD PTR [bp-4]	;Name
	*** 0002b8	e8 00 00 		call	_copyout
					$L20006:
	*** 0002bb	83 c4 08 		add	sp,8
;|*** 		setAH((unsigned char)EMMstatus);
; Line 383
	*** 0002be	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 0002c2	a0 00 00 		mov	al,BYTE PTR _EMMstatus
	*** 0002c5	26 88 47 1d 		mov	BYTE PTR es:[bx+29],al
;|*** 	} else if ( regp->hregs.h.ral == 1 ) {
; Line 384
	*** 0002c9	5e 			pop	si
	*** 0002ca	c9 			leave	
	*** 0002cb	c3 			ret	
					$I260:
	*** 0002cc	26 80 7f 1c 01 		cmp	BYTE PTR es:[bx+28],1
	*** 0002d1	75 47 			jne	$I262
;|*** 		GetHandleDirectory();		/* See if already there */
; Line 385
	*** 0002d3	e8 00 00 		call	_GetHandleDirectory
;|*** 		switch ( regp->hregs.h.rah ) {
; Line 386
	*** 0002d6	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 0002da	26 8a 47 1d 		mov	al,BYTE PTR es:[bx+29]
	*** 0002de	2a e4 			sub	ah,ah
	*** 0002e0	3d a0 00 		cmp	ax,160
	*** 0002e3	74 17 			je	$SC268
	*** 0002e5	3d a1 00 		cmp	ax,161
	*** 0002e8	74 39 			je	$I273
;|*** 		case NAMED_HANDLE_NOT_FOUND:
;|*** 			break;
;|*** 		case DUPLICATE_HANDLE_NAMES:
;|*** 			return;
;|*** 		default:
;|*** 			if ( handle == regp->hregs.x.rdx )
; Line 392
	*** 0002ea	26 39 77 14 		cmp	WORD PTR es:[bx+20],si
	*** 0002ee	74 0c 			je	$SC268
;|*** 				break;		/* same handle, OK */
; Line 393
	*** 0002f0	26 89 77 14 		mov	WORD PTR es:[bx+20],si
;|*** 			regp->hregs.x.rdx = handle;
;|*** 			setAH(DUPLICATE_HANDLE_NAMES);
; Line 395
	*** 0002f4	26 c6 47 1d a1 		mov	BYTE PTR es:[bx+29],161
;|*** 			return;
; Line 396
	*** 0002f9	5e 			pop	si
	*** 0002fa	c9 			leave	
	*** 0002fb	c3 			ret	
					$SC268:
;|*** 		}
;|*** 		Name = (char far *)source_addr();
; Line 398
	*** 0002fc	e8 00 00 		call	_source_addr
	*** 0002ff	89 46 fc 		mov	WORD PTR [bp-4],ax	;Name
	*** 000302	89 56 fe 		mov	WORD PTR [bp-2],dx
;|*** 		copyin(Handle_Name_Table[handle & 0xFF], Name, Handle_Name_Len);
; Line 399
	*** 000305	6a 08 			push	8
	*** 000307	52 			push	dx
	*** 000308	50 			push	ax
	*** 000309	8b c6 			mov	ax,si
	*** 00030b	2a e4 			sub	ah,ah
	*** 00030d	c1 e0 03 		shl	ax,3
	*** 000310	05 00 00 		add	ax,OFFSET _Handle_Name_Table
	*** 000313	50 			push	ax
	*** 000314	e8 00 00 		call	_copyin
	*** 000317	eb a2 			jmp	SHORT $L20006
	*** 000319	90 			nop	
					$I262:
;|*** 		setAH((unsigned char)EMMstatus);
;|*** 	} else
;|*** 		setAH(INVALID_SUBFUNCTION);
; Line 402
	*** 00031a	c4 1e 00 00 		les	bx,DWORD PTR _regp
					$L20005:
	*** 00031e	26 c6 47 1d 8f 		mov	BYTE PTR es:[bx+29],143
					$I273:
;|*** 
;|*** }
; Line 404
	*** 000323	5e 			pop	si
	*** 000324	c9 			leave	
	*** 000325	c3 			ret	

_GetSetHandleName	ENDP
;|*** 
;|*** 
;|*** 
;|*** 
;|*** /*
;|***  * GetHandleDirectory
;|***  *
;|***  *  Subfunction 0 Returns a directory of handles and handle names
;|***  *  Subfunction 1 Returns the handle specified by the name at [ds:si]
;|***  *
;|***  *	parameters:
;|***  *		al == 0
;|***  *		es:di == Data area to copy handle name to
;|***  *	returns:
;|***  *		al == Number of entries in the handle_dir array
;|***  *		[es:di] == Handle_Dir array
;|***  *
;|***  *	parameters:
;|***  *		al == 1
;|***  *		[ds:si] == Handle name to locate
;|***  *	returns:
;|***  *		ah == Status
;|***  *
;|***  *	parameters:
;|***  *		al == 2
;|***  *	returns:
;|***  *		bx == Total handles in system
;|***  *
;|***  * ISP 5/23/88 Updated for MEMM.  nameaddress and dir_entry made into far *
;|***  *	       copyin routine used to copy name into local area for search.
;|***  */
;|*** GetHandleDirectory()
;|*** {
; Line 437
	PUBLIC	_GetHandleDirectory
_GetHandleDirectory	PROC NEAR
	*** 000326	c8 0e 00 00 		enter	WORD PTR 14,0
	*** 00032a	56 			push	si
;	NameAddress = -8
;	register si = hp
;	Dir_Entry = -4
;	Handle_Num = -12
;	Found = -14
;|*** 	char far			*NameAddress;
;|*** 	register struct handle_ptr	*hp;
;|*** 	struct Handle_Dir_Entry far	*Dir_Entry;
;|*** 	unsigned short			Handle_Num, Found;
;|*** /*
;|***  * since all local variables are allocated on stack (SS seg)
;|***  * and DS and SS has grown apart (ie DS != SS),
;|***  * we need variables in DS seg (ie static variables) to pass
;|***  * to copyout(),copyin() and Names_Match() which expects those
;|***  * parameters that are near pointers to be in DS
;|***  *
;|***  * PC 08/03/88
;|***  */
;|*** 	static Handle_Name			Name;
;|*** 	static unsigned short		Real_Handle;
;|*** 
;|*** 	if ( regp->hregs.h.ral == 0 ) {
; Line 454
	*** 00032b	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00032f	26 80 7f 1c 00 		cmp	BYTE PTR es:[bx+28],0
	*** 000334	75 74 			jne	$I282
;|*** 		Dir_Entry = (struct Handle_Dir_Entry far *)dest_addr();
; Line 455
	*** 000336	e8 00 00 		call	_dest_addr
	*** 000339	89 46 fc 		mov	WORD PTR [bp-4],ax	;Dir_Entry
	*** 00033c	89 56 fe 		mov	WORD PTR [bp-2],dx
;|*** 		hp = handle_table;
; Line 456
	*** 00033f	be 00 00 		mov	si,OFFSET _handle_table
;|*** 		for (Handle_Num = 0; Handle_Num < handle_table_size; Handle_Num++) {
; Line 457
	*** 000342	c7 46 f4 00 00 		mov	WORD PTR [bp-12],0	;Handle_Num
	*** 000347	eb 44 			jmp	SHORT $F283
	*** 000349	90 			nop	
					$FC284:
;|*** 		    if ( hp->page_index != NULL_PAGE) {
; Line 458
	*** 00034a	83 3c ff 		cmp	WORD PTR [si],-1
	*** 00034d	74 38 			je	$I286
;|*** 			Real_Handle =  Handle_Num;
; Line 459
	*** 00034f	8b 46 f4 		mov	ax,WORD PTR [bp-12]	;Handle_Num
	*** 000352	a3 08 00 		mov	$S281_Real_Handle,ax
;|*** 			copyout(Dir_Entry, &Real_Handle, sizeof(short));
; Line 460
	*** 000355	6a 02 			push	2
	*** 000357	68 08 00 		push	OFFSET DGROUP:$S281_Real_Handle
	*** 00035a	ff 76 fe 		push	WORD PTR [bp-2]
	*** 00035d	ff 76 fc 		push	WORD PTR [bp-4]	;Dir_Entry
	*** 000360	e8 00 00 		call	_copyout
	*** 000363	83 c4 08 		add	sp,8
;|*** 			copyout(Dir_Entry->Dir_Handle_Name, Handle_Name_Table[Handle_Num], Handle_Name_Len);
; Line 461
	*** 000366	6a 08 			push	8
	*** 000368	8b 46 f4 		mov	ax,WORD PTR [bp-12]	;Handle_Num
	*** 00036b	c1 e0 03 		shl	ax,3
	*** 00036e	05 00 00 		add	ax,OFFSET _Handle_Name_Table
	*** 000371	50 			push	ax
	*** 000372	8b 46 fc 		mov	ax,WORD PTR [bp-4]	;Dir_Entry
	*** 000375	8b 56 fe 		mov	dx,WORD PTR [bp-2]
	*** 000378	05 02 00 		add	ax,2
	*** 00037b	52 			push	dx
	*** 00037c	50 			push	ax
	*** 00037d	e8 00 00 		call	_copyout
	*** 000380	83 c4 08 		add	sp,8
;|*** 			Dir_Entry++;
; Line 462
	*** 000383	83 46 fc 0a 		add	WORD PTR [bp-4],10	;Dir_Entry
;|*** 		    } hp++;
; Line 463
					$I286:
	*** 000387	83 c6 04 		add	si,4
;|*** 		} setAX((EMMstatus << 8) + handle_count);
; Line 464
	*** 00038a	ff 46 f4 		inc	WORD PTR [bp-12]	;Handle_Num
					$F283:
	*** 00038d	a1 00 00 		mov	ax,_handle_table_size
	*** 000390	39 46 f4 		cmp	WORD PTR [bp-12],ax	;Handle_Num
	*** 000393	72 b5 			jb	$FC284
	*** 000395	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000399	8a 26 00 00 		mov	ah,BYTE PTR _EMMstatus
	*** 00039d	2a c0 			sub	al,al
	*** 00039f	03 06 00 00 		add	ax,_handle_count
	*** 0003a3	26 89 47 1c 		mov	WORD PTR es:[bx+28],ax
;|*** 	} else if ( regp->hregs.h.ral == 1 ) {
; Line 465
	*** 0003a7	5e 			pop	si
	*** 0003a8	c9 			leave	
	*** 0003a9	c3 			ret	
					$I282:
	*** 0003aa	26 80 7f 1c 01 		cmp	BYTE PTR es:[bx+28],1
	*** 0003af	74 03 			je	$JCC943
	*** 0003b1	e9 9a 00 		jmp	$I288
					$JCC943:
;|*** 		NameAddress = (char far *)source_addr();
; Line 466
	*** 0003b4	e8 00 00 		call	_source_addr
	*** 0003b7	89 46 f8 		mov	WORD PTR [bp-8],ax	;NameAddress
	*** 0003ba	89 56 fa 		mov	WORD PTR [bp-6],dx
;|*** 		copyin(Name, NameAddress, Handle_Name_Len);
; Line 467
	*** 0003bd	6a 08 			push	8
	*** 0003bf	52 			push	dx
	*** 0003c0	50 			push	ax
	*** 0003c1	68 00 00 		push	OFFSET DGROUP:$S280_Name
	*** 0003c4	e8 00 00 		call	_copyin
	*** 0003c7	83 c4 08 		add	sp,8
;|*** 		hp = handle_table;
; Line 468
	*** 0003ca	be 00 00 		mov	si,OFFSET _handle_table
;|*** 		Found = 0;
; Line 469
	*** 0003cd	c7 46 f2 00 00 		mov	WORD PTR [bp-14],0	;Found
;|*** 		Handle_Num = 0;
; Line 470
	*** 0003d2	c7 46 f4 00 00 		mov	WORD PTR [bp-12],0	;Handle_Num
;|*** 		while ((Handle_Num < handle_table_size) && (Found < 2)) {
; Line 471
	*** 0003d7	eb 32 			jmp	SHORT $L20008
	*** 0003d9	90 			nop	
					$FC290:
	*** 0003da	83 7e f2 02 		cmp	WORD PTR [bp-14],2	;Found
	*** 0003de	73 33 			jae	$FB291
;|*** 		    if ( hp->page_index != NULL_PAGE ) {
; Line 472
	*** 0003e0	83 3c ff 		cmp	WORD PTR [si],-1
	*** 0003e3	74 20 			je	$I294
;|*** 			if (Names_Match(Name, Handle_Name_Table[Handle_Num])) {
; Line 473
	*** 0003e5	8b 46 f4 		mov	ax,WORD PTR [bp-12]	;Handle_Num
	*** 0003e8	c1 e0 03 		shl	ax,3
	*** 0003eb	05 00 00 		add	ax,OFFSET _Handle_Name_Table
	*** 0003ee	50 			push	ax
	*** 0003ef	68 00 00 		push	OFFSET DGROUP:$S280_Name
	*** 0003f2	e8 00 00 		call	_Names_Match
	*** 0003f5	83 c4 04 		add	sp,4
	*** 0003f8	0b c0 			or	ax,ax
	*** 0003fa	74 09 			je	$I294
;|*** 			    Found++;
; Line 474
	*** 0003fc	ff 46 f2 		inc	WORD PTR [bp-14]	;Found
;|*** 			    Real_Handle = Handle_Num;
; Line 475
	*** 0003ff	8b 46 f4 		mov	ax,WORD PTR [bp-12]	;Handle_Num
	*** 000402	a3 08 00 		mov	$S281_Real_Handle,ax
;|*** 			}
; Line 476
;|*** 		    } hp++;
; Line 477
					$I294:
	*** 000405	83 c6 04 		add	si,4
;|*** 		    Handle_Num++;
; Line 478
	*** 000408	ff 46 f4 		inc	WORD PTR [bp-12]	;Handle_Num
;|*** 		}
; Line 479
					$L20008:
	*** 00040b	a1 00 00 		mov	ax,_handle_table_size
	*** 00040e	39 46 f4 		cmp	WORD PTR [bp-12],ax	;Handle_Num
	*** 000411	72 c7 			jb	$FC290
					$FB291:
;|*** 		switch (Found) {
; Line 480
	*** 000413	8b 46 f2 		mov	ax,WORD PTR [bp-14]	;Found
	*** 000416	0b c0 			or	ax,ax
	*** 000418	74 12 			je	$SC299
	*** 00041a	3d 01 00 		cmp	ax,1
	*** 00041d	74 19 			je	$SC300
;|*** 		    case 0:
;|*** 			setAH((unsigned char)NAMED_HANDLE_NOT_FOUND);
;|*** 			break;
;|*** 		    case 1:
;|*** 			setDX(Real_Handle);
;|*** 			setAH((unsigned char)EMMstatus);
;|*** 			break;
;|*** 		    default:
;|*** 			setAH((unsigned char)DUPLICATE_HANDLE_NAMES);
; Line 489
	*** 00041f	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000423	26 c6 47 1d a1 		mov	BYTE PTR es:[bx+29],161
;|*** 		}
; Line 490
	*** 000428	5e 			pop	si
	*** 000429	c9 			leave	
	*** 00042a	c3 			ret	
	*** 00042b	90 			nop	
					$SC299:
;|*** 			setAH((unsigned char)NAMED_HANDLE_NOT_FOUND);
; Line 482
	*** 00042c	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000430	26 c6 47 1d a0 		mov	BYTE PTR es:[bx+29],160
;|*** 			break;
;|*** 		    case 1:
;|*** 			setDX(Real_Handle);
;|*** 			setAH((unsigned char)EMMstatus);
;|*** 			break;
;|*** 		    default:
;|*** 			setAH((unsigned char)DUPLICATE_HANDLE_NAMES);
;|*** 		}
;|*** 
;|*** 	} else if ( regp->hregs.h.ral == 2 ) {
; Line 492
	*** 000435	5e 			pop	si
	*** 000436	c9 			leave	
	*** 000437	c3 			ret	
					$SC300:
;|*** 			setDX(Real_Handle);
; Line 485
	*** 000438	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00043c	a1 08 00 		mov	ax,$S281_Real_Handle
	*** 00043f	26 89 47 14 		mov	WORD PTR es:[bx+20],ax
;|*** 			setAH((unsigned char)EMMstatus);
; Line 486
					$L20009:
	*** 000443	a0 00 00 		mov	al,BYTE PTR _EMMstatus
	*** 000446	26 88 47 1d 		mov	BYTE PTR es:[bx+29],al
;|*** 			break;
; Line 487
	*** 00044a	5e 			pop	si
	*** 00044b	c9 			leave	
	*** 00044c	c3 			ret	
	*** 00044d	90 			nop	
					$I288:
;|*** 		    default:
;|*** 			setAH((unsigned char)DUPLICATE_HANDLE_NAMES);
;|*** 		}
;|*** 
;|*** 	} else if ( regp->hregs.h.ral == 2 ) {
; Line 492
	*** 00044e	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 000452	26 80 7f 1c 02 		cmp	BYTE PTR es:[bx+28],2
	*** 000457	75 09 			jne	$I303
;|*** 		setBX(handle_table_size);
; Line 493
	*** 000459	a1 00 00 		mov	ax,_handle_table_size
	*** 00045c	26 89 47 10 		mov	WORD PTR es:[bx+16],ax
	*** 000460	eb e1 			jmp	SHORT $L20009
					$I303:
;|*** 		setAH((unsigned char)EMMstatus);
;|*** 	} else
;|*** 		setAH(INVALID_SUBFUNCTION);
; Line 496
	*** 000462	26 c6 47 1d 8f 		mov	BYTE PTR es:[bx+29],143
;|*** 
;|*** #undef	handle
;|*** }
; Line 499
	*** 000467	5e 			pop	si
	*** 000468	c9 			leave	
	*** 000469	c3 			ret	

_GetHandleDirectory	ENDP
;|*** 
;|*** /*
;|***  * Prepare For Warm Boot
;|***  *
;|***  *	Always ready to reboot the system so just return status = OK
;|***  *
;|***  *	parameters:
;|***  *		None
;|***  *	returns:
;|***  *		AH = EMMstatus
;|***  *
;|***  * 05/09/88 ISP No update needed.
;|***  *
;|***  */
;|*** PrepareForWarmBoot()
;|*** {
; Line 515
	PUBLIC	_PrepareForWarmBoot
_PrepareForWarmBoot	PROC NEAR
;|*** 	setAH((unsigned char)EMMstatus);
; Line 516
	*** 00046a	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00046e	a0 00 00 		mov	al,BYTE PTR _EMMstatus
	*** 000471	26 88 47 1d 		mov	BYTE PTR es:[bx+29],al
;|*** }
; Line 517
	*** 000475	c3 			ret	

_PrepareForWarmBoot	ENDP
;|*** 
;|*** /*
;|***  * Enable/Disable OS/E Function Set Functions
;|***  *
;|***  *	Enable/Disable access to functions 26, 28 and 30
;|***  *
;|***  *	parameters:
;|***  *		AL = 0		Enable Functions
;|***  *		AL = 1		Disable Functions
;|***  *		AL = 2		Return Access Key
;|***  *		BX, CX		Access Key
;|***  *	returns:
;|***  *		AH = EMMstatus
;|***  *		BX, CX		Access Key if successful
;|***  *
;|***  * 05/09/88 ISP Updated for MEMM. Removed check for pCurVMID
;|***  *
;|***  */
;|*** OSDisable()
;|*** {
; Line 537
	PUBLIC	_OSDisable
_OSDisable	PROC NEAR
	*** 000476	c8 02 00 00 		enter	WORD PTR 2,0
;	function = -2
;|*** 	unsigned char function = regp->hregs.h.ral;
; Line 538
	*** 00047a	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00047e	26 8a 47 1c 		mov	al,BYTE PTR es:[bx+28]
	*** 000482	88 46 fe 		mov	BYTE PTR [bp-2],al	;function
;|*** 
;|*** 	if ( function > 2 ) {
; Line 540
	*** 000485	3c 02 			cmp	al,2
	*** 000487	76 07 			jbe	$I310
;|*** 		setAH(INVALID_SUBFUNCTION);
; Line 541
	*** 000489	26 c6 47 1d 8f 		mov	BYTE PTR es:[bx+29],143
;|*** 		return;
; Line 542
	*** 00048e	c9 			leave	
	*** 00048f	c3 			ret	
					$I310:
	*** 000490	a1 00 00 		mov	ax,WORD PTR _OSEnabled
	*** 000493	0b 06 02 00 		or	ax,WORD PTR _OSEnabled+2
	*** 000497	75 35 			jne	$I311
;|*** 	}
;|*** 
;|*** 	if ( OSEnabled == OS_IDLE ) {		/* First invocation */
;|*** 		if ( function == 2 ) {
; Line 546
	*** 000499	80 7e fe 02 		cmp	BYTE PTR [bp-2],2	;function
	*** 00049d	75 07 			jne	$I312
;|*** 			setAH(ACCESS_DENIED);
; Line 547
					$L20010:
	*** 00049f	26 c6 47 1d a4 		mov	BYTE PTR es:[bx+29],164
;|*** 			return;
; Line 548
	*** 0004a4	c9 			leave	
	*** 0004a5	c3 			ret	
					$I312:
	*** 0004a6	e8 00 00 		call	_Get_Key_Val
	*** 0004a9	99 			cwd	
	*** 0004aa	a3 00 00 		mov	WORD PTR _OSKey,ax
	*** 0004ad	89 16 02 00 		mov	WORD PTR _OSKey+2,dx
;|*** 		}
;|*** 		OSKey = Get_Key_Val();		/* Suitably random number */
;|*** 		regp->hregs.x.rbx = (short)OSKey;
; Line 551
	*** 0004b1	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 0004b5	26 89 47 10 		mov	WORD PTR es:[bx+16],ax
;|*** 		regp->hregs.x.rcx = (short)(OSKey >> 16);
; Line 552
	*** 0004b9	8b c2 			mov	ax,dx
	*** 0004bb	26 89 47 18 		mov	WORD PTR es:[bx+24],ax
;|*** 	} else {				/* Check Key */
; Line 553
					$I315:
;|*** 		if ( (short)OSKey != regp->hregs.x.rbx
;|*** 		     || (short)(OSKey >> 16) != regp->hregs.x.rcx ) {
;|*** 			setAH(ACCESS_DENIED);
;|*** 			return;
;|*** 		}
;|*** 	}
;|*** 	if ( function == 0 )			/* enable */
; Line 560
	*** 0004bf	80 7e fe 00 		cmp	BYTE PTR [bp-2],0	;function
	*** 0004c3	75 23 			jne	$I317
;|*** 		OSEnabled = 1;
; Line 561
	*** 0004c5	c7 06 00 00 01 00 	mov	WORD PTR _OSEnabled,1
	*** 0004cb	eb 27 			jmp	SHORT $L20011
	*** 0004cd	90 			nop	
					$I311:
;|*** 	} else {				/* Check Key */
; Line 553
;|*** 		if ( (short)OSKey != regp->hregs.x.rbx
;|*** 		     || (short)(OSKey >> 16) != regp->hregs.x.rcx ) {
; Line 555
	*** 0004ce	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 0004d2	a1 00 00 		mov	ax,WORD PTR _OSKey
	*** 0004d5	26 39 47 10 		cmp	WORD PTR es:[bx+16],ax
	*** 0004d9	75 c4 			jne	$L20010
	*** 0004db	26 8b 47 18 		mov	ax,WORD PTR es:[bx+24]
	*** 0004df	39 06 02 00 		cmp	WORD PTR _OSKey+2,ax
	*** 0004e3	74 da 			je	$I315
	*** 0004e5	eb b8 			jmp	SHORT $L20010
	*** 0004e7	90 			nop	
					$I317:
;|*** 			setAH(ACCESS_DENIED);
;|*** 			return;
;|*** 		}
;|*** 	}
;|*** 	if ( function == 0 )			/* enable */
;|*** 		OSEnabled = 1;
;|*** 	else if ( function == 1 )		/* disable */
; Line 562
	*** 0004e8	80 7e fe 01 		cmp	BYTE PTR [bp-2],1	;function
	*** 0004ec	75 0e 			jne	$I319
;|*** 		OSEnabled = 2;
; Line 563
	*** 0004ee	c7 06 00 00 02 00 	mov	WORD PTR _OSEnabled,2
					$L20011:
	*** 0004f4	c7 06 02 00 00 00 	mov	WORD PTR _OSEnabled+2,0
;|*** 	else if ( function == 2 )		/* return key */
; Line 564
	*** 0004fa	eb 0e 			jmp	SHORT $I321
					$I319:
	*** 0004fc	80 7e fe 02 		cmp	BYTE PTR [bp-2],2	;function
	*** 000500	75 08 			jne	$I321
;|*** 		OSEnabled = 0;
; Line 565
	*** 000502	2b c0 			sub	ax,ax
	*** 000504	a3 02 00 		mov	WORD PTR _OSEnabled+2,ax
	*** 000507	a3 00 00 		mov	WORD PTR _OSEnabled,ax
;|*** 
;|*** 	setAH((unsigned char)EMMstatus);
; Line 567
					$I321:
	*** 00050a	c4 1e 00 00 		les	bx,DWORD PTR _regp
	*** 00050e	a0 00 00 		mov	al,BYTE PTR _EMMstatus
	*** 000511	26 88 47 1d 		mov	BYTE PTR es:[bx+29],al
;|*** }
; Line 568
	*** 000515	c9 			leave	
	*** 000516	c3 			ret	
	*** 000517	90 			nop	

_OSDisable	ENDP
_TEXT	ENDS
END
