     1                                  ;	SCCSID = @(#)misc.asm	1.1 85/04/10
     2                                  ;TITLE MISC - Miscellanious routines for MS-DOS
     3                                  ;NAME  MISC
     4                                  ;
     5                                  ; Miscellaneous system calls most of which are CAVEAT
     6                                  ;
     7                                  ;   $SLEAZEFUNC
     8                                  ;   $SLEAZEFUNCDL
     9                                  ;   $GET_INDOS_FLAG
    10                                  ;   $GET_IN_VARS
    11                                  ;   $GET_DEFAULT_DPB
    12                                  ;   $GET_DPB
    13                                  ;   $DISK_RESET
    14                                  ;   $SETDPB
    15                                  ;   $Dup_PDB
    16                                  ;   $CREATE_PROCESS_DATA_BLOCK
    17                                  ;   SETMEM
    18                                  ;   FETCHI_CHECK
    19                                  ;   $GSetMediaID
    20                                  ;
    21                                  ;   Revision  history:
    22                                  ;
    23                                  ;	Created: ARR 30 March 1983
    24                                  ;
    25                                  ;	A000   version 4.00   Jan. 1988
    26                                  ;	A001   D490 -- Change IOCTL subfunctions from 63h, 43h to 66h , 46h
    27                                  
    28                                  [list -]
    28          ******************       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
    33                                  
    34                                  [list +]
    35                                  section DOSCODECODE
    36                                  [list -]
    36          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    36          ******************       warning: out: BPB.INC... [-w+user]
    36          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    36          ******************       warning: out: DEVSYM.INC... [-w+user]
    43                                  
    44                                  ENTRYPOINTSEG	EQU	0CH
    45                                  MAXDIF		EQU	0FFFH
    46                                  SAVEXIT 	EQU	10
    47                                  
    48                                  	i_need	LASTBUFFER,DWORD
    49                                  	i_need	BuffHead,DWORD
    50                                  	i_need	INDOS,BYTE
    51                                  	i_need	SYSINITVAR,BYTE
    52                                  	i_need	CurrentPDB,WORD
    53                                  	i_need	CreatePDB,BYTE
    54                                  	i_need	FATBYTE,BYTE
    55                                  	i_need	THISCDS,DWORD
    56                                  	i_need	THISSFT,DWORD
    57                                  	i_need	FETCHI_TAG,WORD 		 ; for TAG CHECK
    58                                  	i_need	BUF_HASH_COUNT,WORD		 ;AN000; number of Hash Entries
    59                                  	i_need	HIGH_SECTOR,WORD		 ;AN000; high word of sector #
    60                                  	i_need	DOS34_FLAG,WORD 		 ;AN000;
    61                                  %if debug
    62                                  	I_need	BugLev,WORD
    63                                  	I_need	BugTyp,WORD
    64                                  %include "bugtyp.nas"
    65                                  %endif
    66                                  
    67                                   assume nocheck, ss:DOSGROUP
    68                                  
    69                                  BREAK <SleazeFunc -- get a pointer to media byte>
    70                                  
    71                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
    72                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
    73                                  ;									   ;
    74                                  ; Inputs:
    75                                  ;	None
    76                                  ; Function:
    77                                  ;	Return Stuff sort of like old get fat call
    78                                  ; Outputs:
    79                                  ;	DS:BX = Points to FAT ID byte (IBM only)
    80                                  ;		GOD help anyone who tries to do ANYTHING except
    81                                  ;		READ this ONE byte.
    82                                  ;	DX = Total Number of allocation units on disk
    83                                  ;	CX = Sector size
    84                                  ;	AL = Sectors per allocation unit
    85                                  ;	   = -1 if bad drive specified
    86                                  
    87                                  	procedure   D_SLEAZEFUNC,NEAR
    87          ******************       warning: proc D_SLEAZEFUNC... [-w+user]
    88                                  ASSUME	DS:NOTHING,ES:NOTHING
    89                                  
    90 00000000 B200                    	MOV	DL,0
    91                                  
    92                                  entry	D_SLEAZEFUNCDL
    93                                  ;Same as above except drive passed in DL (0=default, 1=A, 2=B, ...)
    94                                  
    95 00000002 161F                    	context DS
    96 00000004 88D0                    	MOV	AL,DL
    97 00000006 E8(0000)                	invoke	GETTHISDRV		; Get CDS structure
    98                                  SET_AL_RET:
    99                                  ;	MOV	AL,error_invalid_drive	; Assume error				;AC000;
   100 00000009 721E                    	JC	BADSLDRIVE
   101 0000000B E8(0000)                	invoke	DISK_INFO
   102 0000000E 72F9                    	JC	SET_AL_RET		; User FAILed to I 24
   103 00000010 8826[0000]              	MOV	[FATBYTE],AH
   104                                  ; NOTE THAT A FIXED MEMORY CELL IS USED --> THIS CALL IS NOT
   105                                  ; RE-ENTRANT. USERS BETTER GET THE ID BYTE BEFORE THEY MAKE THE
   106                                  ; CALL AGAIN
   107 00000014 BF[0000]                	MOV	DI,OFFSET FATBYTE wrt DOSGROUP
   108 00000017 30E4                    	XOR	AH,AH			; AL has sectors/cluster
   109                                  		; Does not handle EDR-DOS 256 SpC,
   110                                  		;  what does EDR-DOS do?
   111                                  		; A: EDR-DOS returns 0 in al.
   112 00000019 E8(0000)                	invoke	get_user_stack
   113                                  ASSUME	DS:NOTHING
   114 0000001C 894C04                  	MOV	[SI + user_CX],CX
   115 0000001F 895C06                  	MOV	[SI + user_DX],BX
   116 00000022 897C02                  	MOV	[SI + user_BX],DI
   117 00000025 8C540E                  	MOV	[SI + user_DS], ss	; stash correct pointer
   118 00000028 C3                      	return
   119                                  BADSLDRIVE:
   120 00000029 E9(0000)                	transfer    FCB_Ret_ERR
   121                                  EndProc D_SLEAZEFUNC
   122                                  ;									   ;
   123                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   124                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   125                                  
   126                                  BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag>
   127                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   128                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   129                                  ;									   ;
   130                                  ; Inputs:
   131                                  ;	None
   132                                  ; Function:
   133                                  ;	Returns location of DOS status for interrupt routines
   134                                  ; Returns:
   135                                  ;	Flag location in ES:BX
   136                                  
   137                                  	procedure   D_GET_INDOS_FLAG,NEAR
   137          ******************       warning: proc D_GET_INDOS_FLAG... [-w+user]
   138                                  ASSUME	DS:NOTHING,ES:NOTHING
   139                                  
   140 0000002C E8(0000)                	invoke	get_user_stack
   141 0000002F C74402[0000]            	MOV	word [SI + user_BX],OFFSET INDOS wrt DOSGROUP
   142 00000034 8C5410                  	MOV	[SI + user_ES],SS
   143 00000037 C3                      	return
   144                                  EndProc D_GET_INDOS_FLAG
   145                                  ;									   ;
   146                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   147                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   148                                  
   149                                  BREAK <$Get_IN_VARS -- Return a pointer to DOS variables>
   150                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   151                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   152                                  ;									   ;
   153                                  ; Return a pointer to interesting DOS variables This call is version
   154                                  ; dependent and is subject to change without notice in future versions.
   155                                  ; Use at risk.
   156                                  	procedure   D_GET_IN_VARS,NEAR
   156          ******************       warning: proc D_GET_IN_VARS... [-w+user]
   157 00000038 E8(0000)                	invoke	get_user_stack
   158 0000003B C74402[0000]            	MOV	word [SI + user_BX],OFFSET SYSINITVAR wrt DOSGROUP
   159 00000040 8C5410                  	MOV	[SI + user_ES],SS
   160 00000043 C3                      	return
   161                                  EndProc D_GET_IN_VARS
   162                                  ;									   ;
   163                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   164                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   165                                  
   166                                  
   167                                  BREAK <$Get_Default_DPB,$Get_DPB -- Return pointer to DPB>
   168                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   169                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   170                                  ;									   ;
   171                                  ; Inputs:
   172                                  ;	None
   173                                  ; Function:
   174                                  ;	Return pointer to drive parameter table for default drive
   175                                  ; Returns:
   176                                  ;	DS:BX points to the DPB
   177                                  ;	AL = 0 If OK, = -1 if bad drive (call 50 only)
   178                                  
   179                                  	procedure   D_GET_DEFAULT_DPB,NEAR
   179          ******************       warning: proc D_GET_DEFAULT_DPB... [-w+user]
   180                                  ASSUME	DS:NOTHING,ES:NOTHING
   181                                  
   182 00000044 B200                    	MOV	DL,0
   183                                  
   184                                  	entry	D_GET_DPB
   185                                  ; Same as above only drive passed in DL (0=default, 1=A, 2=B, ...)
   186                                  
   187 00000046 161F                    	context DS
   188 00000048 88D0                    	MOV	AL,DL
   189 0000004A E8(0000)                	invoke	GETTHISDRV		; Get CDS structure
   190 0000004D 7223                    	JC	ISNODRV 		; no valid drive
   191 0000004F C43E[0000]              	LES	DI,[THISCDS]		; check for net CDS
   192 00000053 26F745430080            	TEST	word [ES:DI + curdir_flags],curdir_isnet
   193 00000059 7517                    	JNZ	ISNODRV 		; No DPB to point at on NET stuff
   194 0000005B E8(0000)                	EnterCrit CritDisk
   195 0000005E E8(0000)                	invoke	FATRead_CDS		; Force Media Check and return DPB
   196 00000061 E8(0000)                	LeaveCrit CritDisk
   197 00000064 720C                    	JC	ISNODRV 		; User FAILed to I 24, only error we
   198                                  					;   have.
   199 00000066 E8(0000)                	invoke	get_user_stack
   200                                  ASSUME	DS:NOTHING
   201 00000069 896C02                  	MOV	[SI + user_BX],BP
   202 0000006C 8C440E                  	MOV	[SI + user_DS],ES
   203 0000006F 30C0                    	XOR	AL,AL
   204 00000071 C3                      	return
   205                                  
   206                                  ISNODRV:
   207 00000072 B0FF                    	MOV	AL,-1
   208 00000074 C3                      	return
   209                                  EndProc D_GET_Default_dpb
   210                                  ;									   ;
   211                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   212                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   213                                  
   214                                  
   215                                  BREAK <$Disk_Reset -- Flush out all dirty buffers>
   216                                  
   217                                  	procedure   D_DISK_RESET,NEAR
   217          ******************       warning: proc D_DISK_RESET... [-w+user]
   218                                  ASSUME	DS:NOTHING,ES:NOTHING
   219                                  
   220                                  ; Inputs:
   221                                  ;	None
   222                                  ; Function:
   223                                  ;	Flush and invalidate all buffers
   224                                  ; Returns:
   225                                  ;	Nothing
   226                                  
   227 00000075 B0FF                    	MOV	AL,-1
   228                                   entry D_DISK_RESET2
   229 00000077 161F                    	context DS
   230 00000079 E8(0000)                	EnterCrit   critDisk
   231 0000007C 830E[0000]04            	OR	word [DOS34_FLAG],FROM_DISK_RESET					;AN000;
   232 00000081 E8(0000)                	invoke	FLUSHBUF
   233 00000084 8326[0000]FB            	AND	word [DOS34_FLAG],NO_FROM_DISK_RESET 				;AN000;
   234                                  ;
   235                                  ; We will "ignore" any errors on the flush, and go ahead and invalidate.  This
   236                                  ; call doesn't return any errors and it is supposed to FORCE a known state, so
   237                                  ; let's do it.
   238                                  ;
   239                                  ; Invalidate 'last-buffer' used
   240                                  ;
   241 00000089 BBFFFF                  	MOV	BX,-1
   242 0000008C 891E[0200]              	MOV	WORD PTR [LASTBUFFER+2],BX
   243 00000090 891E[0000]              	MOV	WORD PTR [LASTBUFFER],BX
   244                                  ;
   245                                  ;	TEST	[DOS34_FLAG],IFS_DRIVE_RESET	 ;AN000;;IFS. from ifs call back ?
   246                                  ;	JZ	FreeDone			 ;AN000;;IFS. no
   247                                  ;	AND	[DOS34_FLAG],NO_IFS_DRIVE_RESET  ;AN000;;IFS. clear the flag
   248                                  ;	LeaveCrit   critDisk			 ;AN000;;IFS.
   249                                  ;	return					 ;AN000;;IFS. return
   250                                  FreeDone:
   251 00000094 E8(0000)                	LeaveCrit   critDisk
   252 00000097 B8FFFF                  	MOV	AX,-1
   253                                  multNET equ MultNET	; NASM port equate
   254 0000009A B82011CD2F              	CallInstall NetFlushBuf,multNET,32
   255 0000009F C3                      	return
   256                                  EndProc D_DISK_RESET
   257                                  
   258                                  BREAK <$SetDPB - Create a valid DPB from a user-specified BPB>
   259                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   260                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   261                                  ;									   ;
   262                                  	procedure   D_SETDPB,NEAR
   262          ******************       warning: proc D_SETDPB... [-w+user]
   263                                  ASSUME	DS:NOTHING,ES:NOTHING
   264                                  
   265                                  ; Inputs:
   266                                  ;	ES:BP Points to DPB
   267                                  ;	DS:SI Points to BPB
   268                                  ; Function:
   269                                  ;	Build a correct DPB from the BPB
   270                                  ; Outputs:
   271                                  ; ES:BP and DS preserved all others destroyed
   272                                  
   273 000000A0 89EF                    	MOV	DI,BP
   274 000000A2 AF                      	scasw				; Skip over dpb_drive and dpb_UNIT
   275 000000A3 AD                      	LODSW
   276 000000A4 AB                      	STOSW				; dpb_sector_size
   277 000000A5 85C0                    	test ax, ax
   278 000000A7 7406                    	jz .nonfat
   279 000000A9 807C0300                	CMP	BYTE PTR [SI + BPFTCNT-2],0     ; FAT file system drive		;AN000;
   280 000000AD 7508                    	JNZ	yesfat			      ; yes				;AN000;
   281                                  .nonfat:
   282 000000AF 26C6450400              	MOV	BYTE PTR [ES:DI + dpb_FAT_count-4],0
   283 000000B4 EB74                    	JMP	setend			      ; NO				;AN000;
   284 000000B6 90                      	nop	; identicalise
   285                                  yesfat:
   286 000000B7 89C2                    	MOV	DX,AX
   287 000000B9 AC                      	LODSB				; get amount clusters (0 means 256)
   288 000000BA 48                      	dec ax
   289 000000BB AA                      	STOSB				; dpb_cluster_mask
   290 000000BC B400                    	mov ah, 0
   291 000000BE 40                      	inc ax				; translate EDR-DOS 0 to 256
   292 000000BF B300                    	mov bl, 0			; bl = shift count
   293                                  LOG2LOOP:
   294 000000C1 A801                    	TEST	AL,1
   295 000000C3 7506                    	JNZ	SAVLOG
   296 000000C5 FEC3                    	inc bl				; increment shift count
   297 000000C7 D1E8                    	shr ax, 1			; shift right amount clusters
   298 000000C9 EBF6                    	JMP	SHORT LOG2LOOP
   299                                  SAVLOG:
   300 000000CB 88D8                    	mov al, bl			; bl = al = shift count
   301 000000CD AA                      	STOSB				; dpb_cluster_shift
   302 000000CE A5                      	MOVSW				; dpb_first_FAT Start of FAT (# of reserved sectors)
   303 000000CF AC                      	LODSB
   304 000000D0 AA                      	STOSB				; dpb_FAT_count Number of FATs
   305                                  ;	OR	AL,AL			; NONFAT ?				;AN000;
   306                                  ;	JZ	setend			; yes, don't do anything                ;AN000;
   307 000000D1 88C7                    	MOV	BH,AL
   308 000000D3 AD                      	LODSW
   309 000000D4 AB                      	STOSW				; dpb_root_entries Number of directory entries
   310 000000D5 B105                    	MOV	CL,5
   311 000000D7 D3EA                    	SHR	DX,CL			; Directory entries per sector
   312 000000D9 48                      	DEC	AX
   313 000000DA 01D0                    	ADD	AX,DX			; Cause Round Up
   314 000000DC 89D1                    	MOV	CX,DX
   315 000000DE 31D2                    	XOR	DX,DX
   316 000000E0 F7F1                    	DIV	CX
   317 000000E2 89C1                    	MOV	CX,AX			; Number of directory sectors
   318 000000E4 47                      	INC	DI
   319 000000E5 47                      	INC	DI			; Skip dpb_first_sector
   320 000000E6 A5                      	MOVSW				; Total number of sectors in DSKSIZ (temp as dpb_max_cluster)
   321 000000E7 AC                      	LODSB
   322 000000E8 26884617                	MOV	[ES:BP + dpb_media],AL	; Media byte
   323 000000EC AD                      	LODSW				; Number of sectors in a FAT
   324 000000ED AB                      	STOSW				;AC000;;>32mb dpb_FAT_size
   325 000000EE 88FA                    	MOV	DL,BH			;AN000;;>32mb
   326 000000F0 30F6                    	XOR	DH,DH			;AN000;;>32mb
   327 000000F2 F7E2                    	MUL	DX			;AC000;;>32mb Space occupied by all FATs
   328 000000F4 26034606                	ADD	AX,[ES:BP + dpb_first_FAT]
   329 000000F8 AB                      	STOSW				; dpb_dir_sector
   330 000000F9 01C8                    	ADD	AX,CX			; Add number of directory sectors
   331 000000FB 2689460B                	MOV	[ES:BP + dpb_first_sector],AX
   332                                  
   333 000000FF 88D9                    	mov cl, bl			; cluster size shift count
   334 00000101 26837E0D00              	CMP	WORD PTR [ES:BP + DSKSIZ],0	;F.C. >32mb			;AN000;
   335 00000106 751A                    	JNZ	normal_dpb	       ;F.C. >32mb				;AN000;
   336 00000108 30ED                    	XOR	CH,CH		       ;F.C. >32mb				;AN000;
   337                                  BPB_BigTotalSectors equ BPB_BIGTOTALSECTORS	; NASM port label
   338                                  BPB_SectorsPerTrack equ BPB_SECTORSPERTRACK	; NASM port label
   339 0000010A 8B5C08                  	MOV	BX,WORD PTR [SI+BPB_BigTotalSectors-BPB_SectorsPerTrack]	;AN000;
   340 0000010D 8B540A                  	MOV	DX,WORD PTR [SI+BPB_BigTotalSectors-BPB_SectorsPerTrack+2]	;AN000;
   341 00000110 29C3                    	SUB	BX,AX		       ;AN000;;F.C. >32mb
   342 00000112 83DA00                  	SBB	DX,0		       ;AN000;;F.C. >32mb
   343 00000115 E306                    	jcxz	norot		       ;AN000;;F.C. >32mb
   344                                  rott:				       ;AN000;;F.C. >32mb
   345 00000117 D1EA                    	shr	DX,1		       ;AN000;;F.C. >32mb
   346 00000119 D1DB                    	RCR	BX,1		       ;AN000;;F.C. >32mb
   347 0000011B E2FA                    	LOOP	rott		       ;AN000;;F.C. >32mb
   348                                  norot:				       ;AN000;
   349 0000011D 89D8                    	MOV	AX,BX		       ;AN000;;F.C. >32mb
   350 0000011F EB09                    	JMP	setend		       ;AN000;;F.C. >32mb
   351 00000121 90                      	nop	; identicalise
   352                                  normal_dpb:
   353 00000122 262B460D                	SUB	AX,[ES:BP + DSKSIZ]
   354 00000126 F7D8                    	NEG	AX			; Sectors in data area
   355                                  ;;	MOV	CL,BL			; dpb_cluster_shift
   356 00000128 D3E8                    	SHR	AX,CL			; Div by sectors/cluster
   357                                  setend:
   358 0000012A 40                      	INC	AX
   359 0000012B 2689460D                	MOV	[ES:BP + dpb_max_cluster],AX
   360 0000012F 26C7461D0000            	MOV	word [ES:BP + dpb_next_free],0 ; Init so first ALLOC starts at
   361                                  					; begining of FAT
   362 00000135 26C7461FFFFF            	MOV	word [ES:BP + dpb_free_cnt],-1 ; current count is invalid.
   363 0000013B C3                      	return
   364                                  EndProc D_SETDPB
   365                                  ;									   ;
   366                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   367                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   368                                  
   369                                  BREAK <$Create_Process_Data_Block,SetMem -- Set up process data block>
   370                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   371                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   372                                  ;									   ;
   373                                  ;
   374                                  ; Inputs:   DX is new segment address of process
   375                                  ;	    SI is end of new allocation block
   376                                  ;
   377                                  	procedure   D_Dup_PDB,NEAR
   377          ******************       warning: proc D_Dup_PDB... [-w+user]
   378                                  ASSUME	DS:NOTHING,ES:NOTHING
   379 0000013C 36C606[0000]FF          	MOV	byte [ss:CreatePDB],0FFH		; indicate a new process
   380 00000142 368E1E[0000]            	MOV	DS,[ss:CurrentPDB]
   381                                   assume ds:PSP
   382 00000147 56                      	PUSH	SI
   383 00000148 EB0A                    	JMP	SHORT	CreateCopy
   384                                  EndProc D_Dup_PDB
   385                                  
   386                                  	procedure   D_CREATE_PROCESS_DATA_BLOCK,NEAR
   386          ******************       warning: proc D_CREATE_PROCESS_DATA_BLOCK... [-w+user]
   387                                  ASSUME	DS:NOTHING,ES:NOTHING
   388                                  
   389                                  ; Inputs:
   390                                  ;	DX = Segment number of new base
   391                                  ; Function:
   392                                  ;	Set up program base and copy term and ^C from int area
   393                                  ; Returns:
   394                                  ;	None
   395                                  ; Called at DOS init
   396                                  
   397 0000014A E8(0000)                	CALL	get_user_stack
   398 0000014D 8E5C14                  	MOV	DS,[SI + user_CS]
   399                                   assume ds:PSP
   400                                  PDB_Block_len equ PDB_block_len	; NASM port label
   401 00000150 FF360200                	PUSH	word [PDB_Block_len]
   402                                  CreateCopy:
   403 00000154 8EC2                    	MOV	ES,DX
   404                                   assume es:nothing
   405 00000156 31F6                    	XOR	SI,SI			; copy all 80h bytes
   406 00000158 89F7                    	MOV	DI,SI
   407 0000015A B98000                  	MOV	CX,80H
   408 0000015D F3A5                    	REP	MOVSW
   409                                  ; DOS 3.3 7/9/86
   410                                  
   411 0000015F B91400                  	MOV	CX,FilPerProc		; copy handles in case of
   412 00000162 BF1800                  	MOV	DI,offset PDB_JFN_Table	; Set Handle Count has been issued
   413 00000165 1E                      	PUSH	DS
   414 00000166 C5363400                	LDS	SI,[PDB_JFN_Pointer]
   415                                   assume ds:nothing
   416 0000016A F3A4                    	REP	MOVSB
   417 0000016C 1F                      	POP	DS
   418                                   assume ds:PSP
   419                                  
   420                                  ; DOS 3.3 7/9/86
   421 0000016D 36F606[0000]FF          	TEST	byte [ss:CreatePDB],0FFh; Shall we create a process?
   422 00000173 744B                    	JZ	Create_PDB_cont 	; nope, old style call
   423                                  ;
   424                                  ; Here we set up for a new process...
   425                                  ;
   426                                  
   427 00000175 16                      	PUSH	ss
   428 00000176 1F                      	POP	DS
   429                                  	DOSAssume   CS,<DS>,"MISC/Create_Copy"
   430 00000177 31DB                    	XOR	BX,BX			; dup all jfns
   431 00000179 B91400                  	MOV	CX,FilPerProc		; only 20 of them
   432                                  
   433                                  Create_dup_jfn:
   434 0000017C 06                      	PUSH	ES			; save new PDB
   435 0000017D E8(0000)                	invoke	SFFromHandle		; get sf pointer
   436 00000180 B0FF                    	MOV	AL,-1			; unassigned JFN
   437 00000182 7225                    	JC	CreateStash		; file was not really open
   438 00000184 26F745050010            	TEST	word [ES:DI + sf_flags],sf_no_inherit
   439 0000018A 751D                    	JNZ	CreateStash		; if no-inherit bit is set, skip dup.
   440                                  ;
   441                                  ; We do not inherit network file handles.
   442                                  ;
   443 0000018C 268A6502                	MOV	AH,BYTE PTR [ES:DI + sf_mode]
   444 00000190 80E4F0                  	AND	AH,sharing_mask
   445                                  sharing_net_fcb equ sharing_net_FCB	; NASM port equate
   446 00000193 80FC70                  	CMP	AH,sharing_net_fcb
   447 00000196 7411                    	jz	CreateStash
   448                                  ;
   449                                  ; The handle we have found is duplicatable (and inheritable).  Perform
   450                                  ; duplication operation.
   451                                  ;
   452 00000198 893E[0000]              	MOV	WORD PTR [THISSFT],DI
   453 0000019C 8C06[0200]              	MOV	WORD PTR [THISSFT+2],ES
   454 000001A0 E8(0000)                	invoke	DOS_DUP 		; signal duplication
   455                                  ;
   456                                  ; get the old sfn for copy
   457                                  ;
   458 000001A3 E8(0000)                	invoke	pJFNFromHandle		; ES:DI is jfn
   459 000001A6 268A05                  	MOV	AL,[ES:DI]		; get sfn
   460                                  ;
   461                                  ; Take AL (old sfn or -1) and stash it into the new position
   462                                  ;
   463                                  CreateStash:
   464 000001A9 07                      	POP	ES
   465                                   assume es:nothing
   466 000001AA 26884718                	MOV	[ES:BX + PDB_JFN_Table],AL; copy into new place!
   467 000001AE 43                      	INC	BX			; next jfn...
   468                                  create_dup_jfn equ Create_dup_jfn	; NASM port label
   469 000001AF E2CB                    	LOOP	create_dup_jfn
   470                                  
   471 000001B1 8B1E[0000]              	MOV	BX,[CurrentPDB]		; get current process
   472 000001B5 26891E1600              	MOV	[ES:PDB_Parent_PID],BX	; stash in child
   473 000001BA 8C06[0000]              	MOV	[CurrentPDB],ES
   474 000001BE 8EDB                    	MOV	DS,BX
   475                                  	ASSUME	DS:NOTHING
   476                                  ;
   477                                  ; end of new process create
   478                                  ;
   479                                  Create_PDB_cont:
   480 000001C0 36C606[0000]00          	MOV	BYTE PTR [ss:CreatePDB],0h ; reset flag
   481 000001C6 58                      	POP	AX
   482                                  
   483                                  	entry	SETMEM			; called from NEARDOSINIT, ss != DOSDATA
   484                                  ASSUME	DS:NOTHING,ES:NOTHING,SS:NOTHING
   485                                  
   486                                  ; Inputs:
   487                                  ;	AX = Size of memory in paragraphs
   488                                  ;	DX = Segment
   489                                  ; Function:
   490                                  ;	Completely prepares a program base at the
   491                                  ;	specified segment.
   492                                  ; Called at DOS init
   493                                  ; Outputs:
   494                                  ;	DS = DX
   495                                  ;	ES = DX
   496                                  ;	[0] has INT int_abort
   497                                  ;	[2] = First unavailable segment
   498                                  ;	[5] to [9] form a long call to the entry point
   499                                  ;	[10] to [13] have exit address (from int_terminate)
   500                                  ;	[14] to [17] have ctrl-C exit address (from int_ctrl_c)
   501                                  ;	[18] to [21] have fatal error address (from int_fatal_abort)
   502                                  ; DX,BP unchanged. All other registers destroyed.
   503                                  
   504 000001C7 31C9                    	XOR	CX,CX
   505 000001C9 8ED9                    	MOV	DS,CX
   506                                   assume ds:IVT
   507 000001CB 8EC2                    	MOV	ES,DX
   508                                   assume es:nothing
   509 000001CD BE8800                  	MOV	SI,addr_int_terminate
   510 000001D0 BF0A00                  	MOV	DI,SAVEXIT
   511 000001D3 B90600                  	MOV	CX,6
   512 000001D6 F3A5                    	REP	MOVSW
   513 000001D8 26A30200                	MOV	[ES:2],AX
   514 000001DC 29D0                    	SUB	AX,DX
   515 000001DE 3DFF0F                  	CMP	AX,MAXDIF
   516 000001E1 7603                    	JBE	HAVDIF
   517 000001E3 B8FF0F                  	MOV	AX,MAXDIF
   518                                  HAVDIF:
   519 000001E6 83E810                  	SUB	AX,10H			; Allow for 100h byte "stack"
   520 000001E9 BB0C00                  	MOV	BX,ENTRYPOINTSEG	;	in .COM files
   521 000001EC 29C3                    	SUB	BX,AX
   522 000001EE B104                    	MOV	CL,4
   523 000001F0 D3E0                    	SHL	AX,CL
   524 000001F2 8EDA                    	MOV	DS,DX
   525                                   assume ds:nothing
   526 000001F4 A30600                  	MOV	WORD PTR [PDB_CPM_Call+1],AX
   527 000001F7 891E0800                	MOV	WORD PTR [PDB_CPM_Call+3],BX
   528 000001FB C7060000CD20            	MOV	word [PDB_Exit_Call],(int_abort << 8) + mi_INT
   529 00000201 C60605009A              	MOV	BYTE PTR [PDB_CPM_Call],mi_Long_CALL
   530                                  PDB_Call_System equ PDB_Call_system	; NASM port label
   531 00000206 C7065000CD21            	MOV	WORD PTR [PDB_Call_System],(int_command << 8) + mi_INT
   532 0000020C C6065200CB              	MOV	BYTE PTR [PDB_Call_System+2],mi_Long_RET
   533 00000211 C70634001800            	MOV	WORD PTR [PDB_JFN_Pointer],PDB_JFN_Table
   534 00000217 8C1E3600                	MOV	WORD PTR [PDB_JFN_Pointer+2],DS
   535 0000021B C70632001400            	MOV	WORD PTR [PDB_JFN_Length],FilPerProc
   536                                  ;
   537                                  ; The server runs several PDB's without creating them VIA EXEC.  We need to
   538                                  ; enumerate all PDB's at CPS time in order to find all references to a
   539                                  ; particular SFT.  We perform this by requiring that the server link together
   540                                  ; for us all sub-PDB's that he creates.  The requirement for us, now, is to
   541                                  ; initialize this pointer.
   542                                  ;
   543 00000221 830E3800FF              	or	word ptr [PDB_Next_PDB],-1
   544 00000226 830E3A00FF              	or	word ptr [PDB_Next_PDB+2],-1
   545 0000022B C3                      	return
   546                                  
   547                                  EndProc D_CREATE_PROCESS_DATA_BLOCK
   548                                  
   549                                  ;									   ;
   550                                  ;	     C	A  V  E  A  T	  P  R	O  G  R  A  M  M  E  R		   ;
   551                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   552                                  	procedure   FETCHI_CHECK,NEAR
   552          ******************       warning: proc FETCHI_CHECK... [-w+user]
   553                                  ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   554 0000022C 9C                      	PUSHF
   555 0000022D 36813E[0000]7258        	CMP	word [ss:FETCHI_TAG],22642
   556 00000234 7403                    	JZ	TAG_OK
   557 00000236 E8(0000)                	invoke	TAGCRASHDOS	      ; go to hell
   558                                  TAG_OK:
   559 00000239 9D                      	POPF
   560 0000023A C3                      	return
   561                                  EndProc FETCHI_CHECK
   562                                  
   563                                  BREAK <$GSetMediaID -- get set media ID>
   564                                  ; Inputs:
   565                                  ;	BL= drive number as defined in IOCTL
   566                                  ;	AL= 0 get media ID
   567                                  ;	    1 set media ID
   568                                  ;	DS:DX= buffer containing information
   569                                  ;		DW  0  info level (set on input)
   570                                  ;		DD  ?  serial #
   571                                  ;		DB  11 dup(?)  volume id
   572                                  ;		DB   8 dup(?)  file system type
   573                                  ; Function:
   574                                  ;	Get or set media ID
   575                                  ; Returns:
   576                                  ;	carry clear, DS:DX is filled
   577                                  ;	carry set, error
   578                                  
   579                                  	procedure   D_GSetMediaID,NEAR ;AN000;
   579          ******************       warning: proc D_GSetMediaID... [-w+user]
   580                                  ASSUME	DS:NOTHING,ES:NOTHING, ss:DOSGROUP
   581                                  
   582 0000023B B96608                  	MOV	CX,0866H	      ;AN000;MS.; assume get  for IOCTL
   583 0000023E 3C00                    	CMP	AL,0		      ;AN001;MS.; get ?
   584 00000240 7407                    	JZ	doioctl 	      ;AN000;MS.; yes
   585 00000242 3C01                    	CMP	AL,1		      ;AN000;MS.; set ?
   586 00000244 7509                    	JNZ	errorfunc	      ;AN000;MS.; no
   587 00000246 B94608                  	MOV	CX,0846H	      ;AN001;MS.;
   588                                  doioctl:			      ;AN000;
   589 00000249 B00D                    	MOV	AL,0DH		      ;AN000;MS.; generic IOCTL
   590 0000024B E8(0000)                	invoke	D_IOCTL		      ;AN000;MS.; let IOCTL take care of it
   591 0000024E C3                      	return			      ;AN000;MS.;
   592                                  errorfunc:			      ;AN000;
   593 0000024F B001E9(0000)            	error	error_invalid_function;AN000;MS.	; invalid function
   594                                  EndProc D_GSetMediaID		      ;AN000;
   595                                  
   596                                  END
