     1                                  ;*********************************************************************
     2                                  ;*   MLLIB2.ASM                                                      *
     3                                  ;*                                                                   *
     4                                  ;*   By:            Michael Devore                                   *
     5                                  ;*   Date:          12/31/92                                         *
     6                                  ;*   Model:         Small                                            *
     7                                  ;*   Version:       2.5                                              *
     8                                  ;*   Assembler:     MASM 5.0                                         *
     9                                  ;*   Environment:   MS-DOS 2.x+                                      *
    10                                  ;*                                                                   *
    11                                  ;*   library processing part 2                                       *
    12                                  ;*                                                                   *
    13                                  ;*********************************************************************
    14                                  
    15                                  ;TITLE   WARPLINK mllib2
    16                                  ;PAGE    50,80
    17                                  
    18                                  ;.MODEL  SMALL
    19                                  
    20                                  ;*****************************
    21                                  ;* Include files             *
    22                                  ;*****************************
    23                                  
    24                                  [list -]
    29                                       
    30                                  ;*****************************
    31                                  ;* Public declarations       *
    32                                  ;*****************************
    33                                  
    34                                  ; procedures     
    35                                  PUBLIC  proc2_libs
    36                                  
    37                                  ; procedures declared public for profiler
    38                                  PUBLIC  pass2_lib_proc,get_curr_lib,check_libobj_path,load_libmod
    39                                  
    40                                  ; variables
    41                                  PUBLIC  lib_read_amt,libmod_obj_flag
    42                                  PUBLIC	pos_in_list
    43                                  
    44                                  ;*****************************
    45                                  ;* Data begins               *
    46                                  ;*****************************
    47                                  
    48                                  .DATA
    49                                  
    50                                  ;*****************************
    51                                  ;* External declarations     *
    52                                  ;*****************************
    53                                  
    54                                  EXTRN   filename:BYTE,lib_handle:WORD,use_libs:BYTE,lib_page_size:WORD
    55                                  EXTRN   lib_page_num:WORD,lib_block_ptr:WORD,pass_number:BYTE
    56                                  EXTRN   module_flag:BYTE,ems_pages_flushed:BYTE
    57                                  
    58                                  ; initialized local variables
    59                                  
    60                                  .DATA?
    61                                  
    62                                  ; uninitialized local variables
    63                                  
    64                                  ; byte values
    65                                  EVEN
    66 00000000 ??                      libmod_obj_flag DB  ?       ; nonzero if library module listed in object module list
    67                                  
    68                                  ; word values
    69 00000001 ??                      EVEN
    70 00000002 ????                    lib_read_amt    DW  ?       ; amount of bytes to read in from a library (modified by file reread of same module)
    71 00000004 ????                    pos_in_list DW  ?           ; position to read name in object name block namelist
    72                                  
    73                                  ; byte strings
    74 00000006 <res 80h>               pathed_file  DB  128 DUP (?)    ; filename with prepended path
    75                                  
    76                                  ;*****************************
    77                                  ;* Code begins               *
    78                                  ;*****************************
    79                                  
    80                                  .CODE
    81                                  
    82                                  ;*****************************
    83                                  ;* External declarations     *
    84                                  ;*****************************
    85                                  
    86                                  EXTRN   link_error:NEAR,dos_error:NEAR,load_file:NEAR
    87                                  EXTRN   load_buffer:NEAR,alloc_memory:NEAR
    88                                  EXTRN   pass2_obj_proc:NEAR,lib_router:NEAR
    89                                  EXTRN   decrypt:NEAR,print_link_info:NEAR
    90                                  EXTRN	file_not_found:NEAR
    91                                  
    92                                  EXTRN   restore_ems_map:NEAR,map_ems_page:NEAR,read_to_ems:NEAR
    93                                  
    94                                  ;*****************************
    95                                  ;* PROC2_LIBS                *
    96                                  ;*****************************
    97                                  
    98                                  ; main driver for pass 2 processing of libraries
    99                                  ; all registers destroyed except for ds
   100                                  
   101                                  proc2_libs  PROC
   102 00000000 803E[0000]00                cmp byte [use_libs],0          ; see if libraries are used
   103 00000005 7501                        jne pl_2                ; yes
   104 00000007 C3                          ret                     ; no, return
   105                                  
   106                                  pl_2:
   107 00000008 1E                          push    ds              ; save critical register
   108 00000009 8B0E[0000]                  mov cx,[first_libent_ptr] ; save cx -> first library module entry
   109                                  
   110                                  ; bubble sort the library entries by library number and page number in ascending order
   111                                  pl_sort1:
   112 0000000D 89C8                        mov ax,cx               ; get pointer to first library module entry
   113 0000000F 8ED8                        mov ds,ax               ; ds -> first library module entry
   114 00000011 8B1E1E00                    mov bx,[30]          ; bx == segment of second library module entry
   115 00000015 09DB                        or  bx,bx               ; check if nonzero
   116 00000017 7445                        je  pl_sort_done        ; zero, no sort needed (only one entry)
   117 00000019 30D2                        xor dl,dl               ; nonzero dl flags swap this pass
   118                                  
   119                                  pl_sort2:
   120 0000001B 8ED8                        mov ds,ax               ; ds -> lower position library module entry
   121 0000001D 8EC3                        mov es,bx               ; es -> high position library module entry
   122 0000001F A10000                      mov ax,[0]           ; get library number of lower
   123 00000022 268B1E0000                  mov bx,[es:0]           ; get library number of higher
   124 00000027 39D8                        cmp ax,bx               ; compare lower entry to higher
   125 00000029 7224                        jb  pl_sort3            ; less than, don't swap entries
   126 0000002B 770C                        ja  pl_swap             ; greater than, swap entries
   127                                  
   128                                  ; library numbers are equal, check page numbers
   129 0000002D A10200                      mov ax,[2]           ; get page number of lower
   130 00000030 268B1E0200                  mov bx,[es:2]           ; get page number of higher
   131 00000035 39D8                        cmp ax,bx               ; compare lower entry to higher
   132 00000037 7616                        jbe pl_sort3            ; less than or equal to, don't swap entries
   133                                  
   134                                  ; swap the library entries
   135                                  pl_swap:
   136 00000039 31F6                        xor si,si
   137                                  
   138                                  ; swap entire all bytes in entry EXCEPT last two bytes, segment pointer to next block
   139                                  pl_swap2:
   140 0000003B 8B04                        mov ax,[si]
   141 0000003D 268B1C                      mov bx,[es:si]
   142 00000040 268904                      mov [es:si],ax
   143 00000043 891C                        mov [si],bx
   144 00000045 83C602                      add si,2
   145 00000048 83FE1E                      cmp si,30               ; see if at pointer to next block yet
   146 0000004B 72EE                        jb  pl_swap2            ; no
   147 0000004D B201                        mov dl,1                ; flag that swap occurred
   148                                  
   149                                  pl_sort3:
   150 0000004F 8CC0                        mov ax,es
   151 00000051 268B1E1E00                  mov bx,[es:30]          ; get segment of next block
   152 00000056 09DB                        or  bx,bx               ; see if nonzero
   153 00000058 75C1                        jne pl_sort2            ; yes
   154 0000005A 08D2                        or  dl,dl               ; check if swap occurred this pass
   155 0000005C 75AF                        jne pl_sort1            ; yes, try another pass
   156                                  
   157                                  ; sort complete, library module entries sorted by library number and page number
   158                                  pl_sort_done:
   159 0000005E 1F                          pop ds                  ; restore critical register
   160                                  
   161                                  pl_proc:
   162 0000005F B002                        mov al,2                ; give lib_router procedure pass 2 flag
   163 00000061 E8(0000)                    call    lib_router      ; initialize data and route to proper library code
   164 00000064 C3                          ret
   165                                  proc2_libs  ENDP
   166                                  
   167                                  ;*****************************
   168                                  ;* PASS2_LIB_PROC            *
   169                                  ;*****************************
   170                                  
   171                                  ; main pass 2 library processing
   172                                  ; destroys ax,bx,cx,dx,di,si,es
   173                                  
   174                                  pass2_lib_proc  PROC
   175 00000065 C706[0000]FFFF              mov word [current_lib],65535   ; force library to load on first compare
   176 0000006B A1[0000]                    mov ax,[first_libent_ptr] ; get pointer to first library module entry
   177                                  
   178                                  p2_loop:
   179 0000006E 09C0                        or  ax,ax               ; check that segment is nonzero
   180 00000070 7503                        jne p2_1                ; yes
   181 00000072 E9C500                      jmp NEAR PTR p2_ret     ; segment is zero, all done processing library modules
   182                                  
   183                                  p2_1:
   184 00000075 8EC0                        mov es,ax               ; es -> library module entry
   185 00000077 50                          push    ax              ; save entry segment
   186                                  
   187 00000078 26A10000                    mov ax,[es:0]           ; get library
   188 0000007C 3B06[0000]                  cmp ax,[current_lib]      ; see if matches current library
   189 00000080 7503                        jne p2_newlib           ; no
   190 00000082 E98800                      jmp NEAR PTR  p2_2      ; yes
   191                                  
   192                                  p2_newlib:
   193 00000085 833E[0000]FF                cmp word [current_lib],65535   ; see if first time through loop
   194 0000008A 740F                        je  p2_1a               ; yes
   195 0000008C 89C1                        mov cx,ax               ; save library in cx
   196 0000008E 8B1E[0000]                  mov bx,[lib_handle]       ; get file handle of previously opened library
   197 00000092 B43E                        mov ah,3eh              ; close file
   198 00000094 CD21                        int 21h
   199 00000096 E8(0000)                    call    restore_ems_map
   200 00000099 89C8                        mov ax,cx               ; get library back in ax
   201                                  
   202                                  p2_1a:
   203 0000009B A3[0000]                    mov [current_lib],ax      ; update current library to reflect library being processed
   204                                  
   205                                  ; get and open library indicated by library module entry
   206 0000009E 06                          push    es              ; save critical register
   207 0000009F 31C9                        xor cx,cx               ; cx == library entry counter
   208 000000A1 A1[0000]                    mov ax,[first_libblk_ptr] ; get first object name block
   209                                  
   210                                  p2_1b:
   211 000000A4 BE0400                      mov si,4                ; si -> first name in block
   212 000000A7 8EC0                        mov es,ax               ; point extra segment at object name block
   213                                  
   214                                  p2_lib_loop:
   215 000000A9 268A04                      mov al,[es:si]          ; get flag byte
   216 000000AC 24C0                        and al,0c0h             ; only get overlay bits
   217 000000AE A2[0000]                    mov [obj_ovl_flag],al     ; save overlay status for module
   218 000000B1 2440                        and al,40h              ; get nonvector root call status
   219 000000B3 A2[0000]                    mov [nonovl_rvect],al     ; save it to global variable
   220 000000B6 46                          inc si                  ; adjust past prepended flag byte in entry
   221 000000B7 B81001                      mov ax,LIB_NAMBLK_BYSIZE    ; size of block in bytes
   222 000000BA 262B060000                  sub ax,[es:0]           ; minus free space, ax == end of used namelist
   223 000000BF 39F0                        cmp ax,si               ; check that position in list is below end
   224 000000C1 770B                        ja  p2_lib2             ; not at end yet, check namelist position
   225                                  
   226 000000C3 26A10200                    mov ax,[es:2]           ; get pointer to next block
   227 000000C7 09C0                        or  ax,ax               ; check that is not null
   228 000000C9 75D9                        jne p2_1b               ; non-null, next block exists, loop and check it
   229 000000CB E99A00                      jmp NEAR PTR lib_internal   ; internal error
   230                                  
   231                                  p2_lib2:
   232 000000CE 3B0E[0000]                  cmp cx,[current_lib]      ; see if at proper position in library name block
   233 000000D2 740E                        je  p2_lib4             ; yes
   234                                  
   235                                  ; not at proper position, gobble bytes until next library name
   236                                  p2_lib_gobble:
   237 000000D4 268A04                      mov al,[es:si]          ; check if at end of library name in block
   238 000000D7 08C0                        or  al,al
   239 000000D9 7403                        je  p2_lib3             ; yes
   240 000000DB 46                          inc si                  ; bump to next char
   241 000000DC EBF6                        jmp p2_lib_gobble
   242                                  
   243                                  p2_lib3:
   244 000000DE 46                          inc si                  ; bump to first char of next name in block
   245 000000DF 41                          inc cx                  ; bump count of entry scanned
   246 000000E0 EBC7                        jmp SHORT p2_lib_loop   ; and loop back to try next namelist position
   247                                  
   248                                  p2_lib4:
   249 000000E2 1E                          push    ds              ; save critical register
   250 000000E3 8CD8                        mov ax,ds
   251 000000E5 8CC1                        mov cx,es
   252 000000E7 8ED9                        mov ds,cx               ; ds:si -> library name in block
   253 000000E9 8EC0                        mov es,ax
   254 000000EB BF[0000]                    mov di,OFFSET filename wrt DGROUP   ; es:di -> destination of library name
   255                                  
   256                                  p2_transfer:
   257 000000EE A4                          movsb                   ; transfer a char from the block to filename
   258 000000EF 807CFF00                    cmp BYTE PTR [si-1],0   ; zero byte signals end of transfer
   259 000000F3 75F9                        jne p2_transfer         ; nonzero, keep looping
   260                                  
   261 000000F5 1F                          pop ds                  ; restore critical register
   262 000000F6 07                          pop es                  ; restore critical register
   263 000000F7 E8(0000)                    call    print_link_info ; print library name, if applicable
   264 000000FA BA[0000]                    mov dx,OFFSET filename wrt DGROUP   ; DS:DX -> ASCIIZ file specification
   265 000000FD B8003D                      mov ax,3d00h            ; open file with read access
   266 00000100 CD21                        int 21h
   267 00000102 E8(0000)                    call    restore_ems_map
   268 00000105 7230                        jc  p2_doserr           ; error occurred
   269                                  
   270 00000107 A3[0000]                    mov [lib_handle],ax       ; save library file handle
   271 0000010A A1[0000]                    mov ax,[current_lib]      ; get current library value
   272                                  
   273                                  p2_2:
   274 0000010D 80CC80                      or  ah,80h              ; set high bit
   275 00000110 A3[0200]                    mov WORD PTR [lib_id+2],ax    ; save as high word of library id
   276 00000113 26A10400                    mov ax,[es:4]           ; get library page size
   277 00000117 A3[0000]                    mov [lib_page_size],ax    ; save to memory variable
   278 0000011A 26A10200                    mov ax,[es:2]           ; get page number (location in lib file)
   279 0000011E A3[0000]                    mov [lib_page_num],ax     ; save to memory variable
   280 00000121 A3[0000]                    mov WORD PTR [lib_id],ax  ; save as low word of library id
   281                                  
   282 00000124 268B1E0600                  mov bx,[es:6]           ; get module length
   283                                  
   284 00000129 E82B01                      call    load_libmod     ; load the module
   285                                  ;***    mov es,buffer_base      ; es -> library file i/o buffer
   286                                  
   287 0000012C E8(0000)                    call    pass2_obj_proc  ; pass 2 process loaded library module
   288                                  
   289 0000012F 07                          pop es                  ; es -> library module entry
   290 00000130 26A11E00                    mov ax,[es:30]          ; get pointer to next entry
   291 00000134 E937FF                      jmp NEAR PTR p2_loop    ; loop back to process it
   292                                  
   293                                  p2_doserr:
   294 00000137 E9(0000)                    jmp NEAR PTR dos_error  ; error occurred
   295                                  
   296                                  p2_ret:
   297 0000013A C3                          ret
   298                                  pass2_lib_proc  ENDP
   299                                  
   300                                  ;*****************************
   301                                  ;* GET_CURR_LIB              *
   302                                  ;*****************************
   303                                  
   304                                  ; get current library in filename
   305                                  ; destroys ax,si,di,es
   306                                  
   307                                  get_curr_lib    PROC
   308 0000013B 833E[0000]00                cmp word [current_lib],0       ; see if first library, requires position initialization
   309 00000140 7506                        jne gcl_3               ; nope
   310                                  
   311                                  gcl_2:
   312 00000142 C706[0400]0400              mov word [pos_in_list],4       ; init position in name list to first position in block
   313                                  
   314                                  gcl_3:
   315 00000148 8B36[0400]                  mov si,[pos_in_list]      ; si will offset into block
   316 0000014C A1[0000]                    mov ax,[lib_block_ptr]    ; get current object name block
   317 0000014F 8EC0                        mov es,ax               ; point extra segment at object name block
   318 00000151 B81001                      mov ax,LIB_NAMBLK_BYSIZE    ; size of block in bytes
   319 00000154 262B060000                  sub ax,[es:0]           ; minus free space, ax == end of used namelist
   320 00000159 39F0                        cmp ax,si               ; check that position in list is below end
   321 0000015B 7714                        ja  gcl_4               ; not at end yet, pull name from this block's namelist
   322                                  
   323 0000015D 26A10200                    mov ax,[es:2]           ; get pointer to next block
   324 00000161 A3[0000]                    mov [lib_block_ptr],ax    ; save back to memory variable
   325 00000164 09C0                        or  ax,ax               ; check that is not null
   326 00000166 75DA                        jne gcl_2               ; non-null, next block exists, loop back and try with it
   327                                  
   328                                  ; A WarpLink internal error has occurred, no more libraries were
   329                                  ; available before the count of all libraries was complete
   330                                  lib_internal:
   331 00000168 B80000                      mov ax,INTERNAL_ERR     ; put warplink error code in ax
   332 0000016B B90900                      mov cx,9                ; internal error value
   333 0000016E E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   334                                  
   335                                  gcl_4:
   336 00000171 268A04                      mov al,[es:si]          ; get flag byte
   337 00000174 88C4                        mov ah,al
   338 00000176 80E401                      and ah,1                ; get library module flag
   339 00000179 8826[0000]                  mov [module_flag],ah      ; save flag status
   340 0000017D 88C4                        mov ah,al
   341 0000017F 80E402                      and ah,2                ; get library module in object module list flag
   342 00000182 8826[0000]                  mov [libmod_obj_flag],ah
   343 00000186 24C0                        and al,0c0h             ; only get overlay bits
   344 00000188 A2[0000]                    mov [obj_ovl_flag],al     ; save overlay status for module
   345 0000018B 2440                        and al,40h              ; get nonvector root call status bit
   346 0000018D A2[0000]                    mov [nonovl_rvect],al     ; save it to global variable
   347 00000190 46                          inc si                  ; adjust past prepended flag byte in entry
   348                                  
   349 00000191 06                      	push	es
   350 00000192 1E                      	push	ds
   351 00000193 07                      	pop	es					; es -> warplink data
   352 00000194 1F                      	pop	ds					; ds -> name block
   353 00000195 BF[0000]                    mov di,OFFSET filename wrt DGROUP   ; es:di -> destination of library name
   354                                  
   355                                  gcl_5:
   356 00000198 A4                          movsb                   ; transfer a char from the block to filename
   357 00000199 807CFF00                    cmp BYTE PTR [si-1],0   ; zero byte signals end of transfer
   358 0000019D 75F9                        jne gcl_5               ; nonzero, keep looping
   359                                  
   360 0000019F 06                      	push	es
   361 000001A0 1F                      	pop	ds					; ds -> warplink data
   362                                  
   363 000001A1 8936[0400]                  mov [pos_in_list],si      ; si points to next name or end, save back to memory
   364 000001A5 C3                          ret
   365                                  get_curr_lib    ENDP
   366                                  
   367                                  ;*****************************
   368                                  ;* CHECK_LIBOBJ_PATH         *
   369                                  ;*****************************
   370                                  
   371                                  ; search LIB or OBJ environment string path for library
   372                                  ; upon entry di -> filename, bx -> target string ('LIB=' or 'OBJ=')
   373                                  ; return di -> path+name or terminate with DOS error if not found
   374                                  ; destroys ax,bx,cx,di
   375                                  
   376                                  check_libobj_path  PROC
   377 000001A6 06                          push    es              ; save critical register
   378 000001A7 56                          push    si
   379 000001A8 52                          push    dx
   380 000001A9 57                          push    di              ; save -> original filename
   381 000001AA 803D2E                      cmp BYTE PTR [di],'.'   ; if file already has path, force error
   382 000001AD 742A                        je  cp_not_found
   383 000001AF 803D5C                      cmp BYTE PTR [di],'\'
   384 000001B2 7425                        je  cp_not_found
   385 000001B4 807D013A                    cmp BYTE PTR [di+1],':' ; check for drivespec
   386 000001B8 741F                        je  cp_not_found
   387                                  
   388                                  ; check for a LIB= in the environment
   389 000001BA 31F6                        xor si,si               ; starting location for target string check
   390 000001BC 8E06[0000]                  mov es,[psp]              ; es -> WarpLink's PSP
   391 000001C0 26A12C00                    mov ax,[es:2ch]         ; es -> environment segment from offset 2ch in PSP
   392 000001C4 85C0                    	test ax, ax		; environment valid ?
   393 000001C6 7411                    	jz cp_not_found		; no -->
   394 000001C8 8EC0                    	mov es, ax
   395                                  
   396                                  cp_find_path:
   397 000001CA 31FF                        xor di,di               ; offset into target string
   398                                  
   399                                  cp_loop2:
   400 000001CC 268A04                      mov al,[es:si]          ; get byte from environment string
   401 000001CF 46                          inc si                  ; point to next char in environment
   402 000001D0 3A01                        cmp al,[bx+di]          ; does environment char match LIB string char
   403 000001D2 740C                        je  cp_byte_match       ; yes, try next location
   404 000001D4 260A04                      or  al,[es:si]          ; two zero values in a row mean the end of the environment
   405 000001D7 75F1                        jne cp_find_path        ; not the end of the environment
   406                                  
   407                                  cp_not_found:
   408 000001D9 B80200                      mov ax,2                ; force file not found error
   409 000001DC 5A                          pop dx                  ; ds:dx -> name of library not found
   410 000001DD E9(0000)                    jmp NEAR PTR dos_error  ; go to DOS error handling routine
   411                                  
   412                                  ; check that LIB is not part of another environment string
   413                                  cp_byte_match:
   414 000001E0 09FF                        or  di,di               ; di is zero if first char is matched
   415 000001E2 750C                        jne cp_2                ; not first char, test already done
   416 000001E4 83FE01                      cmp si,1                ; si equals one if LIB is first string in environment block
   417 000001E7 7407                        je  cp_2                ; no previous environment string
   418 000001E9 26807CFE00                  cmp BYTE PTR [es:si-2],0    ; check if char before LIB was nonzero
   419 000001EE 75DA                        jne cp_find_path        ; yes, LIB is a subset of another string, keep looking
   420                                  
   421                                  cp_2:
   422 000001F0 47                          inc di                  ; a match, move to next byte of target string
   423 000001F1 83FF04                      cmp di,4                ; check if all bytes matched
   424 000001F4 72D6                        jb  cp_loop2            ; not yet, keep comparing
   425                                  
   426                                  cp_path_found:
   427 000001F6 BB[0600]                    mov bx,OFFSET pathed_file wrt DGROUP    ; bx+di offset into filename with path from LIB e-var
   428 000001F9 89DA                        mov dx,bx               ; make dx-> name for get file attribute DOS function
   429                                  
   430                                  cp_3:
   431 000001FB 31FF                        xor di,di               ; offset into path prefix
   432                                  
   433                                  cp_4:
   434 000001FD 268A04                      mov al,[es:si]          ; get path character
   435 00000200 3C3B                        cmp al,';'              ; check if path terminator character
   436 00000202 740A                        je  cp_prefix_complete  ; yes, check file's existence with the current path prefix
   437 00000204 3C20                        cmp al,' '              ; anything less than a space is also a terminator character
   438 00000206 7206                        jb  cp_prefix_complete
   439 00000208 8801                        mov [bx+di],al          ; save path character
   440 0000020A 47                          inc di                  ; move to next name slot
   441 0000020B 46                          inc si                  ; move to next byte location
   442 0000020C EBEF                        jmp SHORT cp_4          ; loop for next character
   443                                  
   444                                  cp_prefix_complete:
   445 0000020E 58                          pop ax                  ; ax -> original program name
   446 0000020F 50                          push    ax              ; restore to stack
   447 00000210 56                          push    si              ; save si -> current environment position
   448 00000211 89C6                        mov si,ax               ; append program name to path prefix
   449 00000213 8079FF5C                    cmp BYTE PTR [bx+di-1],'\'  ; check for backslash already in place
   450 00000217 7404                        je  cp_5
   451 00000219 C6015C                      mov BYTE PTR [bx+di],'\'    ;put a backslash between the path and program name
   452 0000021C 47                          inc di                  ; point di past backslash
   453                                  
   454                                  cp_5:
   455 0000021D 8A04                        mov al,[si]             ; get program name character
   456 0000021F 8801                        mov [bx+di],al          ; transfer program name
   457 00000221 08C0                        or  al,al               ; stop transfer after first zero byte transfer
   458 00000223 7404                        je  cp_search           ; now see if file exists in this path
   459 00000225 46                          inc si                  ; move to next name character slot
   460 00000226 47                          inc di
   461 00000227 EBF4                        jmp SHORT cp_5          ; loop for next character
   462                                  
   463                                  cp_search:
   464 00000229 B80043                      mov ax,4300h            ; get file attributes (check for file existence)
   465 0000022C CD21                        int 21h
   466 0000022E E8(0000)                    call    restore_ems_map
   467 00000231 731B                        jnc cp_prog_found       ; found the program
   468 00000233 E8(0000)                	call	file_not_found	; check for file not found errors
   469                                  
   470                                  cp_6:
   471 00000236 5E                          pop si                  ; restore si -> environment block position
   472 00000237 26803C00                    cmp BYTE PTR [es:si],0  ; check last terminator
   473 0000023B 7409                        je  cp_no_more_path     ; if zero then no more path prefixes to try
   474 0000023D 26807C0100                  cmp BYTE PTR [es:si+1],0    ; check character following last terminator
   475 00000242 7402                        je  cp_no_more_path     ; if zero then no more path prefixes to try
   476 00000244 EB05                        jmp SHORT cp_search_again   ; not the final LIB path, keep trying
   477                                  
   478                                  cp_no_more_path:
   479 00000246 B80200                      mov ax,2                ; force program not found error
   480 00000249 EB8E                        jmp cp_not_found
   481                                  
   482                                  cp_search_again:
   483 0000024B 46                          inc si                  ; point to first character after last terminator
   484 0000024C EBAD                        jmp SHORT cp_3          ; try next path
   485                                  
   486                                  cp_prog_found:
   487 0000024E BF[0600]                    mov di,OFFSET pathed_file wrt DGROUP    ; di -> filename with path from LIB e-var
   488 00000251 58                          pop ax                  ; trash e-var position stored on stack
   489 00000252 58                          pop ax                  ; trash old pointer to filename on stack
   490 00000253 5A                          pop dx
   491 00000254 5E                          pop si
   492 00000255 07                          pop es                  ; restore critical register
   493 00000256 C3                          ret
   494                                  check_libobj_path  ENDP
   495                                  
   496                                  ;*****************************
   497                                  ;* LOAD_LIBMOD               *
   498                                  ;*****************************
   499                                  
   500                                  ; seek to and load up to LIB_MAX_READ of library module for pass 1
   501                                  ; up to file length (64K max) for pass 2
   502                                  ; upon entry bx holds file length
   503                                  ; destroys ax,bx,cx,dx,di,si
   504                                  
   505                                  load_libmod PROC
   506 00000257 31C0                        xor ax,ax
   507 00000259 A3[0000]                    mov WORD PTR [prev_pos_adj],ax    ; zero the previous position file adjustment
   508 0000025C A3[0200]                    mov WORD PTR [prev_pos_adj+2],ax  ; zero high word as well
   509 0000025F A3[0000]                    mov [buffer_head],ax      ; init buffer head to zero
   510 00000262 A2[0000]                    mov [eof_flag],al         ; init end of file flag
   511 00000265 A1[0000]                    mov ax,[buffer_end]
   512 00000268 A3[0000]                    mov [buffer_tail],ax      ; init buffer tail to buffer end
   513 0000026B 803E[0000]01                cmp byte [pass_number],1       ; see which pass number
   514 00000270 7513                        jne ll_pass2            ; pass two, use bx value for library read
   515 00000272 803E[0000]02                cmp byte [udl_proc_pass],2     ; see if udl processing
   516 00000277 740C                        je  ll_pass2            ; yes, use bx value for library read
   517                                  
   518 00000279 A1[0200]                    mov ax,[lib_read_amt]     ; get library read amount
   519 0000027C 09C0                        or  ax,ax               ; see if preset to nonzero amount
   520 0000027E 750A                        jne ll_1a               ; yes, use that
   521 00000280 B80010                      mov ax,LIB_MAX_READ     ; no, use default read amount
   522 00000283 EB02                        jmp SHORT ll_1          ; bypass pass 2 code
   523                                  
   524                                  ll_pass2:
   525 00000285 89D8                        mov ax,bx               ; library read amount in bx for pass 2
   526                                  
   527                                  ll_1:
   528 00000287 A3[0200]                    mov [lib_read_amt],ax     ; init library read amount (used if file reread on same module)
   529                                  
   530                                  ll_1a:
   531 0000028A 8B1E[0000]                  mov bx,[lib_handle]       ; get handle of library file in bx
   532                                  
   533                                  ; get file offset of module in file
   534 0000028E A1[0000]                    mov ax,[lib_page_size]
   535 00000291 F726[0000]                  mul word [lib_page_num]        ; dx:ax has file offset of module
   536 00000295 89D1                        mov cx,dx               ; cx == MSW of offset
   537 00000297 89C2                        mov dx,ax               ; dx == LSW of offset
   538 00000299 8916[0000]                  mov WORD PTR [file_pos_adj],dx    ; save offset for adjustment on file offset feedback
   539 0000029D 890E[0200]                  mov WORD PTR [file_pos_adj+2],cx  ; save high word
   540 000002A1 8916[0000]                  mov WORD PTR [lib_pos_adj],dx ; save offset for adjustment on library module feedback
   541 000002A5 890E[0200]                  mov WORD PTR [lib_pos_adj+2],cx   ; save high word
   542                                  
   543                                  %if 0 ;COMMENT #
   544                                  ; swap in library module if stashed in EMS and pass 2
   545                                      cmp byte [pass_number],1       ; see which pass number
   546                                      je  ll_seek             ; pass one, no swap-in
   547                                  
   548                                      cmp byte [ems_pages_flushed],0 ; see if pages in EMS were flushed for ovl, temp file
   549                                      jne ll_seek             ; yes
   550                                  
   551                                      mov si,10
   552                                      cmp WORD PTR [es:si],-1 ; see if module stashed in EMS (first page always set if so)
   553                                      je  ll_seek             ; no
   554                                      xor cl,cl               ; cl holds physical page
   555                                  
   556                                  ll_emsloop:
   557                                      es lodsw   ; get map page
   558                                      cmp ax,-1               ; see if not used (if not used, then no following ones are either)
   559                                      je  ll_emsmapped        ; not used, done mapping in
   560                                      mov bx,ax               ; get logical page in bx
   561                                      mov al,cl               ; get physical page in al
   562                                      call    map_ems_page    ; map in used pages
   563                                      inc cl                  ; bump physical page
   564                                      cmp cl,4                ; see if all physical pages mapped
   565                                      jb  ll_emsloop          ; not yet
   566                                  
   567                                  ; ems mapped in, now shift file bytes down to cover dictionary bytes from pass 1
   568                                  ll_emsmapped:
   569                                      mov ax,[es:6]           ; get buffer tail (byte count) in ax
   570                                      mov bx,[es:18]          ; get file buffer start
   571                                  
   572                                      sub bx,[ems_base]         ; get offset from EMS base
   573                                      and bx,0f3ffh           ; place on nearest EMS page
   574                                      add bx,[ems_base]
   575                                  
   576                                      mov cx,bx               ; get EMS page, 4 high bits will roll off in byte computation
   577                                      shl cx,1
   578                                      shl cx,1
   579                                      shl cx,1
   580                                      shl cx,1                ; cx holds bytes due to dictionary on this EMS page
   581                                      add cx,ax               ; add in byte count due to file
   582                                  
   583                                      mov es,[ems_base]
   584                                      xor di,di               ; es:di -> base of EMS
   585                                      push    ds              ; save critical register
   586                                      mov ds,bx
   587                                      xor si,si               ; ds:si -> file buffer start in EMS
   588                                      shr cx,1                ; convert byte count to write to words
   589                                      rep movsw               ; move the string
   590                                      rcl cx,1                ; pick up carry
   591                                      rep movsb               ; transfer leftover byte, if any
   592                                      pop ds                  ; restore critical register
   593                                      jmp SHORT ll_ret2       ; bypass file i/o stuff and decryption (already decrypted if necessary)
   594                                  END COMMENT #
   595                                  %endif
   596                                  
   597                                  ll_seek:
   598 000002A9 B80042                      mov ax,4200h            ; move file pointer, offset from beginning
   599 000002AC CD21                        int 21h
   600 000002AE E8(0000)                    call    restore_ems_map
   601 000002B1 7306                        jnc ll_2                ; no errors
   602 000002B3 BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   603 000002B6 E9(0000)                    jmp NEAR PTR dos_error  ; error occurred
   604                                  
   605                                  ll_2:
   606 000002B9 8B0E[0000]                  mov cx,[buffer_end]       ; get number of bytes available in buffer to read
   607 000002BD 3B0E[0200]                  cmp cx,[lib_read_amt]     ; don't read more than lib_read_amt of library module code
   608 000002C1 7604                        jbe ll_3                ; lib_read_amt or less
   609 000002C3 8B0E[0200]                  mov cx,[lib_read_amt]     ; force lib_read_amt read
   610                                  
   611                                  ll_3:
   612 000002C7 1E                          push    ds              ; save critical register
   613 000002C8 31D2                        xor dx,dx
   614 000002CA 8E1E[0000]                  mov ds,[buffer_base]      ; DS:DX -> segment:offset of buffer area
   615                                  
   616 000002CE E8(0000)                    call    read_to_ems     ; read file, transfer to EMS is necessary
   617                                  
   618 000002D1 1F                          pop ds                  ; restore critical register
   619                                  
   620                                  ll_exit:
   621 000002D2 39C1                        cmp cx,ax               ; see if all bytes were read
   622 000002D4 7405                        je  ll_ret              ; yes
   623 000002D6 C606[0000]01                mov byte [eof_flag],1          ; set end of file flag
   624                                  
   625                                  ll_ret:
   626 000002DB E8(0000)                    call    decrypt         ; decrypt if SmartMem library
   627                                  
   628                                  ll_ret2:
   629 000002DE A3[0000]                    mov [buffer_tail],ax      ; set buffer tail at end of bytes read
   630 000002E1 C3                          ret
   631                                  load_libmod ENDP
   632                                  
   633                                  END
