     1                                  ;	SCCSID = @(#)handle.asm 1.1 85/04/10
     2                                  ;TITLE	HANDLE - Handle-related system calls
     3                                  ;NAME	HANDLE
     4                                  ;
     5                                  ; Handle related system calls for MSDOS 2.X.  Only top-level system calls
     6                                  ; are present.	I/O specs are defined in DISPATCH.  The system calls are:
     7                                  ;
     8                                  ;   $Close     written
     9                                  ;   $Commit    written		  DOS 3.3  F.C. 6/4/86
    10                                  ;   $ExtHandle written		  DOS 3.3  F.C. 6/4/86
    11                                  ;   $Read      written
    12                                  ;   Align_Buffer		  DOS 4.00
    13                                  ;   $Write     written
    14                                  ;   $LSeek     written
    15                                  ;   $FileTimes written
    16                                  ;   $Dup       written
    17                                  ;   $Dup2      written
    18                                  ;
    19                                  ;   Revision history:
    20                                  ;
    21                                  ;	Created: MZ 28 March 1983
    22                                  ;		 MZ 15 Dec   1982 Jeff Harbers and Multiplan hard disk copy
    23                                  ;				  rely on certain values in AX when $CLOSE
    24                                  ;				  succeeds even though we document it as
    25                                  ;				  always trashing AX.
    26                                  ;
    27                                  ;	A000  version 4.00  Jan. 1988
    28                                  ;
    29                                  
    30                                  [list -]
    30          ******************       warning: redefining multi-line macro `struc' [-w+pp-macro-redef-multi]
    14                              <4> [list -]
    14                              <3> [list -]
     3                              <2> 
     4                              <2> addsection DOSSTART, align=16 PUBLIC class=DOSSTART
     5                              <2> ; (no prior section) ; DOSSTART		ENDS
     6                              <2> 
     7                              <2> addsection DOSSTARTJUMP, align=1 PUBLIC class=START
     8                              <2> ; (no prior section) ; DOSSTARTJUMP		ENDS
     9                              <2> 
    10                              <2> addsection CONSTANTS, align=2 PUBLIC class=CONST
    11                              <2> ; (no prior section) ; CONSTANTS	ENDS
    12                              <2> 
    13                              <2> addsection DATA, align=2 PUBLIC class=DATA
    14                              <2> ; (no prior section) ; DATA		ENDS
    15                              <2> 
    16                              <2> addsection TABLE, align=2 PUBLIC class=TABLE
    17                              <2> ; (no prior section) ; TABLE		ENDS
    18                              <2> 
    19                              <2> addsection DOSDATATABLE, align=2 PUBLIC class=DOSDATACODE
    20                              <2> ; (no prior section) ; DOSDATATABLE		ENDS
    21                              <2> 
    22                              <2> addsection DOSDATACODE, align=1 PUBLIC class=DOSDATACODE
    23                              <2> ; (no prior section) ; DOSDATACODE		ENDS
    24                              <2> 
    25                              <2> addsection DOSBIODATA, align=2 PUBLIC class=DOSBIODATA
    26                              <2> 
    27                              <2> addsection LAST, align=16 PUBLIC class=LAST
    28                              <2> ; (no prior section) ; LAST		ENDS
    29                              <2> 
    30                              <2> group DOSGROUP DOSSTART DOSSTARTJUMP CONSTANTS DATA TABLE DOSDATATABLE DOSDATACODE DOSBIODATA LAST
     8                              <1> 
     9                              <1> %include "dcodeseg.nas"
     1                              <2> 
     2                              <2> %ifndef DCODESEGNAS
     3                              <2> %assign DCODESEGNAS 1
     4                              <2> 
     5                              <2> section DOSCODETABLE align=2 PUBLIC class=DOSCODE
     6                              <2> ; (no prior section) ; DOSCODETABLE		ENDS
     7                              <2> section DOSCODECODE align=1 PUBLIC class=DOSCODE
     8                              <2> ; (no prior section) ; DOSCODECODE		ENDS
     9                              <2> section DOSBIOCODE align=2 PUBLIC class=DOSCODE
    10                              <2> section BIOCODE	align=2 PUBLIC class=DOSCODE
    11                              <2> 
    12                              <2> %ifnidni DOSENTRYGROUP, DOSCODEGROUP
    13                              <2>  group DOSCODEGROUP DOSCODETABLE DOSCODECODE DOSBIOCODE BIOCODE
    14                              <2> %endif
    15                              <2> 
    16                              <2> %endif
    10                              <1> 
    11                              <1> section LAST
    12                              <1> ; (no prior section) ; LAST		ENDS
    35                                  
    36                                  [list +]
    37                                  section DOSCODECODE
    38                                  [list -]
    38          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    38          ******************       warning: out: BPB.INC... [-w+user]
    38          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    38          ******************       warning: out: DEVSYM.INC... [-w+user]
    38          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    47                                  ;.sall
    48                                  
    49                                  	EXTRN	DOS_Read:NEAR, DOS_Write:NEAR
    50                                  
    51                                  %ifndef BUF2
    52                                  %IF	BUFFERFLAG
    53                                  	extrn	save_user_map:near
    54                                  	extrn	restore_user_map:near
    55                                  	extrn	Setup_EMS_Buffers:near
    56                                  %ENDIF
    57                                  %endif
    58                                  
    59                                  	I_need	ThisSFT,DWORD		; pointer to SFT entry
    60                                  	I_need	DMAAdd,DWORD		; old-style DMA address
    61                                  	I_Need	EXTERR_LOCUS,byte	; Extended Error Locus
    62                                  	I_need	FailErr,BYTE		; failed error flag
    63                                  	I_need	User_ID,WORD		; current effective user_id
    64                                  	i_need	JShare,DWORD		; jump table
    65                                  	I_need	CurrentPDB,WORD 	; current process data block
    66                                  	I_need	EXTOPEN_ON,BYTE 	;AN000;FT. flag for extended open
    67                                  ;	I_need	XA_device,BYTE		;AN000; XA device
    68                                  	I_need	XA_type,BYTE		;AN000; extended open subfunction
    69                                  ;	I_need	XA_handle,WORD		;AN000; handle
    70                                  	I_need	THISCDS,DWORD		;AN000;
    71                                  	I_need	DUMMYCDS,128		;AN000;
    72                                  	I_need	SAVE_ES,WORD		;AN000; saved ES
    73                                  	I_need	SAVE_DI,WORD		;AN000; saved DI
    74                                  	I_need	SAVE_DS,WORD		;AN000; saved DS
    75                                  	I_need	SAVE_SI,WORD		;AN000; saved SI
    76                                  	I_need	SAVE_CX,WORD		;AN000; saved CX
    77                                  
    78                                  %ifndef BUF2
    79                                  %IF	BUFFERFLAG
    80                                  	I_need	BUF_EMS_MODE,BYTE
    81                                  	I_need	BUF_EMS_LAST_PAGE,DWORD
    82                                  	I_need	BUF_EMS_FIRST_PAGE,DWORD
    83                                  	I_need	BUF_EMS_SAFE_FLAG,BYTE
    84                                  	I_need	BUF_EMS_NPA640,WORD
    85                                  	I_need	BUF_EMS_PAGE_FRAME,WORD
    86                                  	I_need	BUF_EMS_PFRAME,WORD
    87                                  	I_need	LASTBUFFER,DWORD
    88                                  %ENDIF
    89                                  %endif
    90                                  
    91                                  ;	I_need	XA_ES,WORD		;AN000; extended find
    92                                  ;	I_need	XA_BP,WORD		;AN000; extended find
    93                                  ;	I_need	XA_from,BYTE		;AN000; for filetimes
    94                                  %if debug
    95                                  	I_need	BugLev,WORD
    96                                  	I_need	BugTyp,WORD
    97                                  %include "bugtyp.nas"
    98                                  %endif
    99                                  
   100                                  BREAK <$Close - return a handle to the system>
   101                                  
   102                                  ;
   103                                  ;   Assembler usage:
   104                                  ;	    MOV     BX, handle
   105                                  ;	    MOV     AH, Close
   106                                  ;	    INT     int_command
   107                                  ;
   108                                  ;   Error return:
   109                                  ;	    AX = error_invalid_handle
   110                                  ;
   111                                  ;   No registers returned
   112                                  
   113                                  Procedure   D_Close,NEAR
   113          ******************       warning: proc D_Close... [-w+user]
   114                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   115                                  	fmt TypSysCall,LevLog,<"$p Close\n">
   116                                  	fmt TypSysCall,LevArgs,<"$p  Handle = $x\n">,<BX>
   117                                  ;
   118                                  ; Grab the SFT pointer from the JFN.
   119                                  ;
   120 00000000 E8D202                  	call	CheckOwner		; get system file entry
   121 00000003 722B                    	JC	CloseError		; error return
   122                                  	fmt TypAccess,LevSFN,<"$p  Close SFT $x:$x\n">,<es,di>
   123 00000005 161F                    	context DS			; For DOS_CLOSE
   124 00000007 893E[0000]              	MOV	WORD PTR [ThisSFT],DI	; save offset of pointer
   125 0000000B 8C06[0200]              	MOV	WORD PTR [ThisSFT+2],ES ; save segment value
   126                                  ;
   127                                  ; DS:SI point to JFN table entry.
   128                                  ; ES:DI point to SFT
   129                                  ;
   130                                  ; We now examine the user's JFN entry; If the file was a 70-mode file (network
   131                                  ; FCB, we examine the ref count on the SFT;  if it was 1, we free the JFN.
   132                                  ; If the file was not a net FCB, we free the JFN too.
   133                                  ;
   134 0000000F 26833D01                	CMP	word [ES:DI + sf_ref_count],1	; will the SFT become free?
   135 00000013 740A                    	JZ	FreeJFN 		; yes, free JFN anyway.
   136 00000015 268A4502                	MOV	AL,BYTE PTR [ES:DI + sf_mode]
   137 00000019 24F0                    	AND	AL,sharing_mask
   138                                  sharing_net_fcb equ sharing_net_FCB	; NASM port equate
   139 0000001B 3C70                    	CMP	AL,sharing_net_fcb
   140 0000001D 7407                    	JZ	PostFree		; 70-mode and big ref count => free it
   141                                  ;
   142                                  ; The JFN must be freed.  Get the pointer to it and replace the contents with
   143                                  ; -1.
   144                                  ;
   145                                  FreeJFN:
   146 0000001F E8(0000)                	Invoke	pJFNFromHandle		;   d = pJFN (handle);
   147                                  	fmt TypAccess,LevSFN,<"$p  Close jfn pointer $x:$x\n">,<es,di>
   148 00000022 26C605FF                	MOV	BYTE PTR [ES:DI],0FFh	; release the JFN
   149                                  PostFree:
   150                                  ;
   151                                  ; ThisSFT is correctly set, we have DS = DOSGROUP.  Looks OK for a DOS_CLOSE!
   152                                  ;
   153 00000026 E8(0000)                	invoke	DOS_Close
   154                                  ;
   155                                  ; DOS_Close may return an error.  If we see such an error, we report it but
   156                                  ; the JFN stays closed because DOS_Close always frees the SFT!
   157                                  ;
   158 00000029 7205                    	JC	CloseError
   159                                  	fmt TypSysCall,LevLog,<"$p: Close ok\n">
   160                                  close equ Close	; NASM port equate
   161 0000002B B43E                    	MOV	AH,close		; MZ Bogus multiplan fix
   162 0000002D E9(0000)                	transfer    Sys_Ret_OK
   163                                  CloseError:
   164                                  	ASSUME	DS:NOTHING
   165                                  	fmt TypSysCall,LevLog,<"$p: Close error $x\n">,<AX>
   166 00000030 E9(0000)                	transfer    Sys_Ret_Err
   167                                  EndProc D_Close
   168                                  
   169                                  BREAK <$Commit - commit the file>
   170                                  
   171                                  ;
   172                                  ;   Assembler usage:
   173                                  ;	    MOV     BX, handle
   174                                  ;	    MOV     AH, Commit
   175                                  ;	    INT     int_command
   176                                  ;
   177                                  ;   Error return:
   178                                  ;	    AX = error_invalid_handle
   179                                  ;
   180                                  ;   No registers returned
   181                                  
   182                                  Procedure   D_Commit,NEAR
   182          ******************       warning: proc D_Commit... [-w+user]
   183                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   184                                  ;
   185                                  ; Grab the SFT pointer from the JFN.
   186                                  ;
   187 00000033 E89F02                  	call	CheckOwner		; get system file entry
   188 00000036 7213                    	JC	Commiterror		; error return
   189 00000038 161F                    	context DS			; For DOS_COMMIT
   190 0000003A 893E[0000]              	MOV	WORD PTR [ThisSFT],DI	; save offset of pointer
   191 0000003E 8C06[0200]              	MOV	WORD PTR [ThisSFT+2],ES ; save segment value
   192                                  ;
   193                                  ; ES:DI point to SFT
   194                                  ;
   195                                  ;
   196                                  ; ThisSFT is correctly set, we have DS = DOSGROUP.  Looks OK for a DOS_COMMIT
   197                                  ;
   198 00000042 E8(0000)                	invoke	DOS_COMMIT
   199                                  ;
   200                                  ;
   201 00000045 7204                    	JC	Commiterror
   202 00000047 B468                    	MOV	AH,Commit		;
   203 00000049 EBE2                    	transfer    Sys_Ret_OK
   204                                  Commiterror:
   205                                  	ASSUME	DS:NOTHING
   206 0000004B EBE3                    	transfer    Sys_Ret_Err
   207                                  EndProc D_Commit
   208                                  
   209                                  
   210                                  BREAK <$ExtHandle - extend handle count>
   211                                  
   212                                  ;
   213                                  ;   Assembler usage:
   214                                  ;	    MOV     BX, Number of Opens Allowed (MAX=65534;66535 is
   215                                  ;	    MOV     AX, 6700H			 reserved to mark SFT
   216                                  ;	    INT     int_command 		 busy )
   217                                  ;
   218                                  ;   Error return:
   219                                  ;	    AX = error_not_enough_memory
   220                                  ;		 or error_too_many_open_files
   221                                  ;   No registers returned
   222                                  
   223                                  Procedure   D_ExtHandle,NEAR
   223          ******************       warning: proc D_ExtHandle... [-w+user]
   224                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   225                                  ;
   226                                  ;
   227                                  ;
   228 0000004D 31ED                    	XOR	BP,BP			; 0: enlarge   1: shrink  2:psp
   229 0000004F 83FB14                  	CMP	BX,FilPerProc		;  < 20
   230 00000052 7303                    	JAE	getpdb			;  no
   231 00000054 BB1400                  	MOV	BX,FilPerProc		;  bx = 20
   232                                  
   233                                  getpdb:
   234 00000057 368E06[0000]            	MOV	ES,[ss:CurrentPDB] 	; get user process data block
   235                                   assume es:PSP
   236 0000005C 268B0E3200              	MOV	CX,[ES:PDB_JFN_Length]	; get number of handle allowed
   237 00000061 39CB                    	CMP	BX,CX			; the requested == current
   238 00000063 7452                    	JE	ok_done 		; yes and exit
   239 00000065 7723                    	JA	larger			; go allocate new table
   240                                  
   241 00000067 BD0100                  	MOV	BP,1			; shrink
   242 0000006A 268E1E3600              	MOV	DS,WORD PTR [ES:PDB_JFN_Pointer+2] ;
   243                                   assume ds:nothing
   244 0000006F 89DE                    	MOV	SI,BX			;
   245 00000071 29D9                    	SUB	CX,BX			; get difference
   246                                  chck_handles:
   247 00000073 803CFF                  	CMP	BYTE PTR [SI],-1	; scan through handles to ensure close
   248 00000076 7541                    	JNZ	too_many_files		; status
   249 00000078 46                      	INC	SI
   250 00000079 E2F8                    	LOOP	chck_handles
   251 0000007B 83FB14                  	CMP	BX,FilPerProc		; = 20
   252 0000007E 770A                    	JA	larger			; no
   253                                  
   254 00000080 BD0200                  	MOV	BP,2			; psp
   255 00000083 BF1800                  	MOV	DI,PDB_JFN_Table	; es:di -> jfn table in psp
   256 00000086 53                      	PUSH	BX
   257 00000087 EB1E                    	JMP	movhandl
   258 00000089 90                      	nop	; identicalise
   259                                  
   260                                  larger:
   261 0000008A 83FBFF                  	CMP	BX,-1			; 65535 is not allowed
   262 0000008D 747F                    	JZ	invalid_func
   263 0000008F F8                      	CLC
   264 00000090 53                      	PUSH	BX			; save requested number
   265 00000091 83C30F                  	ADD	BX,0FH			; adjust to paragraph boundary
   266 00000094 B104                    	MOV	CL,4
   267 00000096 D3DB                    	RCR	BX,CL			; DOS 4.00 fix				;AC000;
   268 00000098 81E3FF1F                	AND	BX,1FFFH		; clear most 3 bits
   269                                  
   270 0000009C 55                      	PUSH	BP
   271 0000009D E8(0000)                	invoke	D_ALLOC			; allocate memory
   272 000000A0 5D                      	POP	BP
   273 000000A1 7266                    	JC	no_memory		; not enough meory
   274                                  
   275 000000A3 8EC0                    	MOV	ES,AX			; es:di points to new table memory
   276                                   assume es:nothing
   277 000000A5 31FF                    	XOR	DI,DI
   278                                  movhandl:
   279 000000A7 368E1E[0000]            	MOV	DS,[ss:CurrentPDB] 	; get user PDB address
   280                                   assume ds:PSP
   281                                  
   282 000000AC F7C50300                	TEST	BP,3			; enlarge ?
   283 000000B0 740B                    	JZ	enlarge 		; yes
   284 000000B2 59                      	POP	CX			; cx = the amount you shrink
   285 000000B3 51                      	PUSH	CX
   286 000000B4 EB0B                    	JMP	copy_hand
   287 000000B6 90                      	nop	; identicalise
   288                                  ok_done:
   289 000000B7 EB90                    	transfer    Sys_Ret_OK
   290                                  too_many_files:
   291 000000B9 B004                    	MOV	AL,error_too_many_open_files
   292 000000BB EB8E                    	transfer    Sys_Ret_Err
   293                                  enlarge:
   294 000000BD 8B0E3200                	MOV	CX,[PDB_JFN_Length]	  ; get number of old handles
   295                                  copy_hand:
   296 000000C1 89CA                    	MOV	DX,CX
   297 000000C3 C5363400                	LDS	SI,[PDB_JFN_Pointer]   ; get old table pointer
   298                                  ASSUME DS:NOTHING
   299 000000C7 F3A4                    	REP	MOVSB			; copy infomation to new table
   300                                  
   301 000000C9 59                      	POP	CX			; get new number of handles
   302 000000CA 51                      	PUSH	CX			; save it again
   303 000000CB 29D1                    	SUB	CX,DX			; get the difference
   304 000000CD B0FF                    	MOV	AL,-1			; set availability to handles
   305 000000CF F3AA                    	REP	STOSB
   306                                  
   307 000000D1 368E1E[0000]            	MOV	DS,[ss:CurrentPDB] 	; get user process data block
   308                                   assume ds:PSP
   309 000000D6 833E340000              	CMP	WORD PTR [PDB_JFN_Pointer],0  ; check if original table pointer
   310 000000DB 750D                    	JNZ	update_info		; yes, go update PDB entries
   311 000000DD 55                      	PUSH	BP
   312 000000DE 1E                      	PUSH	DS			; save old table segment
   313 000000DF 06                      	PUSH	ES			; save new table segment
   314 000000E0 8E063600                	MOV	ES,WORD PTR [PDB_JFN_Pointer+2] ; get old table segment
   315                                   assume es:nothing
   316 000000E4 E8(0000)                	invoke	D_DEALLOC		; deallocate old table meomory
   317 000000E7 07                      	POP	ES			; restore new table segment
   318                                   assume es:nothing
   319 000000E8 1F                      	POP	DS			; restore old table segment
   320                                   assume ds:nothing
   321 000000E9 5D                      	POP	BP
   322                                  
   323                                  update_info:
   324 000000EA F7C50200                	TEST	BP,2			; psp?
   325 000000EE 7409                    	JZ	non_psp 		; no
   326 000000F0 C70634001800            	MOV	WORD PTR [PDB_JFN_Pointer],PDB_JFN_Table   ; restore
   327 000000F6 EB07                    	JMP	final
   328 000000F8 90                      	nop	; identicalise
   329                                  non_psp:
   330 000000F9 C70634000000            	MOV	WORD PTR [PDB_JFN_Pointer],0  ; new table pointer offset always 0
   331                                  final:
   332 000000FF 8C063600                	MOV	WORD PTR [PDB_JFN_Pointer+2],ES  ; update table pointer segment
   333 00000103 8F063200                	POP	word [PDB_JFN_Length]	 ; restore new number of handles
   334 00000107 EBAE                    	transfer   Sys_Ret_Ok
   335                                  no_memory:
   336 00000109 5B                      	POP	BX			; clean stack
   337 0000010A B008                    	MOV	AL,error_not_enough_memory
   338 0000010C EBAD                    	transfer    Sys_Ret_Err
   339                                  invalid_func:
   340 0000010E B001                    	MOV	AL,error_invalid_function
   341 00000110 EBFA                    	transfer    Sys_Ret_Err
   342                                  EndProc D_ExtHandle
   343                                  
   344                                  BREAK <$READ - Read from a file handle>
   345                                  ;
   346                                  ;   Assembler usage:
   347                                  ;	    LDS     DX, buf
   348                                  ;	    MOV     CX, count
   349                                  ;	    MOV     BX, handle
   350                                  ;	    MOV     AH, Read
   351                                  ;	    INT     int_command
   352                                  ;	  AX has number of bytes read
   353                                  ;   Errors:
   354                                  ;	    AX = read_invalid_handle
   355                                  ;	       = read_access_denied
   356                                  ;
   357                                  ;   Returns in register AX
   358                                  
   359                                  procedure   D_READ,NEAR
   359          ******************       warning: proc D_READ... [-w+user]
   360                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   361                                  	fmt TypSysCall,LevLog,<"Read\n">
   362                                  	fmt TypSysCall,LevArgs,<" Handle $x Cnt $x Buf $x:$x\n">,<BX,CX,DS,DX>
   363 00000112 BE[0000]                	MOV	SI,OFFSET DOS_Read
   364                                  ReadDo:
   365 00000115 E8(0000)                	invoke	pJFNFromHandle
   366 00000118 7208                    	JC	ReadError
   367 0000011A 268A05                  	MOV	AL,[ES:DI]
   368 0000011D E8B501                  	call	CheckOwner		; get the handle
   369 00000120 7302                    	JNC	ReadSetup		; no errors do the operation
   370                                  ReadError:
   371                                  	fmt TypSysCall,LevLog,<"Read/Write error $x\n">,<AX>
   372 00000122 EBEC                    	transfer    SYS_RET_ERR 	; go to error traps
   373                                  ReadSetup:
   374 00000124 36893E[0000]            	MOV	WORD PTR [ss:ThisSFT],DI	; save offset of pointer
   375 00000129 368C06[0200]            	MOV	WORD PTR [ss:ThisSFT+2],ES ; save segment value
   376                                  ;; Extended Open
   377                                  INT_24_ERROR equ int_24_error	; NASM port equate
   378 0000012E 26F745020020            	TEST	word [ES:DI + sf_mode],INT_24_ERROR  ;AN000;;EO. need i24
   379 00000134 7406                    	JZ	needi24 		      ;AN000;;EO. yes
   380                                  EXT_OPEN_I24_OFF equ ext_open_I24_off	; NASM port equate
   381 00000136 36800E[0000]02          	OR	byte [ss:EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;;EO. set it off
   382                                  needi24:				      ;AN000;
   383                                  
   384                                  ;; Extended Open
   385 0000013C 36FF36[0000]36FF36-     	SaveReg <<WORD PTR [ss:DMAAdd]>, <WORD PTR [ss:DMAAdd+2]>>
   385 00000144 [0200]             
   386                                  ;;;;;	BAD SPOT FOR 286!!! SEGMENT ARITHMETIC!!!
   387 00000146 E81500                  	CALL	Align_Buffer		;AN000;MS. align user's buffer
   388                                  ;;;;;	END BAD SPOT FOR 286!!! SEGMENT ARITHMETIC!!!
   389                                  
   390                                  %ifndef BUF2
   391                                  %IF	BUFFERFLAG
   392                                  ;	int	3
   393                                  ;	cmp	[BUF_EMS_MODE], -1
   394                                  ;	jz	dos_call
   395                                  ;	call	choose_buf_page
   396                                  ;	jc	ReadError
   397                                  ;	call	save_user_map
   398                                  ;dos_call:
   399                                  %ENDIF
   400                                  %endif
   401                                  
   402 00000149 161F                    	context DS			; go for DOS addressability
   403 0000014B FFD6                    	CALL	SI			; indirect call to operation
   404 0000014D 8F06[0200]8F06-         	RestoreReg <<WORD PTR [DMAAdd+2]>, <WORD PTR [DMAAdd]>>
   404 00000153 [0000]             
   405                                  
   406                                  %ifndef BUF2
   407                                  %IF	BUFFERFLAG
   408                                  	pushf
   409                                  	push	ax
   410                                  	push	bx
   411                                  
   412                                  	cmp	byte [ss:BUF_EMS_MODE], -1
   413                                  	jz	dos_call_done
   414                                  	call	restore_user_map
   415                                  	mov	ax, word ptr [ss:BUF_EMS_LAST_PAGE]
   416                                  	cmp	[ss:BUF_EMS_PFRAME], ax
   417                                  	je	dos_call_done
   418                                  	mov	word ptr [ss:LASTBUFFER], -1
   419                                  	mov	[ss:BUF_EMS_PFRAME], ax
   420                                  	mov	ax, word ptr [ss:BUF_EMS_LAST_PAGE+2]
   421                                  	mov	[ss:BUF_EMS_PAGE_FRAME], ax
   422                                  	mov	byte [ss:BUF_EMS_SAFE_FLAG], 1
   423                                  	call	Setup_EMS_Buffers
   424                                  
   425                                  dos_call_done:
   426                                  	pop	bx
   427                                  	pop	ax
   428                                  	popf
   429                                  %ENDIF
   430                                  %endif
   431                                  
   432                                  %IFN	BUFFERFLAG
   433                                  	JC	ReadError		; if error, say bye bye
   434                                  %ELSE
   435 00000155 EB01                    	jmp	tmp_rerr
   436 00000157 90                      	nop	; identicalise
   437                                  tmp_rerr:
   438 00000158 72C8                    	jc	ReadError
   439                                  %ENDIF
   440                                  
   441 0000015A 89C8                    	MOV	AX,CX			; get correct return in correct reg
   442                                  	fmt TypSysCall,LevLog,<"Read/Write cnt done $x\n">,<AX>
   443 0000015C EBA9                    	transfer    sys_ret_ok		; successful return
   444                                  EndProc D_READ
   445                                  
   446                                  ;
   447                                  ;   Input: DS:DX points to user's buffer addr
   448                                  ;   Function: rearrange segment and offset for READ/WRITE buffer
   449                                  ;   Output: [DMAADD] set
   450                                  ;
   451                                  ;
   452                                  
   453                                  procedure   Align_Buffer,NEAR		;AN000;
   453          ******************       warning: proc Align_Buffer... [-w+user]
   454                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP  ;AN000;
   455 0000015E 51                      	push cx
   456 0000015F B104                    	mov cl, 4
   457 00000161 8CD8                    	mov ax, ds
   458 00000163 89D3                    	mov bx, dx
   459                                  	; cmp bx, 15
   460                                  	; jbe .end
   461 00000165 83E20F                  	and dx, 15			; mask off full paragraphs
   462 00000168 D3EB                    	shr bx, cl			; how much can at most be added to ds
   463 0000016A 01D8                    	add ax, bx			; => candidate segment,
   464                                  					;  CY if > 0FFFFh (must be in HMA)
   465 0000016C 7308                    	jnc .simple
   466                                  ; ffff:20  ds:dx (want ffff:20) -> 2 ax  -> 2+ffff  = 1000_1
   467                                  ; fffe:20  ds:dx (want ffff:10) -> 2 ax  -> 2+fffe  = 1000_0
   468                                  ; fffe:30  ds:dx (want ffff:20) -> 3 ax  -> 3+fffe  = 1000_1
   469                                  ; fffe:40  ds:dx (want ffff:30) -> 4 ax  -> 4+fffe  = 1000_2
   470                                  ; fffe:80  ds:dx (want ffff:70) -> 8 ax  -> 8+fffe  = 1000_6
   471                                  ; fffe:0   ds:dx (want fffe:0)  -> 0 ax  -> 0+fffe  =  fff_e jnc
   472                                  ; fff0:0   ds:dx (want fff0:0)  -> 0 ax  -> 0+fff0  =  fff_0 jnc
   473                                  ; fff0:80  ds:dx (want fff8:0)  -> 8 ax  -> 8+fff0  =  fff_8 jnc
   474                                  ; fff0:180 ds:dx (want ffff:90) -> 18 ax -> 18+fff0 = 1000_8
   475 0000016E 40                      	inc ax				; adjust, gives offset high 12 bits
   476 0000016F D3E0                    	shl ax, cl			; shift the 12 bits up
   477 00000171 09C2                    	or dx, ax			; get final offset
   478 00000173 B8FFFF                  	mov ax, -1			; final segment is always 0FFFFh if in HMA
   479                                  .simple:
   480 00000176 8ED8                    	mov ds, ax
   481                                   assume ds:nothing
   482                                  .end:
   483 00000178 59                      	pop cx
   484 00000179 368916[0000]            	MOV	WORD PTR [ss:DMAAdd],DX	; use user DX as offset
   485 0000017E 368C1E[0200]            	MOV	WORD PTR [ss:DMAAdd+2],DS	; use user DS as segment for DMA
   486 00000183 C3                      	return				;AN000;
   487                                  EndProc Align_Buffer			;AN000;
   488                                  
   489                                  BREAK <$WRITE - write to a file handle>
   490                                  
   491                                  ;
   492                                  ;   Assembler usage:
   493                                  ;	    LDS     DX, buf
   494                                  ;	    MOV     CX, count
   495                                  ;	    MOV     BX, handle
   496                                  ;	    MOV     AH, Write
   497                                  ;	    INT     int_command
   498                                  ;	  AX has number of bytes written
   499                                  ;   Errors:
   500                                  ;	    AX = write_invalid_handle
   501                                  ;	       = write_access_denied
   502                                  ;
   503                                  ;   Returns in register AX
   504                                  
   505                                  procedure   D_WRITE,NEAR
   505          ******************       warning: proc D_WRITE... [-w+user]
   506                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   507                                  	fmt TypSysCall,LevLog,<"Write\n">
   508                                  	fmt TypSysCall,LevArgs,<" Handle $x Cnt $x Buf $x:$x\n">,<BX,CX,DS,DX>
   509 00000184 BE[0000]                	MOV	SI,OFFSET DOS_Write
   510 00000187 EB8C                    	JMP	ReadDo
   511                                  EndProc D_Write
   512                                  
   513                                  BREAK <$LSEEK - move r/w pointer>
   514                                  
   515                                  ;
   516                                  ;   Assembler usage:
   517                                  ;	    MOV     DX, offsetlow
   518                                  ;	    MOV     CX, offsethigh
   519                                  ;	    MOV     BX, handle
   520                                  ;	    MOV     AL, method
   521                                  ;	    MOV     AH, LSeek
   522                                  ;	    INT     int_command
   523                                  ;	  DX:AX has the new location of the pointer
   524                                  ;   Error returns:
   525                                  ;	    AX = error_invalid_handle
   526                                  ;	       = error_invalid_function
   527                                  ;   Returns in registers DX:AX
   528                                  
   529                                  procedure   D_LSEEK,NEAR
   529          ******************       warning: proc D_LSEEK... [-w+user]
   530                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   531 00000189 E84901                  	call	CheckOwner		; get system file entry
   532                                  LSeekError:
   533                                  
   534                                  %IF	BUFFERFLAG
   535                                  TMP_RERR equ tmp_rerr	; NASM port label
   536 0000018C 72CA                    	JC	TMP_RERR
   537                                  %ELSE
   538                                  	JC	ReadError		; error return
   539                                  %ENDIF
   540 0000018E 3C02                    	CMP	AL,2			; is the seek value correct?
   541 00000190 760A                    	JBE	LSeekDisp		; yes, go dispatch
   542                                  errLoc_Unk equ errLOC_Unk	; NASM port equate
   543 00000192 36C606[0000]01          	MOV	byte [ss:EXTERR_LOCUS],errLoc_Unk ; Extended Error Locus
   544 00000198 B001EB86                	error	error_invalid_function	; invalid method
   545                                  LSeekDisp:
   546 0000019C 3C01                    	CMP	AL,1			; best way to dispatch; check middle
   547 0000019E 720A                    	JB	LSeekStore		; just store CX:DX
   548 000001A0 771B                    	JA	LSeekEOF		; seek from end of file
   549                                  SF_Position equ sf_position	; NASM port equate
   550 000001A2 26035515                	ADD	DX,WORD PTR [ES:DI + SF_Position]
   551 000001A6 26134D17                	ADC	CX,WORD PTR [ES:DI + SF_Position+2]
   552                                  LSeekStore:
   553 000001AA 89C8                    	MOV	AX,CX			; AX:DX
   554 000001AC 92                      	XCHG	AX,DX			; DX:AX is the correct value
   555                                  LSeekSetpos:
   556 000001AD 26894515                	MOV	WORD PTR [ES:DI + SF_Position],AX
   557 000001B1 26895517                	MOV	WORD PTR [ES:DI + SF_Position+2],DX
   558 000001B5 E8(0000)                	invoke	Get_user_stack
   559                                  User_DX equ user_DX	; NASM port equate
   560 000001B8 895406                  	MOV	[SI + User_DX],DX	; return DX:AX
   561 000001BB EB9F                    	transfer    SYS_RET_OK		; successful return
   562                                  
   563                                  LSeekEOF:
   564 000001BD 26F745050080            	TEST	word [ES:DI + sf_flags],sf_isnet
   565 000001C3 750A                    	JNZ	Check_LSeek_Mode	; Is Net
   566                                  LOCAL_LSeek:
   567                                  SF_Size equ sf_size	; NASM port equate
   568 000001C5 26035511                	ADD	DX,WORD PTR [ES:DI + SF_Size]
   569 000001C9 26134D13                	ADC	CX,WORD PTR [ES:DI + SF_Size+2]
   570 000001CD EBDB                    	JMP	LSeekStore		; go and set the position
   571                                  
   572                                  Check_LSeek_Mode:
   573 000001CF 26F745020080            	TEST	word [ES:DI + sf_mode],sf_isfcb
   574 000001D5 75EE                    	JNZ	LOCAL_LSeek		; FCB treated like local file
   575 000001D7 268B4502                	MOV	AX,[ES:DI + sf_mode]
   576 000001DB 25F000                  	AND	AX,sharing_mask
   577 000001DE 83F840                  	CMP	AX,sharing_deny_none
   578 000001E1 7405                    	JZ	NET_LSEEK		; LSEEK exported in this mode
   579 000001E3 83F830                  	CMP	AX,sharing_deny_read
   580 000001E6 75DD                    	JNZ	LOCAL_LSeek		; Treated like local Lseek
   581                                  NET_LSEEK:
   582                                  ;	 JMP	 LOCAL_LSeek
   583                                  ; REMOVE ABOVE INSTRUCTION TO ENABLE DCR 142
   584                                  Net_Lseek equ NET_LSEEK	; NASM port label
   585                                  multNet equ MultNET	; NASM port equate
   586 000001E8 B82111CD2F              	CallInstall Net_Lseek,multNet,33
   587                                  LSeekSetPos equ LSeekSetpos	; NASM port label
   588 000001ED 73BE                    	JNC	LSeekSetPos
   589 000001EF EBA9                    	transfer    SYS_RET_ERR
   590                                  
   591                                  EndProc D_LSeek
   592                                  
   593                                  BREAK <FileTimes - modify write times on a handle>
   594                                  
   595                                  ;
   596                                  ;   Assembler usage:
   597                                  ;	    MOV AH, FileTimes (57H)
   598                                  ;	    MOV AL, func
   599                                  ;	    MOV BX, handle
   600                                  ;	; if AL = 1 then then next two are mandatory
   601                                  ;	    MOV CX, time
   602                                  ;	    MOV DX, date
   603                                  ;	    INT 21h
   604                                  ;	; if AL = 0 then CX/DX has the last write time/date
   605                                  ;	; for the handle.
   606                                  ;
   607                                  ;	AL=02		 get extended attributes
   608                                  ;	   BX=handle
   609                                  ;	   CX=size of buffer (0, return max size )
   610                                  ;	   DS:SI query list (si=-1, selects all EA)
   611                                  ;	   ES:DI buffer to hold EA list
   612                                  ;
   613                                  ;	AL=03		 get EA name list
   614                                  ;	   BX=handle
   615                                  ;	   CX=size of buffer (0, return max size )
   616                                  ;	   ES:DI buffer to hold name list
   617                                  ;
   618                                  ;	AL=04		 set extended attributes
   619                                  ;	   BX=handle
   620                                  ;	   ES:DI buffer of EA list
   621                                  ;
   622                                  ;
   623                                  ;
   624                                  ;
   625                                  ;   Error returns:
   626                                  ;	    AX = error_invalid_function
   627                                  ;	       = error_invalid_handle
   628                                  ;
   629                                  
   630                                  procedure   D_File_Times,NEAR
   630          ******************       warning: proc D_File_Times... [-w+user]
   631                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   632 000001F1 3C02                    	CMP	AL,2			; correct subfunction?
   633 000001F3 7303                    	JAE	gsetxa
   634 000001F5 EB6D                    	JMP	filetimes_ok		; Yes, continue
   635 000001F7 90                      	nop	; identicalise
   636                                  ;;;; DOS 4.00				;AN000;
   637                                  gsetxa: 				;AN000;
   638 000001F8 E8(0000)                	EnterCrit   critSFT		;AN000;;FT. enter critical section
   639 000001FB 3C04                    	CMP	AL,4			;AN000;;FT. =4
   640 000001FD 7603                    	JBE	gshandle		;AN000;;FT. 2,3,4   do get/set by handle
   641                                  funcerr:				;AN000;
   642 000001FF EB59                    	JMP	inval_func		;AN000;;FT. invalid function
   643 00000201 90                      	nop	; identicalise
   644                                  					;AN000;
   645                                  gshandle:				;AN000;
   646 00000202 368C06[0000]            	MOV	[ss:SAVE_ES],ES		;AN000;;FT. save regs
   647 00000207 36893E[0000]            	MOV	[ss:SAVE_DI],DI		;AN000;;FT.
   648 0000020C 368C1E[0000]            	MOV	[ss:SAVE_DS],DS		;AN000;;FT. save regs
   649 00000211 368936[0000]            	MOV	[ss:SAVE_SI],SI		;AN000;;FT.
   650 00000216 36890E[0000]            	MOV	[ss:SAVE_CX],CX		;AN000;;FT.
   651                                  XA_TYPE equ XA_type	; NASM port label
   652 0000021B 36A2[0000]              	MOV	[ss:XA_TYPE],AL		;AN000;;FT.
   653                                  					;AN000;
   654                                  ;	MOV	[XA_handle],BX		;AN000;    ;FT. save handle
   655 0000021F E8B300                  	CALL	CheckOwner		;AN000;    ;FT. get sf pointer
   656 00000222 7306                    	JNC	getsetit		;AN000;    ;FT. good handle
   657 00000224 E8(0000)                	LeaveCrit   critSFT		;AN000;    ;FT. leave critical section
   658 00000227 E962FF                  	JMP	LSeekError		;AN000;    ;FT. turkey handle
   659                                  					;AN000;
   660                                  getsetit:				;AN000;
   661 0000022A 36893E[0000]            	MOV	WORD PTR [ss:ThisSFT],DI	;AN000;       ;FT. set ThisSFT
   662 0000022F 368C06[0200]            	MOV	WORD PTR [ss:ThisSFT+2],ES ;AN000;       ;FT. set ThisSFT
   663                                  ;	TEST	[ES:DI.sf_mode],INT_24_ERROR   ;AN000;;FT. mask INT 24
   664                                  ;	JZ	nomask			       ;AN000;;FT. no
   665                                  ;	OR	[EXTOPEN_ON],EXT_OPEN_I24_OFF  ;AN000;;FT. set bit for I24 handler
   666                                  nomask: 				       ;AN000;
   667 00000234 26F745050080            	TEST	word [ES:DI + sf_flags],sf_isnet      ;AN000;;FT. remote handle
   668 0000023A 7412                    	JZ	localhandle		       ;AN000;;FT. no
   669 0000023C E8(0000)                	LeaveCrit   critSFT		       ;AN000;;FT. doesn't support Network
   670                                  
   671 0000023F 368A1E[0000]            	MOV	BL,[ss:XA_TYPE]		       ;AN000;;FT.
   672                                  IFSsearch:				       ;AN000;
   673                                  multNET equ MultNET	; NASM port equate
   674 00000244 B82D11                  	MOV	AX,(multNET << 8) | 45       ;AN000;;FT. Get/Set XA support
   675 00000247 CD2F                    	INT	2FH			       ;AN000;
   676 00000249 720D                    	JC	getseterror		       ;AN000;;FT. error
   677 0000024B E9(0000)                	transfer    SYS_RET_OK		       ;AN000;;FT.
   678                                  localhandle:				       ;AN000;
   679                                  ;	TEST	[ES:DI.sf_flags],devid_device  ;AN000;;FT. device
   680                                  ;	JZ	getsetfile8		       ;AN000;;FT. no
   681                                  ;	MOV	[XA_device],1		       ;AN000;;FT. indicating device
   682                                  ;	JMP	SHORT doXA		       ;AN000;;FT. do XA
   683                                  getsetfile8:				       ;AN000;
   684                                  ;	MOV	[XA_device],0		       ;AN000;;FT. indicating File
   685                                  ;	LES	BP,[ES:DI.sf_devptr]	       ;AN000;;FT. ES:BP -> DPB
   686                                  
   687                                  doXA:					       ;AN000;
   688                                  ;	MOV	[XA_from],By_XA 	       ;AN000;;FT. from get/set XA
   689                                  ;	PUSH	[SAVE_ES]		       ;AN000;;FT. save XA list
   690                                  ;	PUSH	[SAVE_DI]		       ;AN000;;FT. save XA list
   691                                  
   692 0000024E E8(0000)                	invoke	GetSet_XA		       ;AN000;;FT. issue Get/Set XA
   693                                  ;	POP	SI			       ;AN000;;FT. DS:SI -> XA list
   694                                  ;	POP	DS			       ;AN000;
   695 00000251 7202                    	JC	getexit 		       ;AN000;;FT. error
   696                                  ;	CMP	[XA_device],0		       ;AN000;;FT. device ?
   697                                  ;	JNZ	ftok			       ;AN000;;FT. yes, exit
   698                                  ;	MOV	AX,4			       ;AN000;;FT. function 4 for ShSU
   699                                  ;	CMP	[XA_type],4		       ;AN000;;FT. set XA
   700                                  ;	JNZ	ftok			       ;AN000;;FT. no
   701                                  ;
   702                                  ;
   703                                  ;	LES	DI,[ThisSFT]		       ;AN000;;FT. es:di -> sft
   704                                  ;	CMP	WORD PTR [SI],0 	       ;AN000;;FT. null list ?
   705                                  ;	JNZ	do_share		       ;AN000;;FT. no
   706 00000253 EB4D                    	JMP	SHORT ftok		       ;AN000;;FT. return
   707                                  getexit:				       ;AN000;;FT.
   708 00000255 E8(0000)                	LeaveCrit   critSFT		       ;AN000;;FT. leave critical section
   709                                  
   710                                  
   711                                  getseterror:				       ;AN000;
   712 00000258 EB95                    	transfer    SYS_RET_ERR 	       ;AN000;;FT. mark file as dirty
   713                                  inval_func:
   714                                  
   715                                  ;;;;; DOS 4.00
   716 0000025A 36C606[0000]01          	MOV	byte [ss:EXTERR_LOCUS],errLoc_Unk ; Extended Error Locus
   717 00000260 B001EBF4                	error	error_invalid_function	; give bad return
   718                                  filetimes_ok:
   719 00000264 E86E00                  	call	CheckOwner		; get sf pointer
   720 00000267 7303                    	JNC	gsdt
   721 00000269 E920FF                  	JMP	LSeekError		; turkey handle
   722                                  gsdt:
   723 0000026C 08C0                    	OR	AL,AL			; is it Get?
   724 0000026E 7515                    	JNZ	filetimes_set		; no, go set the time
   725 00000270 FA                      	CLI
   726                                  sf_Time equ sf_time	; NASM port equate
   727 00000271 268B4D0D                	MOV	CX,[ES:DI + sf_Time]	; suck out time
   728                                  sf_Date equ sf_date	; NASM port equate
   729 00000275 268B550F                	MOV	DX,[ES:DI + sf_Date]	; and date
   730 00000279 FB                      	STI
   731 0000027A E8(0000)                	invoke	Get_user_stack		; obtain place to return it
   732 0000027D 894C04                  	MOV	[SI + user_CX],CX 	; and stash in time
   733 00000280 895406                  	MOV	[SI + user_DX],DX 	; and stask in date
   734                                  ext_done:
   735 00000283 EBC6                    	transfer    SYS_RET_OK		; and say goodnight
   736                                  filetimes_set:
   737 00000285 E8(0000)                	EnterCrit   critSFT
   738 00000288 26894D0D                	MOV	[ES:DI + sf_Time],CX	; drop in new time
   739 0000028C 2689550F                	MOV	[ES:DI + sf_Date],DX	; and date
   740 00000290 31C0                    	XOR	AX,AX
   741                                  do_share:
   742                                  %if installed
   743 00000292 36FF1E[3800]            	Call	far [ss:JShare + 14 * 4]
   744                                  %else
   745                                  	Call	ShSU
   746                                  %endif
   747                                  datetimeflg:
   748                                  sf_Flags equ sf_flags	; NASM port equate
   749 00000297 26836505BF              	AND	word [ES:DI + sf_Flags],~ devid_file_clean
   750 0000029C 26814D050040            	OR	word [ES:DI + sf_Flags],sf_close_nodate
   751                                  ftok:
   752 000002A2 E8(0000)                	LeaveCrit   critSFT
   753 000002A5 EBDC                    	transfer    SYS_RET_OK		; mark file as dirty and return
   754                                  EndProc D_File_Times
   755                                  
   756                                  BREAK <$DUP - duplicate a jfn>
   757                                  ;
   758                                  ;   Assembler usage:
   759                                  ;	    MOV     BX, fh
   760                                  ;	    MOV     AH, Dup
   761                                  ;	    INT     int_command
   762                                  ;	  AX has the returned handle
   763                                  ;   Errors:
   764                                  ;	    AX = dup_invalid_handle
   765                                  ;	       = dup_too_many_open_files
   766                                  Procedure   D_DUP,NEAR
   766          ******************       warning: proc D_DUP... [-w+user]
   767                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   768 000002A7 89D8                    	MOV	AX,BX			; save away old handle in AX
   769 000002A9 E8(0000)                	invoke	JFNFree 		; free handle? into ES:DI, new in BX
   770                                  DupErrorCheck:
   771 000002AC 7217                    	JC	DupErr			; nope, bye
   772 000002AE 0657                    	SaveReg <ES,DI> 		; save away SFT
   773 000002B0 5E1F                    	RestoreReg  <SI,DS>		; into convenient place DS:SI
   774 000002B2 93                      	XCHG	AX,BX			; get back old handle
   775 000002B3 E81F00                  	call	CheckOwner		; get sft in ES:DI
   776 000002B6 720D                    	JC	DupErr			; errors go home
   777 000002B8 E8(0000)                	invoke	DOS_Dup_Direct
   778 000002BB E8(0000)                	invoke	pJFNFromHandle		; get pointer
   779 000002BE 268A1D                  	MOV	BL,[ES:DI]		; get SFT number
   780 000002C1 881C                    	MOV	[SI],BL		; stuff in new SFT
   781 000002C3 EBE0                    	transfer    SYS_RET_OK		; and go home
   782 000002C5 EB9B                    DupErr: transfer    SYS_RET_ERR
   783                                  
   784                                  EndProc D_Dup
   785                                  
   786                                  BREAK <$DUP2 - force a dup on a particular jfn>
   787                                  ;
   788                                  ;   Assembler usage:
   789                                  ;	    MOV     BX, fh
   790                                  ;	    MOV     CX, newfh
   791                                  ;	    MOV     AH, Dup2
   792                                  ;	    INT     int_command
   793                                  ;   Error returns:
   794                                  ;	    AX = error_invalid_handle
   795                                  ;
   796                                  Procedure   D_Dup2,NEAR
   796          ******************       warning: proc D_Dup2... [-w+user]
   797                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   798 000002C7 5351                    	SaveReg <BX,CX> 		; save source
   799 000002C9 89CB                    	MOV	BX,CX			; get one to close
   800 000002CB E832FD                  	invoke	D_Close			; close destination handle
   801 000002CE 5B58                    	RestoreReg  <BX,AX>		; old in AX, new in BX
   802 000002D0 E8(0000)                	invoke	pJFNFromHandle		; get pointer
   803 000002D3 EBD7                    	JMP	DupErrorCheck		; check error and do dup
   804                                  EndProc D_Dup2
   805                                  
   806                                  Break	<CheckOwner - verify ownership of handles from server>
   807                                  
   808                                  ;
   809                                  ;   CheckOwner - Due to the ability of the server to close file handles for a
   810                                  ;   process without the process knowing it (delete/rename of open files, for
   811                                  ;   example), it is possible for the redirector to issue a call to a handle
   812                                  ;   that it soes not rightfully own.  We check here to make sure that the
   813                                  ;   issuing process is the owner of the SFT.  At the same time, we do a
   814                                  ;   SFFromHandle to really make sure that the SFT is good.
   815                                  ;
   816                                  ;   Inputs:	BX has the handle
   817                                  ;		User_ID is the current user
   818                                  ;   Output:	Carry Clear => ES:DI points to SFT
   819                                  ;		Carry Set => AX has error code
   820                                  ;   Registers modified: none
   821                                  ;
   822                                  
   823                                  Procedure   CheckOwner,NEAR
   823          ******************       warning: proc CheckOwner... [-w+user]
   824                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   825 000002D5 E8(0000)                	invoke	SFFromHandle
   826 000002D8 7301C3                  	retc
   827 000002DB 50                      	push	ax
   828                                  user_id equ User_ID	; NASM port label
   829 000002DC 36A1[0000]              	mov	ax,[ss:user_id]
   830 000002E0 263B452F                	cmp	ax,[es:di + sf_UID]
   831 000002E4 58                      	pop	ax
   832 000002E5 74F3                    	retz
   833 000002E7 B006                    	mov	al,error_invalid_handle
   834 000002E9 F9                      	stc
   835 000002EA C3                      	return
   836                                  EndProc CheckOwner
   837                                  
   838                                  ;-------------------------------------------------------------------------
   839                                  ;	Function name	: 	choose_buf_page
   840                                  ;	Inputs		:	DMAADD = Xaddr
   841                                  ;				cx = # of bytes to transfer
   842                                  ;	Outputs		:	if NC
   843                                  ;
   844                                  ;				SAFE_FLAG - 0 ==> page is safe. no need to
   845                                  ;						  detect collision between
   846                                  ;						  user & system buffer.
   847                                  ;				SAFE_FLAG - 1 ==> page is unsafe. Must check
   848                                  ;						  for collision
   849                                  ;
   850                                  ;				CY - error
   851                                  ;
   852                                  ;
   853                                  ;	High Level Alogrithm:
   854                                  ;
   855                                  ;	1. If Xaddr. is above the first physical page above 640K
   856                                  ;	   2. choose that page
   857                                  ;	   3. set safe flag
   858                                  ;	4. else
   859                                  ;	   5. choose highest page above 640K
   860                                  ;	   6. If 6 or more pages above 640k
   861                                  ;	      7. Set safe flag				
   862                                  ;	   8. else
   863                                  ;	      9. if Xaddr. + # of bytes to transfer does not spill into the
   864                                  ;	     	 chosen page
   865                                  ;		 10. set safe flag
   866                                  ;	      11.else
   867                                  ;		 12. clear safe flag
   868                                  ;	      13.endif
   869                                  ;	   14.endif
   870                                  ;	15.endif
   871                                  ;
   872                                  ;----------------------------------------------------------------------------
   873                                  ;Procedure 	choose_buf_page,near
   874                                  ;
   875                                  ; ASSUME ds:nothing, es:nothing, ss:dosgroup
   876                                  ;
   877                                  ;	push	cx
   878                                  ;	push	bx
   879                                  ;	push	dx
   880                                  ;	push	si
   881                                  ;	push	ds
   882                                  ;	push	ax
   883                                  ;
   884                                  ;	mov	ax, word ptr [DMAADD+2]
   885                                  ;	and	ax, 0fc00h  	; page segment of transfer segment
   886                                  ;
   887                                  ;	cmp	ax, word ptr [BUF_EMS_FIRST_PAGE]
   888                                  ;	ja	pick_first
   889                                  ;	
   890                                  ;	cmp	[BUF_EMS_NPA640], 6
   891                                  ;	jae	safe_pick_last
   892                                  ;
   893                                  ;	add	cx, word ptr [DMAADD]	; get final offset 
   894                                  ;	mov	bx, cx
   895                                  ;
   896                                  ;	mov	cl, 4
   897                                  ;	shr	bx, cl		; get # of paragraphs
   898                                  ;	mov	ax, word ptr [DMAADD+2]	; get initial segment
   899                                  ;	add	ax, bx		; get final segment
   900                                  ;
   901                                  ;	and	ax, 0fc00h
   902                                  ;	cmp	ax, word ptr [BUF_EMS_LAST_PAGE]
   903                                  ;	jne	safe_pick_last
   904                                  ;
   905                                  ;	mov	[BUF_EMS_SAFE_FLAG], 0
   906                                  ;	jmp	fin_choose_page
   907                                  ;
   908                                  ;safe_pick_last:
   909                                  ;	mov	[BUF_EMS_SAFE_FLAG], 1
   910                                  ;	jmp	fin_choose_page
   911                                  ;
   912                                  ;;pick_last:
   913                                  ;;	mov	ax, word ptr [BUF_EMS_LAST_PAGE]
   914                                  ;;	mov	[BUF_EMS_PFRAME], ax
   915                                  ;;	mov	ax, word ptr [BUF_EMS_LAST_PAGE+2]
   916                                  ;;	mov	[BUF_EMS_PAGE_FRAME], ax
   917                                  ;;	xor	ax, ax
   918                                  ;;	jmp	fin_choose_page
   919                                  ;
   920                                  ;pick_first:
   921                                  ;	mov	ax, word ptr [BUF_EMS_FIRST_PAGE]
   922                                  ;	cmp	[BUF_EMS_PFRAME], ax
   923                                  ;	je	fin_choose_page
   924                                  ;	mov	word ptr [LASTBUFFER], -1
   925                                  ;	mov	[BUF_EMS_PFRAME], ax
   926                                  ;	mov	ax, word ptr [BUF_EMS_FIRST_PAGE+2]
   927                                  ;	mov	[BUF_EMS_PAGE_FRAME], ax
   928                                  ;	mov	[BUF_EMS_SAFE_FLAG], 1
   929                                  ;	call	Setup_EMS_Buffers
   930                                  ;	jmp	fin_choose_page
   931                                  ;
   932                                  ;err_choose_page:
   933                                  ;	stc
   934                                  ;
   935                                  ;fin_choose_page:
   936                                  ;	clc
   937                                  ;
   938                                  ;	pop	ax
   939                                  ;	pop	ds
   940                                  ;	pop	si
   941                                  ;	pop	dx
   942                                  ;	pop	bx
   943                                  ;	pop	cx
   944                                  ;	return
   945                                  ;
   946                                  ;EndProc	choose_buf_page	
   947                                  ;
   948                                  
   949                                  END
   950                                  
   951                                  
