home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / caway349.zip / SOURCE / ALL / API.ASM < prev    next >
Assembly Source File  |  1999-11-01  |  171KB  |  8,870 lines

  1.     .386
  2.  
  3. _apiCode    segment para 'API CODE' use32
  4.     assume cs:_apiCode, ds:_apiCode
  5. _apiCodeStart    label byte
  6.  
  7.  
  8. ;*******************************************************************************
  9. ;Put carry into return carry.
  10. ;*******************************************************************************
  11. cwAPI_C2C    macro
  12.     push    eax
  13.     pushfd
  14.     pushfd
  15.     pop    eax
  16.     and    al,1
  17.     cwAPI_AL2C
  18.     popfd
  19.     pop    eax
  20.     endm
  21.  
  22.  
  23. ;*******************************************************************************
  24. ;Put carry into return carry.
  25. ;*******************************************************************************
  26. cwAPI_AL2C    macro
  27.     local __0, __1
  28.     pushfd
  29.     assume ds:nothing
  30.     test    cs:apiSystemFlags,1
  31.     jz    __0
  32.     or    b[ebp+Int_Flags16],al
  33.     jmp    __1
  34. __0:    or    b[ebp+Int_Flags32],al
  35. __1:    assume ds:_apiCode
  36.     popfd
  37.     endm
  38.  
  39.  
  40. ;*******************************************************************************
  41. ;Call old int 31h handler.
  42. ;*******************************************************************************
  43. cwAPI_CallOld    macro
  44.     local __0, __1
  45.     assume ds:nothing
  46.     test    cs:apiSystemFlags,1
  47.     jz    __0
  48.     pushf
  49.     db 66h
  50.     call    cs:f[OldIntSys]        ;pass it onto previous handler.
  51.     jmp    __1
  52. __0:    pushfd
  53.     call    cs:f[OldIntSys]        ;pass it onto previous handler.
  54. __1:    assume ds:_apiCode
  55.     endm
  56.  
  57.  
  58. ;*******************************************************************************
  59. ;Convert character in AL to upper case.
  60. ;*******************************************************************************
  61. UpperChar    macro
  62.     local __0
  63.     cmp    al,61h        ; 'a'
  64.     jb    __0
  65.     cmp    al,7Ah        ; 'z'
  66.     ja    __0
  67.     and    al,5Fh        ;convert to upper case.
  68. __0:    ;
  69.     endm
  70.  
  71.  
  72. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  73. ;
  74. ;This must be just before cwAPIpatch
  75. ;
  76. cwIdentity    db "CAUSEWAY"
  77. cwMajorVersion    db 0
  78. cwMinorVersion    db 0
  79. ;
  80. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  81. ;
  82. ;CW API int 31h patch.
  83. ;
  84. cwAPIpatch    proc    near
  85.     pushm    ds,es,fs,gs        ;Preserve all registers.
  86.     pushad        ;/
  87.     mov    ebp,esp        ;Make registers addressable.
  88. ;
  89. ;Check if we're allowed to interfere.
  90. ;
  91.     push    ds
  92.     assume ds:nothing
  93.     mov    ds,cs:apiDSeg
  94.     assume ds:_cwMain
  95.     cmp    Int21hExecCount,0
  96.     assume ds:_apiCode
  97.     pop    ds
  98.     jnz    @@Nope
  99. ;
  100. ;Check if this is a CauseWay function.
  101. ;
  102.     cmp    ah,255
  103.     jz    @@Ours
  104. ;
  105. ;Scan the table of other relavent functions.
  106. ;
  107.     mov    edi,offset apiExtraCallTable+2
  108. @@extra:    cmp    cs:w[edi-2],0
  109.     jz    @@Nope
  110.     cmp    ax,cs:w[edi-2]
  111.     jz    @@GotCall
  112.     add    edi,4+2
  113.     jmp    @@extra
  114. ;
  115. ;An internal funtion? so point to table entry.
  116. ;
  117. @@Ours:    movzx    edi,al
  118.     shl    edi,2
  119.     add    edi,offset apiCallTable
  120. ;
  121. ;Check if final call is still going to pass control to the old handler.
  122. ;
  123. @@GotCall:    cmp    cs:d[edi],0
  124.     jz    @@Nope
  125. ;
  126. ;See about turning interrupts back on.
  127. ;
  128.     mov    esi,Int_Flags32
  129.     assume ds:nothing
  130.     test    cs:apiSystemFlags,1    ;/
  131.     assume ds:_apiCode
  132.     jz    @@32bit0        ;/
  133.     movzx    ebp,bp        ;/
  134.     mov    esi,Int_Flags16
  135. @@32Bit0:    and    ss:b[ebp+esi],not 1    ;clear carry.
  136.     cld            ;Default direction.
  137.     test    ss:w[ebp+esi],1 shl 9    ;Were interrupts enabled?
  138.     jz    @@NoInts
  139.     sti            ;Turn interrupts back on.
  140. ;
  141. ;Call the function handler.
  142. ;
  143. @@NoInts:    assume ds:nothing
  144.     call    cs:d[edi]        ;Pass control to handler.
  145.     assume ds:_apiCode
  146.     popad            ;\
  147.     popm    ds,es,fs,gs        ;Restore all registers.
  148.     assume ds:nothing
  149.     test    cs:apiSystemFlags,1
  150.     assume ds:_apiCode
  151.     jz    @@32Bit1
  152.     iret
  153. @@32Bit1:    iretd            ;Return to caller.
  154. ;
  155. ;Not an internal function or anything we want to interfere with so pass control
  156. ;to origional handler.
  157. ;
  158. @@Nope:    popad            ;Restore registers.
  159.     popm    ds,es,fs,gs
  160.     assume ds:nothing
  161.     test    cs:apiSystemFlags,1
  162.     jz    @@n32
  163.     db 66h
  164. @@n32:    jmp    cs:f[OldIntSys]    ;pass it onto previous handler.
  165.     assume ds:_apiCode
  166. ;
  167. OldIntSys    df 0
  168. ;
  169. APICallTable    dd cwAPI_Info        ;00
  170.     dd cwAPI_IntXX        ;01
  171.     dd cwAPI_FarCallReal    ;02
  172.     dd cwAPI_GetSel        ;03
  173.     dd cwAPI_RelSel        ;04
  174.     dd cwAPI_CodeSel        ;05
  175.     dd cwAPI_AliasSel        ;06
  176.     dd cwAPI_GetSelDet        ;07
  177.     ;
  178.     dd cwAPI_GetSelDet32    ;08
  179.     dd cwAPI_SetSelDet        ;09
  180.     dd cwAPI_SetSelDet32    ;0A
  181.     dd cwAPI_GetMem        ;0B
  182.     dd cwAPI_GetMem32        ;0C
  183.     dd cwAPI_ResMem        ;0D
  184.     dd cwAPI_ResMem32        ;0E
  185.     dd cwAPI_RelMem        ;0F
  186.     ;
  187.     dd cwAPI_GetMemLinear    ;10
  188.     dd cwAPI_GetMemLinear32    ;11
  189.     dd cwAPI_ResMemLinear    ;12
  190.     dd cwAPI_ResMemLinear32    ;13
  191.     dd cwAPI_RelMemLinear    ;14
  192.     dd cwAPI_RelMemLinear32    ;15
  193.     dd cwAPI_GetMemNear    ;16
  194.     dd cwAPI_ResMemNear    ;17
  195.     ;
  196.     dd cwAPI_RelMemNear    ;18
  197.     dd cwAPI_Linear2Near    ;19
  198.     dd cwAPI_Near2Linear    ;1A
  199.     dd cwAPI_LockMem        ;1B
  200.     dd cwAPI_LockMem32        ;1C
  201.     dd cwAPI_UnLockMem        ;1D
  202.     dd cwAPI_UnLockMem32    ;1E
  203.     dd cwAPI_LockMemNear    ;1F
  204.     ;
  205.     dd cwAPI_UnLockMemNear    ;20
  206.     dd cwAPI_GetMemDOS        ;21
  207.     dd cwAPI_ResMemDOS        ;22
  208.     dd cwAPI_RelMemDOS        ;23
  209.     dd cwAPI_Exec        ;24
  210.     dd cwAPI_GetDOSTrans    ;25
  211.     dd cwAPI_SetDOSTrans    ;26
  212.     dd cwAPI_GetMCBSize    ;27
  213.     ;
  214.     dd cwAPI_SetMCBSize    ;28
  215.     dd cwAPI_GetSels        ;29
  216.     dd cwAPI_cwLoad        ;2A
  217.     dd cwAPI_cwcInfo        ;2B
  218.     dd cwAPI_GetMemSO        ;2C
  219.     dd cwAPI_ResMemSO        ;2D
  220.     dd cwAPI_RelMemSO        ;2E
  221.     dd cwAPI_UserDump        ;2F
  222.  
  223. ;    dd 16 dup (0)        ;30-3F
  224.     dd    cwAPI_SetDump    ; 30
  225.     dd    cwAPI_UserErrTerm    ; 31
  226.     dd    cwAPI_CWErrName    ; 32
  227.     dd 13 dup (0)        ;33-3F
  228.  
  229.     dd 16 dup (0)        ;40-4F
  230.     dd 16 dup (0)        ;50-5F
  231.     dd 16 dup (0)        ;60-6F
  232.     dd 16 dup (0)        ;70-7F
  233.     ;
  234.     dd 16*7 dup (0)        ;80-EF
  235.     ;
  236.     dd 8 dup (0)        ;F0-F7
  237.     ;
  238.     dd 0            ;F8
  239.     dd cwAPI_ID                ;F9
  240.     dd cwAPI_GetPatch        ;FA
  241.     dd cwAPI_cwcLoad        ;FB
  242.     dd cwAPI_LinearCheck    ;FC
  243.     dd cwAPI_ExecDebug        ;FD
  244.     dd cwAPI_Cleanup        ;FE
  245.     dd 0            ;FF
  246. ;
  247. apiExtraCallTable label byte
  248.     dw 0600h
  249.     dd dpmiAPI_Lock
  250.     dw 0601h
  251.     dd dpmiAPI_UnLock
  252.     dw 0303h
  253.     dd dpmiAPI_GetCallBack
  254.     dw 0304h
  255.     dd dpmiAPI_RelCallBack
  256.     dw 0
  257. cwAPIpatch    endp
  258.  
  259.  
  260. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  261. ;
  262. ;AX    = 0600h
  263. ;BX:CX    = Starting linear address of memory to lock
  264. ;SI:DI    = Size of region to lock in bytes
  265. ;
  266. dpmiAPI_Lock    proc    near
  267.     mov    ax,[ebp+Int_AX]
  268.     mov    bx,[ebp+Int_BX]
  269.     mov    cx,[ebp+Int_CX]
  270.     mov    si,[ebp+Int_SI]
  271.     mov    di,[ebp+Int_DI]
  272.     pushad
  273.     shl    ebx,16
  274.     mov    bx,cx
  275.     shl    esi,16
  276.     mov    si,di
  277.     mov    edx,ebx
  278.     mov    ecx,esi
  279.     mov    ax,Res_LOCK
  280.     call    RegisterResource
  281.     popad
  282.     cwAPI_CallOld
  283.     cwAPI_C2C
  284.     jnc    @@0
  285.     mov    [ebp+Int_AX],ax
  286. @@0:    ret
  287. dpmiAPI_Lock    endp
  288.  
  289.  
  290. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  291. ;
  292. ;AX    = 0601h
  293. ;BX:CX    = Starting linear address of memory to unlock
  294. ;SI:DI    = Size of region to unlock in bytes
  295. ;
  296. dpmiAPI_UnLock    proc    near
  297.     mov    ax,[ebp+Int_AX]
  298.     mov    bx,[ebp+Int_BX]
  299.     mov    cx,[ebp+Int_CX]
  300.     mov    si,[ebp+Int_SI]
  301.     mov    di,[ebp+Int_DI]
  302.     pushad
  303.     shl    ebx,16
  304.     mov    bx,cx
  305.     shl    esi,16
  306.     mov    si,di
  307.     mov    edx,ebx
  308.     mov    ecx,esi
  309.     mov    ax,Res_LOCK
  310.     call    ReleaseResource
  311.     popad
  312.     cwAPI_CallOld
  313.     cwAPI_C2C
  314.     jnc    @@0
  315.     mov    [ebp+Int_AX],ax
  316. @@0:    ret
  317. dpmiAPI_UnLock    endp
  318.  
  319.  
  320. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  321. ;
  322. ;AX = 0303h
  323. ;DS:(E)SI = Selector:Offset of procedure to call
  324. ;ES:(E)DI = Selector:Offset of real mode call structure
  325. ;
  326. ;Returns
  327. ;
  328. ;If function was successful:
  329. ;Carry flag is clear.
  330. ;CX:DX = Segment:Offset of real mode call address
  331. ;
  332. dpmiAPI_GetCallBack proc near
  333.     mov    ax,[ebp+Int_AX]
  334.     mov    ds,[ebp+Int_DS]
  335.     mov    esi,[ebp+Int_ESI]
  336.     mov    es,[ebp+Int_ES]
  337.     mov    edi,[ebp+Int_EDI]
  338.     cwAPI_CallOld
  339.     cwAPI_C2C
  340.     jc    @@9
  341. ;
  342.     mov    [ebp+Int_CX],cx
  343.     mov    [ebp+Int_DX],dx
  344. ;
  345.     shl    ecx,16
  346.     mov    cx,dx
  347.     mov    edx,ecx
  348.     mov    ecx,esi
  349.     xor    ebx,ebx
  350.     mov    bx,ds
  351.     mov    ax,Res_CALLBACK
  352.     call    RegisterResource
  353. ;
  354. @@9:    ret
  355. dpmiAPI_GetCallBack endp
  356.  
  357.  
  358. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  359. ;
  360. ;AX = 0304h
  361. ;CX:DX = Real mode call-back address to free
  362. ;
  363. dpmiAPI_RelCallBack proc near
  364.     mov    ax,[ebp+Int_AX]
  365.     mov    cx,[ebp+Int_CX]
  366.     mov    dx,[ebp+Int_DX]
  367.     cwAPI_CallOld
  368.     cwAPI_C2C
  369.     jc    @@9
  370. ;
  371.     shl    ecx,16
  372.     mov    cx,dx
  373.     mov    edx,ecx
  374.     mov    ax,Res_CALLBACK
  375.     call    ReleaseResource
  376. ;
  377. @@9:    ret
  378. dpmiAPI_RelCallBack endp
  379.  
  380. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  381. ;
  382. ;Call user termination routine on exception
  383. ;
  384. ;On Entry:
  385. ;
  386. ; AX = 0ff31h
  387. ; CL = 0 if 16-bit termination routine
  388. ; CL = nonzero if 32-bit termination routine
  389. ; DS:[E]SI = user termination routine address, if ES is zero or an invalid
  390. ;  selector value, then the user termination routine call is removed
  391. ; ES:[E]DI = user information dump area
  392. ;
  393. ;Returns:
  394. ;
  395. ; None
  396. ;
  397. cwAPI_UserErrTerm    PROC    NEAR
  398.     mov    ds,cs:apiDSeg
  399.     assume ds:_cwMain
  400.     mov    UserTermFlag,0    ; initialize flag
  401.     mov    dx,[ebp+Int_DS]
  402.     lsl    ax,dx
  403.     jnz    uetret            ; invalid selector
  404.     mov    al,[ebp+Int_CL]    ; get bitness flag
  405.     test    al,al
  406.     setne    al            ; 0 if 0, 1 if nonzero
  407.     inc    ax                ; 1 if 16-bit, 2 if 32-bit
  408.     mov    UserTermFlag,al
  409.     cmp    al,1            ; see if 16-bit
  410.     jne    uet32            ; no
  411.  
  412.     mov    ax,[ebp+Int_SI]
  413.     mov    WORD PTR UserTermRoutine,ax
  414.     mov    WORD PTR UserTermRoutine+2,dx
  415.     mov    ax,[ebp+Int_DI]
  416.     mov    WORD PTR UserTermDump,ax
  417.     mov    ax,[ebp+Int_ES]
  418.     mov    WORD PTR UserTermDump+2,ax
  419.     jmp    uetret
  420.  
  421. uet32:
  422.     mov    eax,[ebp+Int_ESI]
  423.     mov    DWORD PTR UserTermRoutine,eax
  424.     mov    WORD PTR UserTermRoutine+4,dx
  425.     mov    eax,[ebp+Int_EDI]
  426.     mov    DWORD PTR UserTermDump,eax
  427.     mov    ax,[ebp+Int_ES]
  428.     mov    WORD PTR UserTermDump+4,ax
  429.  
  430. uetret:
  431.     ret
  432. cwAPI_UserErrTerm    ENDP
  433.  
  434. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  435. ;
  436. ;Disable/enable error display and CW.ERR creation
  437. ;
  438. ;On Entry:
  439. ;
  440. ; AX = 0ff30h
  441. ; CL = 0, disable error display and CW.ERR file creation
  442. ; CL = nonzero, enable error display and CW.ERR file creation
  443. ;
  444. ;Returns:
  445. ;
  446. ; None
  447. ;
  448. cwAPI_SetDump    PROC    NEAR
  449.     mov    ds,cs:apiDSeg
  450.     assume ds:_cwMain
  451.     mov    al,[ebp+Int_CL]
  452.     mov    EnableDebugDump,al
  453.     ret
  454. cwAPI_SetDump    ENDP
  455.  
  456. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  457. ;
  458. ; change CW.ERR file name, with optional path/drivespec
  459. ;
  460. ;On Entry:
  461. ;
  462. ; AX = 0ff32h
  463. ; CX:[E]DX = new CW.ERR ASCIIZ file name
  464. ;
  465. ;Returns:
  466. ;
  467. ; None
  468. ;
  469. cwAPI_CWErrName    PROC    NEAR
  470.     mov    ds,cs:apiDSeg
  471.     assume ds:_cwMain
  472.     mov    edx,[ebp+Int_EDX]
  473.     test    cs:apiSystemFlags,1
  474.     jz    cen2
  475.     movzx    edx,dx    ; 16-bit, zero high word of edx
  476.  
  477. cen2:
  478.     mov    ax,[ebp+Int_CX]
  479.     mov    es,ax
  480.     mov    ebx,OFFSET NewCWErrName    ; ds:ebx -> destination, es:edx -> source
  481.     mov    cx,80        ; don't allow more than 80 chars in file name
  482.  
  483. cenloop:
  484.     mov    al,es:[edx]
  485.     test    al,al
  486.     je    centerm        ; at null terminator
  487.     mov    ds:[ebx],al
  488.     inc    edx
  489.     inc    ebx
  490.     dec    cx
  491.     jne    cenloop
  492.  
  493. centerm:
  494.     mov    BYTE PTR ds:[ebx],0
  495.     ret
  496. cwAPI_CWErrName    ENDP
  497.  
  498. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  499. ;
  500. ;Setup user buffer display in CW.ERR file
  501. ;
  502. ;On Entry:
  503. ;
  504. ; AX = 0ff2fh
  505. ; ES:[E]DI -> user buffer to display in CW.ERR
  506. ; CX = count of bytes to display from buffer in CW.ERR
  507. ; BL = 'A' if ASCII dump (non-binary display of bytes, control characters
  508. ;      display as periods)
  509. ; BH = nonzero if preset ASCII buffer to word value, ignored for non-ASCII
  510. ; DX = word value to fill ASCII dump buffer if BH is nonzero, ignored
  511. ;      for non-ASCII
  512. ;
  513. ;Returns:
  514. ;
  515. ; Carry set on ASCII dump invalid buffer address
  516. ;
  517. cwAPI_UserDump    PROC    NEAR
  518.     mov    ds,cs:apiDSeg
  519.     assume ds:_cwMain
  520.     mov    ax,[ebp+Int_ES]
  521.     verr    ax
  522.     jnz    udfail            ; can't read to user selector
  523.     mov    DebugUserSel,ax
  524.     mov    es,ax
  525.  
  526.     mov    edi,[ebp+Int_EDI]
  527.     xor    eax,eax
  528.     mov    ax,es
  529.     lsl    eax,eax
  530.     cmp    eax,10000h
  531.     jnc    @@0
  532.     movzx    edi,di
  533. @@0:
  534.     mov    DebugUserOff,edi
  535.     mov    cx,[ebp+Int_CX]
  536.     mov    DebugUserCount,cx
  537.  
  538. ; check for out of bounds
  539.     movzx    edx,cx
  540.     add    edx,edi
  541.     jc    udfail
  542.     dec    edx                ; make relative 0
  543.     xor    eax,eax
  544.     mov    ax,es
  545.     lsl    eax,eax
  546.     cmp    eax,edx
  547.     jb    udfail
  548.  
  549.     mov    al,[ebp+Int_BL]
  550.     cmp    al,'A'
  551.     je    aflag
  552.     xor    al,al
  553.  
  554. aflag:
  555.     mov    DebugAsciiFlag,al
  556.     test    al,al
  557.     je    udret            ; if not ASCII then no fill
  558.     mov    al,[ebp+Int_BH]    ; check fill flag
  559.     test    al,al        ; no fill, carry flag reset by default
  560.     je    udret
  561.  
  562. ; fill the allocation with value in dx to count specified in cx
  563.     mov    ax,es
  564.     verw    ax
  565.     jnz    udfail            ; can't write to user selector
  566.     mov    ax,[ebp+Int_DX]
  567.     push    ax
  568.     push    ax
  569.     pop    eax
  570.     push    ecx
  571.     shr    ecx,1
  572.     rep    stosd
  573.     pop    ecx
  574.     and    cx,3
  575.     je    udsuccess
  576.     mov    es:[edi],al        ; finish off remainder bytes
  577.     dec    cx
  578.     je    udsuccess
  579.     inc    edi
  580.     mov    es:[edi],ah
  581.     dec    cx
  582.     je    udsuccess
  583.     inc    edi
  584.     mov    es:[edi],al
  585.  
  586. udsuccess:
  587.     clc                    ; flag success
  588.     jmp    udret
  589.  
  590. udfail:
  591.     mov    DebugUserCount,0
  592.     stc                    ; flag failure
  593.  
  594. udret:
  595.     cwAPI_C2C
  596.     ret
  597. cwAPI_UserDump    ENDP
  598.  
  599. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  600. ;
  601. ;Get CauseWay identifier, return PageDIRLinear and Page1stLinear info
  602. ;
  603. ;Returns:
  604. ;
  605. ;EDX    - Linear address of patch table.
  606. ;
  607. cwAPI_ID    proc    near
  608.     push    ds
  609.     assume ds:nothing
  610.     mov    ax,KernalDS
  611.     mov    ds,ax
  612.     assume ds:_cwRaw
  613.     mov    esi,PageDIRLinear
  614.     mov    edi,Page1stLinear
  615.     pop    ds
  616.     mov    ecx,"CAUS"
  617.     mov    edx,"EWAY"
  618.     mov    [ebp+Int_ESI],esi
  619.     mov    [ebp+Int_EDI],edi
  620.     mov    [ebp+Int_EDX],edx
  621.     mov    [ebp+Int_ECX],ecx
  622.     xor    al,al
  623.     cwAPI_AL2C
  624.     ret
  625. cwAPI_ID    endp
  626.  
  627. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  628. ;
  629. ;Get patch table address.
  630. ;
  631. ;Returns:
  632. ;
  633. ;EDX    - Linear address of patch table.
  634. ;
  635. cwAPI_GetPatch    proc    near
  636.     assume ds:nothing
  637.     mov    bx,cs:apiDDSeg
  638.     sys    GetSelDet32
  639.     add    edx,offset PatchTable
  640.     assume ds:_apiCode
  641.     mov    [ebp+Int_EDX],edx
  642.     xor    al,al
  643.     cwAPI_AL2C
  644.     ret
  645. cwAPI_GetPatch    endp
  646.  
  647.  
  648. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  649. ;
  650. ;Get address of transfer buffer.
  651. ;
  652. ;Returns:
  653. ;
  654. ;BX    - Real mode segment
  655. ;DX    - Protected mode selector.
  656. ;ECX    - Buffer size.
  657. ;
  658. cwAPI_GetDOSTrans proc near
  659.     assume ds:nothing
  660.     mov    es,cs:apiDSeg
  661.     assume es:_cwMain
  662.     mov    es,es:PSPSegment
  663.     assume es:nothing
  664.     assume ds:_apiCode
  665.     mov    ax,es:w[EPSP_TransReal]
  666.     mov    [ebp+Int_BX],ax
  667.     mov    ax,es:w[EPSP_TransProt]
  668.     mov    [ebp+Int_DX],ax
  669.     mov    eax,es:d[EPSP_TransSize]
  670.     mov    [ebp+Int_ECX],eax
  671.     ret
  672. cwAPI_GetDOSTrans endp
  673.  
  674.  
  675. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  676. ;
  677. ;Set real mode transfer buffer address.
  678. ;
  679. ;On Entry:
  680. ;
  681. ;BX    - Real mode segment.
  682. ;DX    - Protected mode selector.
  683. ;ECX    - Buffer size.
  684. ;
  685. cwAPI_SetDOSTrans proc near
  686.     mov    bx,[ebp+Int_BX]
  687.     mov    dx,[ebp+Int_DX]
  688.     mov    ecx,[ebp+Int_ECX]
  689.     assume ds:nothing
  690.     mov    es,cs:apiDSeg
  691.     assume es:_cwMain
  692.     mov    es,es:PSPSegment
  693.     assume es:nothing
  694.     assume ds:_apiCode
  695.     mov    es:w[EPSP_TransReal],bx
  696.     mov    es:w[EPSP_TransProt],dx
  697.     cmp    ecx,10000h
  698.     jc    @@0
  699.     mov    ecx,65535
  700. @@0:    mov    es:d[EPSP_TransSize],ecx
  701.     ret
  702. cwAPI_SetDOSTrans endp
  703.  
  704.  
  705. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  706. ;
  707. ;Get various useful variable contents.
  708. ;
  709. ;Returns:
  710. ;
  711. ;AX    - 0-4G selector.
  712. ;BX    - Current PSP selector.
  713. ;ECX    - Transfer buffer size.
  714. ;DX    - Transfer buffer real mode segment.
  715. ;ESI    - Transfer buffer offset.
  716. ;DI    - System flags.
  717. ;ES    - Transfer buffer protected mode selector.
  718. ;
  719. cwAPI_Info    proc    near
  720.     assume ds:nothing
  721.     mov    ds,cs:apiDSeg
  722.     assume ds:_cwMain
  723.     mov    di,w[SystemFlags]
  724.     mov    ax,RealSegment
  725.     mov    bx,PspSegment
  726.     mov    es,bx
  727.     mov    dx,es:w[EPSP_TransReal]
  728.     mov    ecx,es:d[EPSP_TransSize]
  729.     mov    es,es:w[EPSP_TransProt]
  730.     xor    esi,esi
  731.     assume ds:_apiCode
  732.     mov    [ebp+Int_AX],ax
  733.     mov    [ebp+Int_BX],bx
  734.     mov    [ebp+Int_ECX],ecx
  735.     mov    [ebp+Int_DX],dx
  736.     mov    [ebp+Int_ESI],esi
  737.     mov    [ebp+Int_DI],di
  738.     mov    [ebp+Int_ES],es
  739.     ret
  740. cwAPI_Info    endp
  741.  
  742.  
  743. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  744. ;
  745. ;Pass control to a real mode interrupt handler.
  746. ;
  747. ;On Entry:
  748. ;
  749. ;BL    - INT number.
  750. ;ES:[E]DI    - Real mode register structure.
  751. ;
  752. cwAPI_IntXX    proc    near
  753.     mov    edi,[ebp+Int_EDI]
  754.     mov    es,[ebp+Int_ES]
  755. ;    mov    bl,[ebp+Int_BL]
  756.     xor    eax,eax
  757.     mov    ax,es
  758.     lsl    eax,eax
  759.     cmp    eax,10000h
  760.     jnc    @@0
  761.     movzx    edi,di
  762. @@0:    assume ds:nothing
  763.     mov    ds,cs:apiDSeg
  764.     assume ds:_cwMain
  765.     cmp    ProtectedType,2
  766.     assume ds:_apiCode
  767.     jnz    @@NoStack0
  768.     assume ds:nothing
  769.     mov    ds,cs:apiDSeg
  770.     assume ds:_cwMain
  771.     sub    DPMIStackOff,RawStackDif
  772.     mov    ax,DPMIStackOff
  773.     add    ax,RawStackDif
  774.     mov    es:Real_SP[edi],ax
  775.     mov    ax,DPMIStackSeg
  776.     mov    es:Real_SS[edi],ax
  777.  
  778. ; MED 05/23/96
  779.     test    cs:apiSystemFlags,1
  780.     jz    medUse32Bit8
  781.     mov    ebx,Int_Flags16
  782.     jmp    medUse16Bit8
  783.  
  784. medUse32Bit8:
  785.     mov    ebx,Int_Flags32
  786.  
  787. medUse16Bit8:
  788.     mov    ax,ss:[ebp+ebx]
  789.     and    ax,1111110011111111b    ;clear Trap and INT flag.
  790.     mov    es:Real_Flags[edi],ax    ; explicitly set flags on DPMI 300h call
  791.  
  792.     assume ds:_apiCode
  793.     jmp    @@DoneStack0
  794. @@NoStack0:
  795.     mov    es:Real_SP[edi],0    ;use DPMI provided stack.
  796.     mov    es:Real_SS[edi],0
  797. @@DoneStack0:
  798.     xor    cx,cx        ;No stack parameters.
  799.     mov    bh,ch        ;no flags.
  800.  
  801.     mov    bl,ss:[ebp+Int_BL]    ; MED 05/23/96
  802.  
  803.     mov    ax,0300h
  804.     cwAPI_CallOld
  805.     cwAPI_C2C
  806.     assume ds:nothing
  807.     mov    ds,cs:apiDSeg
  808.     assume ds:_cwMain
  809.     cmp    ProtectedType,2
  810.     assume ds:_apiCode
  811.     jnz    @@DoneStack1
  812.     assume ds:nothing
  813.     mov    ds,cs:apiDSeg
  814.     assume ds:_cwMain
  815.     add    DPMIStackOff,RawStackDif
  816.     assume ds:_apiCode
  817. @@DoneStack1:    assume ds:nothing
  818.     test    cs:apiSystemFlags,1
  819.     assume ds:_apiCode
  820.     jz    @@Use32Bit8
  821.     mov    ebx,Int_Flags16
  822.     jmp    @@Use16Bit8
  823. @@Use32Bit8:    mov    ebx,Int_Flags32
  824. @@Use16Bit8:    mov    ax,ss:[ebp+ebx]
  825.     and    ax,0000011000000000b        ;retain IF.
  826.     and    es:Real_Flags[edi],1111100111111111b    ;lose IF.
  827.     or    es:Real_Flags[edi],ax
  828.     ret
  829. cwAPI_IntXX    endp
  830.  
  831.  
  832. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  833. ;
  834. ;Pass control to a real mode far routine.
  835. ;
  836. ;On Entry:
  837. ;
  838. ;ES:[E]DI    - Real mode register structure.
  839. ;
  840. cwAPI_FarCallReal proc near
  841.     mov    edi,[ebp+Int_EDI]
  842.     mov    es,[ebp+Int_ES]
  843.     xor    eax,eax
  844.     mov    ax,es
  845.     lsl    eax,eax
  846.     cmp    eax,10000h
  847.     jnc    @@0
  848.     movzx    edi,di
  849. @@0:    pushf
  850.     pop    es:Real_Flags[edi]
  851.     assume ds:nothing
  852.     mov    ds,cs:apiDSeg
  853.     assume ds:_cwMain
  854.     cmp    ProtectedType,2
  855.     assume ds:_apiCode
  856.     jnz    @@NoStack1
  857.     assume ds:nothing
  858.     mov    ds,cs:apiDSeg
  859.     assume ds:_cwMain
  860.     sub    DPMIStackOff,RawStackDif
  861.     mov    ax,DPMIStackOff
  862.     add    ax,RawStackDif
  863.     mov    es:Real_SP[edi],ax
  864.     mov    ax,DPMIStackSeg
  865.     mov    es:Real_SS[edi],ax
  866.     assume ds:_apiCode
  867.     jmp    @@DoneStack2
  868. @@NoStack1:    mov    es:Real_SP[edi],0    ;use DPMI provided stack.
  869.     mov    es:Real_SS[edi],0
  870. @@DoneStack2:    xor    cx,cx        ;No stack parameters.
  871.     xor    bx,bx        ;no flags.
  872.     mov    ax,0301h
  873.     cwAPI_CallOld
  874.     cwAPI_C2C
  875.     assume ds:nothing
  876.     mov    ds,cs:apiDSeg
  877.     assume ds:_cwMain
  878.     cmp    ProtectedType,2
  879.     assume ds:_apiCode
  880.     jnz    @@DoneStack3
  881.     assume ds:nothing
  882.     mov    ds,cs:apiDSeg
  883.     assume ds:_cwMain
  884.     add    DPMIStackOff,RawStackDif
  885.     assume ds:_apiCode
  886. @@DoneStack3:    ;
  887.     assume ds:nothing
  888.     test    cs:apiSystemFlags,1
  889.     assume ds:_apiCode
  890.     jz    @@Use32Bit8
  891.     mov    ebx,Int_Flags16
  892.     jmp    @@Use16Bit8
  893. @@Use32Bit8:    mov    ebx,Int_Flags32
  894. @@Use16Bit8:    mov    ax,ss:[ebp+ebx]
  895.     and    ax,0000011000000000b        ;retain IF.
  896.     and    es:Real_Flags[edi],1111100111111111b    ;lose IF.
  897.     or    es:Real_Flags[edi],ax
  898.     ret
  899. cwAPI_FarCallReal endp
  900.  
  901.  
  902. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  903. ;
  904. ;Allocate a selector.
  905. ;
  906. ;Returns:
  907. ;
  908. ;Carry set on error (no more selectors) else,
  909. ;
  910. ;BX    - new selector.
  911. ;
  912. cwAPI_GetSel    proc    near
  913.     xor    eax,eax
  914.     xor    ebx,ebx
  915.     call    _SetSelector
  916.     cwAPI_C2C
  917.     jc    @@9
  918.     mov    [ebp+Int_BX],bx
  919. @@9:    ret
  920. cwAPI_GetSel    endp
  921.  
  922.  
  923. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  924. ;
  925. ;Allocate multiple selectors.
  926. ;
  927. ;On Entry:
  928. ;
  929. ;CX    - Number of selectors.
  930. ;
  931. ;Returns:
  932. ;
  933. ;Carry set on error (not enough selectors) else,
  934. ;
  935. ;BX    - Base selector.
  936. ;
  937. cwAPI_GetSels    proc    near
  938. ;
  939. ;Get selectors from DPMI.
  940. ;
  941.     mov    cx,[ebp+Int_CX]
  942.     mov    ax,0000h
  943.     cwAPI_CallOld
  944.     cwAPI_C2C
  945.     jc    @@9
  946. ;
  947.     mov    [ebp+Int_BX],ax
  948.     movzx    edx,ax
  949.     movzx    ecx,cx
  950.     mov    ax,Res_SEL
  951. @@0:    call    RegisterResource
  952.     add    edx,8
  953.     dec    ecx
  954.     jnz    @@0
  955. ;
  956. @@9:    ret
  957. cwAPI_GetSels    endp
  958.  
  959.  
  960. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  961. ;
  962. ;Release a selector.
  963. ;
  964. ;On Entry:
  965. ;
  966. ;BX    - Selector to release.
  967. ;
  968. cwAPI_RelSel    proc    near
  969.     mov    bx,[ebp+Int_BX]
  970.     mov    ds,[ebp+Int_DS]
  971.     mov    es,[ebp+Int_ES]
  972.     mov    fs,[ebp+Int_FS]
  973.     mov    gs,[ebp+Int_GS]
  974.     call    _RelSelector
  975.     cwAPI_C2C
  976.     jc    @@9
  977.     mov    [ebp+Int_DS],ds
  978.     mov    [ebp+Int_ES],es
  979.     mov    [ebp+Int_FS],fs
  980.     mov    [ebp+Int_GS],gs
  981. @@9:    ret
  982. cwAPI_RelSel    endp
  983.  
  984.  
  985. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  986. ;
  987. ;Force a selector to be type CODE.
  988. ;
  989. ;On Entry:
  990. ;
  991. ;BX    - Selector.
  992. ;
  993. cwAPI_CodeSel    proc    near
  994.     mov    bx,[ebp+Int_BX]
  995.     call    _CodeSelector
  996.     cwAPI_C2C
  997.     ret
  998. cwAPI_CodeSel    endp
  999.  
  1000.  
  1001. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1002. ;
  1003. ;Allocate a selector with type DATA that maps same memory as another selector.
  1004. ;
  1005. ;On Entry:
  1006. ;
  1007. ;BX    - selector.
  1008. ;
  1009. ;Returns:
  1010. ;
  1011. ;AX    - New selector.
  1012. ;
  1013. cwAPI_AliasSel    proc    near
  1014.     mov    ax,000ah
  1015.     mov    bx,[ebp+Int_BX]
  1016.     cwAPI_CallOld
  1017.     cwAPI_C2C
  1018.     jc    @@9
  1019. ;
  1020.     mov    [ebp+Int_AX],ax
  1021.     pushm    eax,edx
  1022.     movzx    edx,ax
  1023.     mov    ax,Res_SEL
  1024.     call    RegisterResource
  1025.     popm    eax,edx
  1026. ;
  1027. @@9:    ret
  1028. cwAPI_AliasSel    endp
  1029.  
  1030.  
  1031. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1032. ;
  1033. ;Get selector base & limit.
  1034. ;
  1035. ;On Entry:
  1036. ;
  1037. ;BX    - selector.
  1038. ;
  1039. ;Returns:
  1040. ;
  1041. ;CX:DX    - Linear base.
  1042. ;SI:DI    - Byte granular limit.
  1043. ;
  1044. cwAPI_GetSelDet proc near
  1045.     mov    bx,[ebp+Int_BX]
  1046.     call    _DetSelector
  1047.     cwAPI_C2C
  1048.     jc    @@9
  1049. ;
  1050.     mov    ecx,eax        ;get base.
  1051.     mov    dx,cx
  1052.     shr    ecx,16
  1053.     mov    esi,ebx        ;get limit.
  1054.     mov    di,si
  1055.     shr    esi,16
  1056.     mov    [ebp+Int_CX],cx
  1057.     mov    [ebp+Int_DX],dx
  1058.     mov    [ebp+Int_SI],si
  1059.     mov    [ebp+Int_DI],di
  1060. ;
  1061. @@9:    ret
  1062. cwAPI_GetSelDet endp
  1063.  
  1064.  
  1065. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1066. ;
  1067. ;Get selector base & limit.
  1068. ;
  1069. ;On Entry:
  1070. ;
  1071. ;BX    - selector.
  1072. ;
  1073. ;Returns:
  1074. ;
  1075. ;EDX    - base
  1076. ;ECX    - limit
  1077. ;
  1078. cwAPI_GetSelDet32 proc near
  1079.     mov    bx,[ebp+Int_BX]
  1080.     call    _DetSelector
  1081.     cwAPI_C2C
  1082.     jc    @@9
  1083. ;
  1084.     mov    [ebp+Int_EDX],eax
  1085.     mov    [ebp+Int_ECX],ebx
  1086. ;
  1087. @@9:    ret
  1088. cwAPI_GetSelDet32 endp
  1089.  
  1090.  
  1091. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1092. ;
  1093. ;Set selectors base & limit.
  1094. ;
  1095. ;On Entry:
  1096. ;
  1097. ;BX    - selector
  1098. ;CX:DX    - Linear base.
  1099. ;SI:DI    - Byte granular limit.
  1100. ;
  1101. cwAPI_SetSelDet proc near
  1102.     mov    cx,[ebp+Int_CX]
  1103.     mov    dx,[ebp+Int_DX]
  1104.     mov    si,[ebp+Int_SI]
  1105.     mov    di,[ebp+Int_DI]
  1106.     shl    ecx,16        ;Get base to somewhere useful.
  1107.     mov    cx,dx
  1108.     mov    eax,ecx
  1109.     shl    esi,16        ;get limit to somewhere useful.
  1110.     mov    si,di
  1111.     mov    ebx,esi
  1112.     mov    cx,[ebp+Int_BX]
  1113.     call    _SizeSelector
  1114.     cwAPI_C2C
  1115.     ret
  1116. cwAPI_SetSelDet endp
  1117.  
  1118.  
  1119. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1120. ;
  1121. ;Set a selectors details.
  1122. ;
  1123. ;On Entry:
  1124. ;
  1125. ;BX    - selector
  1126. ;EDX    - base
  1127. ;ECX    - limit.
  1128. ;
  1129. cwAPI_SetSelDet32 proc near
  1130.     mov    cx,[ebp+Int_BX]
  1131.     mov    eax,[ebp+Int_EDX]
  1132.     mov    ebx,[ebp+Int_ECX]
  1133.     call    _SizeSelector
  1134.     cwAPI_C2C
  1135.     ret
  1136. cwAPI_SetSelDet32 endp
  1137.  
  1138.  
  1139. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1140. ;
  1141. ;Allocate some memory with a selector attatched.
  1142. ;
  1143. ;On Entry:
  1144. ;
  1145. ;CX:DX    - Size of block required in bytes. (-1:-1 to get maximum memory size)
  1146. ;
  1147. ;On Exit:
  1148. ;
  1149. ;Carry clear if OK &
  1150. ;
  1151. ;BX    - Selector to access the block with.
  1152. ;
  1153. ;Else if CX:DX was -1, CX:DX is size of largest block available.
  1154. ;
  1155. cwAPI_GetMem    proc    near
  1156.     mov    cx,[ebp+Int_CX]
  1157.     mov    dx,[ebp+Int_DX]
  1158.     shl    ecx,16
  1159.     mov    cx,dx
  1160.  
  1161. ; MED 06/25/97
  1162.     push    ds        ; test padding flag
  1163.     mov    ds,cs:apiDSeg
  1164.     assume ds:_cwMain
  1165.     test    Pad1Flag,-1
  1166.     pop    ds
  1167.     assume ds:nothing
  1168.     je    gm2        ; padding flag not turned on
  1169.     test    ecx,0ffff0000h
  1170.     jne    gm2        ; don't pad >64K allocation
  1171.     add    ecx,1023
  1172.     and    ecx,NOT 1023    ; pad to 1K-boundary allocation
  1173. gm2:
  1174.  
  1175.     call    mcbGetMemLinear32
  1176.     jc    @@2
  1177.     sys    GetSel
  1178.     jc    @@0
  1179.     mov    edx,esi
  1180.     jecxz    @@3
  1181.     dec    ecx        ;limit=length-1
  1182. @@3:    sys    SetSelDet32
  1183.     mov    [ebp+Int_BX],bx
  1184.     clc
  1185.     jmp    @@1
  1186. @@0:    call    mcbRelMemLinear32
  1187.     stc
  1188.     jmp    @@1
  1189.     ;
  1190. @@2:    mov    dx,cx
  1191.     shr    ecx,16
  1192.     mov    ax,[ebp+Int_CX]
  1193.     shl    eax,16
  1194.     mov    ax,[ebp+Int_DX]
  1195.     cmp    eax,-2
  1196.     jz    @@5
  1197.     cmp    eax,-1
  1198.     jnz    @@4
  1199. @@5:    mov    [ebp+Int_CX],cx
  1200.     mov    [ebp+Int_DX],dx
  1201. @@4:    stc
  1202.     ;
  1203. @@1:    cwAPI_C2C
  1204.     ret
  1205. cwAPI_GetMem    endp
  1206.  
  1207.  
  1208. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1209. ;
  1210. ;Allocate some memory and return selector:offset (16-bit).
  1211. ;
  1212. ;On Entry:
  1213. ;
  1214. ;CX:DX    - Size of block required in bytes.
  1215. ;
  1216. ;On Exit:
  1217. ;
  1218. ;Carry set on error else,
  1219. ;
  1220. ;SI:DI    - selector:offset of allocated memory.
  1221. ;
  1222. cwAPI_GetMemSO    proc    near
  1223.     mov    cx,[ebp+Int_CX]
  1224.     mov    dx,[ebp+Int_DX]
  1225.     shl    ecx,16
  1226.     mov    cx,dx
  1227.     call    mcbGetMemLinear32    ;allocate some memory.
  1228.     jc    @@9
  1229.     assume ds:nothing
  1230.     cmp    cs:mcbLastChunk,0    ;DPMI memory?
  1231.     assume ds:_apiCode
  1232.     jnz    @@1
  1233. ;
  1234. ;Allocate a selector for this memory.
  1235. ;
  1236.     sys    GetSel
  1237.     jc    @@8
  1238.     mov    edx,esi
  1239.     jecxz    @@0
  1240.     dec    ecx        ;limit=length-1
  1241. @@0:    sys    SetSelDet32
  1242.     xor    dx,dx
  1243.     jmp    @@7
  1244. ;
  1245. ;Get chunk's selector.
  1246. ;
  1247. @@1:    push    es
  1248.     assume ds:nothing
  1249.     mov    es,cs:apiDSeg
  1250.     assume es:_cwMain
  1251.     mov    es,RealSegment
  1252.     assume es:nothing
  1253.     mov    edi,cs:mcbLastChunk
  1254.     assume ds:_apiCode
  1255.     mov    bx,es:[edi+mcbChunkSel]    ;get chunk selector.
  1256.     pop    es
  1257.     mov    edx,esi
  1258.     sub    edx,edi        ;get blocks offset.
  1259. ;
  1260. @@7:    mov    [ebp+Int_SI],bx
  1261.     mov    [ebp+Int_DI],dx
  1262.     clc
  1263.     jmp    @@9
  1264. ;
  1265. @@8:    call    mcbRelMemLinear32
  1266.     stc
  1267. ;
  1268. @@9:    cwAPI_C2C
  1269.     ret
  1270. cwAPI_GetMemSO    endp
  1271.  
  1272.  
  1273. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1274. ;
  1275. ;On Entry:
  1276. ;
  1277. ;ECX    - Size of block required in bytes. (-1 to get maximum memory size)
  1278. ;
  1279. ;On Exit:
  1280. ;
  1281. ;Carry clear if OK &
  1282. ;
  1283. ;BX    - Selector to access the block with.
  1284. ;
  1285. ;Else if ECX was -1, ECX is size of largest block available.
  1286. ;
  1287. cwAPI_GetMem32    proc near
  1288.     mov    ecx,[ebp+Int_ECX]
  1289.     call    mcbGetMemLinear32
  1290.     jc    @@2
  1291.     sys    GetSel
  1292.     jc    @@0
  1293.     mov    edx,esi
  1294.     jecxz    @@3
  1295.     dec    ecx        ;limit=length-1
  1296.     sys    SetSelDet32
  1297. @@3:    mov    [ebp+Int_BX],bx
  1298.     clc
  1299.     jmp    @@1
  1300. @@0:    call    mcbRelMemLinear32
  1301.     stc
  1302.     jmp    @@1
  1303.     ;
  1304. @@2:    cmp    d[ebp+Int_ECX],-1
  1305.     jz    @@5
  1306.     cmp    d[ebp+Int_ECX],-2
  1307.     jnz    @@4
  1308. @@5:    mov    [ebp+Int_ECX],ecx
  1309. @@4:    stc
  1310.     ;
  1311. @@1:    cwAPI_C2C
  1312.     ret
  1313. cwAPI_GetMem32    endp
  1314.  
  1315.  
  1316. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1317. ;
  1318. ;Re-size a previously allocated block of memory.
  1319. ;
  1320. ;On Entry:
  1321. ;
  1322. ;BX    - Selector for block.
  1323. ;CX:DX    - New size of block required in bytes.
  1324. ;
  1325. ;On Exit:
  1326. ;
  1327. ;Carry clear if OK.
  1328. ;
  1329. cwAPI_ResMem    proc    near
  1330.     mov    bx,[ebp+Int_BX]
  1331.     mov    cx,[ebp+Int_CX]
  1332.     mov    dx,[ebp+Int_DX]
  1333.     shl    ecx,16        ;convert new size to 32-bit.
  1334.     mov    cx,dx
  1335.     push    ecx
  1336.     sys    GetSelDet32        ;Get selector base address.
  1337.     mov    esi,edx
  1338.     pop    ecx
  1339.     jc    @@9
  1340.     call    mcbResMemLinear32    ;re-size the memory.
  1341.     jc    @@9
  1342.     mov    edx,esi
  1343.     dec    ecx
  1344.     sys    SetSelDet32
  1345. @@9:    cwAPI_C2C
  1346.     ret
  1347. cwAPI_ResMem    endp
  1348.  
  1349.  
  1350. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1351. ;
  1352. ;Re-size a previously allocated block of memory.
  1353. ;
  1354. ;On Entry:
  1355. ;
  1356. ;SI:DI    - Selector:offset for block.
  1357. ;CX:DX    - New size of block required in bytes.
  1358. ;
  1359. ;On Exit:
  1360. ;
  1361. ;Carry set on error else,
  1362. ;
  1363. ;SI:DI    - selector:offset new block address.
  1364. ;
  1365. cwAPI_ResMemSO    proc    near
  1366.     mov    ds,[ebp+Int_DS]
  1367.     mov    es,[ebp+Int_ES]
  1368.     mov    fs,[ebp+Int_FS]
  1369.     mov    gs,[ebp+Int_GS]
  1370. ;
  1371.     mov    bx,w[ebp+Int_SI]
  1372.     sys    GetSelDet32        ;get selectors details.
  1373.     jc    @@9
  1374.     mov    esi,edx
  1375.     movzx    eax,w[ebp+Int_DI]
  1376.     add    esi,eax        ;get memory blocks address.
  1377.     mov    cx,[ebp+Int_CX]
  1378.     mov    dx,[ebp+Int_DX]
  1379.     shl    ecx,16        ;convert new size to 32-bit.
  1380.     mov    cx,dx
  1381.     call    mcbResMemLinear32    ;re-size the memory.
  1382.     jc    @@9
  1383. ;
  1384. ;Check new block type.
  1385. ;
  1386.     assume ds:nothing
  1387.     cmp    cs:mcbLastChunk,0    ;DPMI memory?
  1388.     assume ds:_apiCode
  1389.     jnz    @@1
  1390. ;
  1391. ;Update selectors details.
  1392. ;
  1393.     mov    edx,esi
  1394.     dec    ecx
  1395.     sys    SetSelDet32
  1396.     xor    dx,dx
  1397.     jmp    @@7
  1398. ;
  1399. ;Get chunk's selector.
  1400. ;
  1401. @@1:    push    es
  1402.     assume ds:nothing
  1403.     mov    es,cs:apiDSeg
  1404.     assume es:_cwMain
  1405.     mov    es,RealSegment
  1406.     assume es:nothing
  1407.     mov    edi,cs:mcbLastChunk
  1408.     assume ds:_apiCode
  1409.     mov    bx,es:[edi+mcbChunkSel]    ;get chunk selector.
  1410.     pop    es
  1411.     mov    edx,esi
  1412.     sub    edx,edi        ;get blocks offset.
  1413. ;
  1414. ;Check if the old block had it's own selector.
  1415. ;
  1416.     cmp    w[ebp+Int_DI],0    ;offset of zero?
  1417.     jnz    @@7
  1418.     push    bx
  1419.     mov    bx,w[ebp+Int_SI]
  1420.     sys    RelSel        ;release the selector.
  1421.     pop    bx
  1422. ;
  1423. @@7:    mov    [ebp+Int_SI],bx
  1424.     mov    [ebp+Int_DI],dx
  1425.     clc
  1426. ;
  1427. @@9:    cwAPI_C2C
  1428.     mov    [ebp+Int_DS],ds
  1429.     mov    [ebp+Int_ES],es
  1430.     mov    [ebp+Int_FS],fs
  1431.     mov    [ebp+Int_GS],gs
  1432.     ret
  1433. cwAPI_ResMemSO    endp
  1434.  
  1435.  
  1436. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1437. ;
  1438. ;Re-size a previously allocated block of memory.
  1439. ;
  1440. ;On Entry:
  1441. ;
  1442. ;BX    - Selector for block.
  1443. ;ECX    - New size of block required in bytes.
  1444. ;
  1445. ;On Exit:
  1446. ;
  1447. ;Carry clear if OK.
  1448. ;
  1449. cwAPI_ResMem32    proc    near
  1450.     mov    bx,[ebp+Int_BX]
  1451.     mov    ecx,[ebp+Int_ECX]
  1452.     push    ecx
  1453.     sys    GetSelDet32        ;Get selector base address.
  1454.     mov    esi,edx
  1455.     pop    ecx
  1456.     jc    @@9
  1457.     call    mcbResMemLinear32    ;re-size the memory.
  1458.     jc    @@9
  1459.     mov    edx,esi
  1460.     dec    ecx
  1461.     sys    SetSelDet32
  1462. @@9:    cwAPI_C2C
  1463.     ret
  1464. cwAPI_ResMem32    endp
  1465.  
  1466.  
  1467. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1468. ;
  1469. ;Release previously allocated block of memory. Is be used for memory allocated
  1470. ;by either GetMem or GetMem32.
  1471. ;
  1472. ;
  1473. ;On Entry:
  1474. ;
  1475. ;BX    - Selector for block to release.
  1476. ;
  1477. cwAPI_RelMem    proc    near
  1478.     mov    bx,[ebp+Int_BX]
  1479.     sys    GetSelDet32        ;Get selector base address.
  1480.     jc    @@9
  1481.     mov    esi,edx
  1482.     mov    ds,[ebp+Int_DS]
  1483.     mov    es,[ebp+Int_ES]
  1484.     mov    fs,[ebp+Int_FS]
  1485.     mov    gs,[ebp+Int_GS]
  1486.     sys    RelSel        ;release the selector.
  1487.     mov    [ebp+Int_DS],ds
  1488.     mov    [ebp+Int_ES],es
  1489.     mov    [ebp+Int_FS],fs
  1490.     mov    [ebp+Int_GS],gs
  1491.     call    mcbRelMemLinear32    ;release the memory.
  1492. @@9:    cwAPI_C2C
  1493.     ret
  1494. cwAPI_RelMem    endp
  1495.  
  1496.  
  1497. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1498. ;
  1499. ;Release block of memory allocated via GetMemSO.
  1500. ;
  1501. ;On Entry:
  1502. ;
  1503. ;SI:DI    - Selector:offset for block to release.
  1504. ;
  1505. cwAPI_RelMemSO    proc    near
  1506. ;
  1507. ;Zero any segment registers using this selector.
  1508. ;
  1509.     mov    bx,w[ebp+Int_SI]
  1510.     and    bx,0ffffh-3
  1511.     jz    @@bad        ; MED 11/18/96, screen out null pointer releases
  1512.     xor    cx,cx
  1513.     mov    ax,w[ebp+Int_DS]
  1514.     and    ax,0ffffh-3
  1515.     cmp    ax,bx
  1516.     jnz    @@0
  1517.     mov    w[ebp+Int_DS],cx
  1518.     mov    ds,cx
  1519. @@0:    mov    ax,w[ebp+Int_ES]
  1520.     and    ax,0ffffh-3
  1521.     cmp    ax,bx
  1522.     jnz    @@1
  1523.     mov    w[ebp+Int_ES],cx
  1524.     mov    es,cx
  1525. @@1:    mov    ax,w[ebp+Int_FS]
  1526.     and    ax,0ffffh-3
  1527.     cmp    ax,bx
  1528.     jnz    @@2
  1529.     mov    w[ebp+Int_FS],cx
  1530.     mov    fs,cx
  1531. @@2:    mov    ax,w[ebp+Int_GS]
  1532.     and    ax,0ffffh-3
  1533.     cmp    ax,bx
  1534.     jnz    @@3
  1535.     mov    w[ebp+Int_GS],cx
  1536.     mov    gs,cx
  1537. @@3:    ;
  1538.     mov    bx,w[ebp+Int_SI]
  1539.     sys    GetSelDet32        ;get selectors details.
  1540.     jc    @@9
  1541.     mov    esi,edx
  1542.     movzx    eax,w[ebp+Int_DI]
  1543.     add    esi,eax        ;get memory blocks address.
  1544.     call    mcbRelMemLinear32    ;release the memory.
  1545. ;
  1546. ;Check if block had it's own selector.
  1547. ;
  1548.     cmp    w[ebp+Int_DI],0    ;offset of zero?
  1549.     jnz    @@4
  1550.     mov    bx,w[ebp+Int_SI]
  1551.     sys    RelSel        ;release the selector.
  1552. ;
  1553. @@4:    clc
  1554. ;
  1555. @@9:    cwAPI_C2C
  1556.     ret
  1557.  
  1558. ; MED 11/18/96
  1559. @@bad:
  1560.     stc
  1561.     jmp    @@9
  1562.  
  1563. cwAPI_RelMemSO    endp
  1564.  
  1565. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1566. ;
  1567. ;Allocate a block of memory without a selector.
  1568. ;
  1569. ;On Entry:
  1570. ;
  1571. ;CX:DX    - Size of block required in bytes.
  1572. ;
  1573. ;On Exit:
  1574. ;
  1575. ;Carry clear if OK &,
  1576. ;
  1577. ;SI:DI    - Linear address of block allocated.
  1578. ;
  1579. cwAPI_GetMemLinear proc near
  1580.     mov    cx,[ebp+Int_CX]
  1581.     mov    dx,[ebp+Int_DX]
  1582.     shl    ecx,16
  1583.     mov    cx,dx
  1584.     call    mcbGetMemLinear32
  1585.     jc    @@9
  1586.     mov    di,si
  1587.     shr    esi,16
  1588.     mov    [ebp+Int_SI],si
  1589.     mov    [ebp+Int_DI],di
  1590.     clc
  1591. @@9:    cwAPI_C2C
  1592.     ret
  1593. cwAPI_GetMemLinear endp
  1594.  
  1595.  
  1596. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1597. ;
  1598. ;Allocate a block of memory without a selector.
  1599. ;
  1600. ;On Entry:
  1601. ;
  1602. ;ECX    - Size of block required in bytes.
  1603. ;
  1604. ;On Exit:
  1605. ;
  1606. ;Carry clear if OK &,
  1607. ;
  1608. ;ESI    - Linear address of block allocated.
  1609. ;
  1610. cwAPI_GetMemLinear32 proc near
  1611.     mov    ecx,[ebp+Int_ECX]
  1612.     call    mcbGetMemLinear32
  1613.     cwAPI_C2C
  1614.     jc    @@9
  1615.     mov    [ebp+Int_ESI],esi
  1616. @@9:    ret
  1617. cwAPI_GetMemLinear32 endp
  1618.  
  1619.  
  1620. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1621. ;
  1622. ;Re-size a previously allocated block of memory without a selector.
  1623. ;
  1624. ;On Entry:
  1625. ;
  1626. ;SI:DI    - Linear address of block to re-size.
  1627. ;CX:DX    - Size of block required in bytes.
  1628. ;
  1629. ;On Exit:
  1630. ;
  1631. ;Carry clear if OK &,
  1632. ;
  1633. ;SI:DI    - New linear address of block.
  1634. ;
  1635. cwAPI_ResMemLinear proc near
  1636.     mov    si,[ebp+Int_SI]
  1637.     mov    di,[ebp+Int_DI]
  1638.     mov    cx,[ebp+Int_CX]
  1639.     mov    dx,[ebp+Int_DX]
  1640.     shl    ecx,16
  1641.     mov    cx,dx
  1642.     shl    esi,16
  1643.     mov    si,di
  1644.     call    mcbResMemLinear32
  1645.     jc    @@9
  1646.     mov    di,si
  1647.     shr    esi,16
  1648.     mov    [ebp+Int_SI],si
  1649.     mov    [ebp+Int_DI],di
  1650.     clc
  1651. @@9:    cwAPI_C2C
  1652.     ret
  1653. cwAPI_ResMemLinear endp
  1654.  
  1655.  
  1656. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1657. ;
  1658. ;Re-size a previously allocated block of memory without a selector.
  1659. ;
  1660. ;On Entry:
  1661. ;
  1662. ;ESI    - Linear address of block to re-size.
  1663. ;ECX    - Size of block required in bytes.
  1664. ;
  1665. ;On Exit:
  1666. ;
  1667. ;Carry clear if OK &,
  1668. ;
  1669. ;ESI    - New linear address of block.
  1670. ;
  1671. cwAPI_ResMemLinear32 proc near
  1672.     mov    esi,[ebp+Int_ESI]
  1673.     mov    ecx,[ebp+Int_ECX]
  1674.     call    mcbResMemLinear32
  1675.     jc    @@9
  1676.     mov    [ebp+Int_ESI],esi
  1677. @@9:    cwAPI_C2C
  1678.     ret
  1679. cwAPI_ResMemLinear32 endp
  1680.  
  1681.  
  1682. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1683. ;
  1684. ;Release previously allocated block of memory (linear address).
  1685. ;
  1686. ;On Entry:
  1687. ;
  1688. ;SI:DI    - Linear address of block to release.
  1689. ;
  1690. ;On Exit:
  1691. ;
  1692. cwAPI_RelMemLinear proc near
  1693.     mov    si,[ebp+Int_SI]
  1694.     mov    di,[ebp+Int_DI]
  1695.     shl    esi,16
  1696.     mov    si,di
  1697.     call    mcbRelMemLinear32
  1698.     cwAPI_C2C
  1699.     ret
  1700. cwAPI_RelMemLinear endp
  1701.  
  1702.  
  1703. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1704. ;
  1705. ;Release previously allocated block of memory (linear address).
  1706. ;
  1707. ;On Entry:
  1708. ;
  1709. ;ESI    - Linear address of block to release.
  1710. ;
  1711. ;On Exit:
  1712. ;
  1713. cwAPI_RelMemLinear32 proc near
  1714.     mov    esi,[ebp+Int_ESI]
  1715.     call    mcbRelMemLinear32
  1716.     cwAPI_C2C
  1717.     ret
  1718. cwAPI_RelMemLinear32 endp
  1719.  
  1720.  
  1721. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1722. ;
  1723. ;Allocate an application relative block of memory.
  1724. ;
  1725. ;On Entry:
  1726. ;
  1727. ;EBX    - Size of block required in bytes.
  1728. ;
  1729. ;On Exit:
  1730. ;
  1731. ;Carry clear if OK &,
  1732. ;
  1733. ;ESI    - Application relative linear address of block allocated.
  1734. ;
  1735. cwAPI_GetMemNear proc near
  1736.     mov    ecx,[ebp+Int_EBX]
  1737.     call    mcbGetMemLinear32
  1738.     jc    @@9
  1739.     assume ds:nothing
  1740.     mov    ds,cs:apiDSeg
  1741.     assume ds:_cwMain
  1742.     mov    ds,PSPSegment
  1743.     sub    esi,ds:d[EPSP_NearBase]
  1744.     assume ds:_apiCode
  1745.     mov    [ebp+Int_ESI],esi
  1746.     clc
  1747. @@9:    cwAPI_C2C
  1748.     ret
  1749. cwAPI_GetMemNear endp
  1750.  
  1751.  
  1752. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1753. ;
  1754. ;Re-size a previously allocated application relative block of memory.
  1755. ;
  1756. ;On Entry:
  1757. ;
  1758. ;EBX    - Size of block required in bytes.
  1759. ;ESI    - application relative linear address of block to re-size.
  1760. ;
  1761. ;On Exit:
  1762. ;
  1763. ;Carry clear if OK &,
  1764. ;
  1765. ;ESI    - New application relative linear address of block.
  1766. ;
  1767. cwAPI_ResMemNear proc near
  1768.     mov    ecx,[ebp+Int_EBX]
  1769.     mov    esi,[ebp+Int_ESI]
  1770.     assume ds:nothing
  1771.     mov    ds,cs:apiDSeg
  1772.     assume ds:_cwMain
  1773.     mov    ds,PSPSegment
  1774.     add    esi,ds:d[EPSP_NearBase]
  1775.     assume ds:_apiCode
  1776.     call    mcbResMemLinear32
  1777.     jc    @@9
  1778.     assume ds:nothing
  1779.     mov    ds,cs:apiDSeg
  1780.     assume ds:_cwMain
  1781.     mov    ds,PSPSegment
  1782.     sub    esi,ds:d[EPSP_NearBase]
  1783.     assume ds:_apiCode
  1784.     mov    [ebp+Int_ESI],esi
  1785.     clc
  1786. @@9:    cwAPI_C2C
  1787.     ret
  1788. cwAPI_ResMemNear endp
  1789.  
  1790.  
  1791. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1792. ;
  1793. ;Release previously allocated application relative block of memory.
  1794. ;
  1795. ;On Entry:
  1796. ;
  1797. ;ESI    - Application relative linear address of block to release.
  1798. ;
  1799. cwAPI_RelMemNear proc near
  1800.     mov    esi,[ebp+Int_ESI]
  1801.     assume ds:nothing
  1802.     mov    ds,cs:apiDSeg
  1803.     assume ds:_cwMain
  1804.     mov    ds,PSPSegment
  1805.     add    esi,ds:d[EPSP_NearBase]
  1806.     assume ds:_apiCode
  1807.     call    mcbRelMemLinear32
  1808.     cwAPI_C2C
  1809.     ret
  1810. cwAPI_RelMemNear endp
  1811.  
  1812.  
  1813. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1814. ;
  1815. ;Convert linear address to application relative address.
  1816. ;
  1817. ;On Entry:
  1818. ;
  1819. ;ESI    - Linear address to convert.
  1820. ;
  1821. ;On Exit:
  1822. ;
  1823. ;ESI    - Application relative linear address.
  1824. ;
  1825. cwAPI_Linear2Near proc near
  1826.     mov    esi,[ebp+Int_ESI]
  1827.     assume ds:nothing
  1828.     mov    ds,cs:apiDSeg
  1829.     assume ds:_cwMain
  1830.     mov    ds,PSPSegment
  1831.     sub    esi,ds:d[EPSP_NearBase]
  1832.     assume ds:_apiCode
  1833.     mov    [ebp+Int_ESI],esi
  1834.     ret
  1835. cwAPI_Linear2Near endp
  1836.  
  1837.  
  1838. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1839. ;
  1840. ;Convert application relative address to linear address.
  1841. ;
  1842. ;On Entry:
  1843. ;
  1844. ;ESI    - Application relative linear address.
  1845. ;
  1846. ;On Exit:
  1847. ;
  1848. ;ESI    - Linear address to convert.
  1849. ;
  1850. cwAPI_Near2Linear proc near
  1851.     mov    esi,[ebp+Int_ESI]
  1852.     assume ds:nothing
  1853.     mov    ds,cs:apiDSeg
  1854.     assume ds:_cwMain
  1855.     mov    ds,PSPSegment
  1856.     add    esi,ds:d[EPSP_NearBase]
  1857.     assume ds:_apiCode
  1858.     mov    [ebp+Int_ESI],esi
  1859.     ret
  1860. cwAPI_Near2Linear endp
  1861.  
  1862.  
  1863. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1864. ;
  1865. ;Lock a region of memory.
  1866. ;
  1867. ;On Entry:
  1868. ;
  1869. ;BX:CX    - Starting linear address of memory to lock.
  1870. ;SI:DI    - Size of region to lock in bytes.
  1871. ;
  1872. ;On Exit:
  1873. ;
  1874. ;Carry set on error, none of the memory locked, else memory is locked.
  1875. ;
  1876. cwAPI_LockMem    proc    near
  1877.     mov    bx,[ebp+Int_BX]
  1878.     mov    cx,[ebp+Int_CX]
  1879.     mov    si,[ebp+Int_SI]
  1880.     mov    di,[ebp+Int_DI]
  1881.     mov    ax,0600h
  1882.     cwAPI_CallOld
  1883.     jc    @@9
  1884. ;
  1885.     mov    dx,bx
  1886.     shl    edx,16
  1887.     mov    dx,cx
  1888.     mov    cx,si
  1889.     shl    ecx,16
  1890.     mov    cx,di
  1891.     mov    ax,Res_LOCK
  1892.     call    RegisterResource
  1893.     clc
  1894. ;
  1895. @@9:    cwAPI_C2C
  1896.     ret
  1897. cwAPI_LockMem    endp
  1898.  
  1899.  
  1900. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1901. ;
  1902. ;Lock a region of memory.
  1903. ;
  1904. ;On Entry:
  1905. ;
  1906. ;ESI    - Starting linear address of memory to lock.
  1907. ;ECX    - Size of region to lock in bytes.
  1908. ;
  1909. ;On Exit:
  1910. ;
  1911. ;Carry set on error, none of the memory locked, else memory is locked.
  1912. ;
  1913. cwAPI_LockMem32 proc near
  1914.     mov    esi,[ebp+Int_ESI]
  1915.     mov    ecx,[ebp+Int_ECX]
  1916.     xchg    esi,ecx
  1917.     mov    ebx,ecx
  1918.     shr    ebx,16
  1919.     mov    di,si
  1920.     shr    esi,16
  1921.     mov    ax,0600h
  1922.     cwAPI_CallOld
  1923.     jc    @@9
  1924.     mov    dx,bx
  1925.     shl    edx,16
  1926.     mov    dx,cx
  1927.     mov    cx,si
  1928.     shl    ecx,16
  1929.     mov    cx,di
  1930.     mov    ax,Res_LOCK
  1931.     call    RegisterResource
  1932.     clc
  1933. @@9:    cwAPI_C2C
  1934.     ret
  1935. cwAPI_LockMem32 endp
  1936.  
  1937.  
  1938. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1939. ;
  1940. ;Un-lock a region of memory.
  1941. ;
  1942. ;On Entry:
  1943. ;
  1944. ;BX:CX    - Starting linear address of memory to unlock
  1945. ;SI:DI    - Size of region to unlock in bytes
  1946. ;
  1947. cwAPI_UnLockMem proc near
  1948.     mov    bx,[ebp+Int_BX]
  1949.     mov    cx,[ebp+Int_CX]
  1950.     mov    si,[ebp+Int_SI]
  1951.     mov    di,[ebp+Int_DI]
  1952.     mov    ax,0601h
  1953.     cwAPI_CallOld
  1954.     jc    @@9
  1955.     mov    dx,bx
  1956.     shl    edx,16
  1957.     mov    dx,cx
  1958.     mov    cx,si
  1959.     shl    ecx,16
  1960.     mov    cx,di
  1961.     mov    ax,Res_LOCK
  1962.     call    ReleaseResource
  1963.     clc
  1964. @@9:    cwAPI_C2C
  1965.     ret
  1966. cwAPI_UnLockMem endp
  1967.  
  1968.  
  1969. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1970. ;
  1971. ;Un-lock a region of memory.
  1972. ;
  1973. ;On Entry:
  1974. ;
  1975. ;ESI    - Starting linear address of memory to unlock
  1976. ;ECX    - Size of region to unlock in bytes
  1977. ;
  1978. ;NOTES:
  1979. ;
  1980. ;This will allow the memory to be swapped to disk by the VMM if neccessary.
  1981. ;Areas below and above the specified memory will also be un-locked if the
  1982. ;specified region is not page aligned.
  1983. ;
  1984. cwAPI_UnLockMem32 proc near
  1985.     mov    esi,[ebp+Int_ESI]
  1986.     mov    ecx,[ebp+Int_ECX]
  1987.     xchg    esi,ecx
  1988.     mov    ebx,ecx
  1989.     shr    ebx,16
  1990.     mov    di,si
  1991.     shr    esi,16
  1992.     mov    ax,0601h
  1993.     cwAPI_CallOld
  1994.     jc    @@9
  1995.     mov    dx,bx
  1996.     shl    edx,16
  1997.     mov    dx,cx
  1998.     mov    cx,si
  1999.     shl    ecx,16
  2000.     mov    cx,di
  2001.     mov    ax,Res_LOCK
  2002.     call    ReleaseResource
  2003.     clc
  2004. @@9:    cwAPI_C2C
  2005.     ret
  2006. cwAPI_UnLockMem32 endp
  2007.  
  2008.  
  2009. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2010. ;
  2011. ;Lock a region of memory using application relative address.
  2012. ;
  2013. ;On Entry:
  2014. ;
  2015. ;ESI    - Starting linear address of memory to lock.
  2016. ;EBX    - Size of region to lock in bytes.
  2017. ;
  2018. ;On Exit:
  2019. ;
  2020. ;Carry set on error, none of the memory locked, else memory is locked.
  2021. ;
  2022. cwAPI_LockMemNear proc near
  2023.     mov    esi,[ebp+Int_ESI]
  2024.     mov    ebx,[ebp+Int_EBX]
  2025.     assume ds:nothing
  2026.     mov    ds,cs:apiDSeg
  2027.     assume ds:_cwMain
  2028.     mov    ds,PSPSegment
  2029.     add    esi,ds:d[EPSP_NearBase]
  2030.     assume ds:_apiCode
  2031.     xchg    esi,ebx
  2032.     mov    di,si
  2033.     shr    esi,16
  2034.     mov    cx,bx
  2035.     shr    ebx,16
  2036.     mov    ax,0600h
  2037.     cwAPI_CallOld
  2038.     jc    @@9
  2039.     mov    dx,bx
  2040.     shl    edx,16
  2041.     mov    dx,cx
  2042.     mov    cx,si
  2043.     shl    ecx,16
  2044.     mov    cx,di
  2045.     mov    ax,Res_LOCK
  2046.     call    RegisterResource
  2047.     clc
  2048. @@9:    cwAPI_C2C
  2049.     ret
  2050. cwAPI_LockMemNear endp
  2051.  
  2052.  
  2053. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2054. ;
  2055. ;Un-lock a region of memory using application relative address.
  2056. ;
  2057. ;On Entry:
  2058. ;
  2059. ;ESI    - Starting linear address of memory to unlock
  2060. ;EBX    - Size of region to unlock in bytes
  2061. ;
  2062. cwAPI_UnLockMemNear proc near
  2063.     mov    esi,[ebp+Int_ESI]
  2064.     mov    ecx,[ebp+Int_ECX]
  2065.     assume ds:nothing
  2066.     mov    ds,cs:apiDSeg
  2067.     assume ds:_cwMain
  2068.     mov    ds,PSPSegment
  2069.     add    esi,ds:d[EPSP_NearBase]
  2070.     assume ds:_apiCode
  2071.     xchg    esi,ebx
  2072.     mov    di,si
  2073.     shr    esi,16
  2074.     mov    cx,bx
  2075.     shr    ebx,16
  2076.     mov    ax,0601h
  2077.     cwAPI_CallOld
  2078.     jc    @@9
  2079.     mov    dx,bx
  2080.     shl    edx,16
  2081.     mov    dx,cx
  2082.     mov    cx,si
  2083.     shl    ecx,16
  2084.     mov    cx,di
  2085.     mov    ax,Res_LOCK
  2086.     call    ReleaseResource
  2087.     clc
  2088. @@9:    cwAPI_C2C
  2089.     ret
  2090. cwAPI_UnLockMemNear endp
  2091.  
  2092.  
  2093. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2094. ;
  2095. ;Allocate a region of DOS (conventional) memory.
  2096. ;
  2097. ;On Entry:
  2098. ;
  2099. ;BX    - Number of paragraphs (16 byte blocks) required.
  2100. ;
  2101. ;On Exit:
  2102. ;
  2103. ;If function was successful:
  2104. ;Carry flag is clear.
  2105. ;
  2106. ;AX    - Initial real mode segment of allocated block
  2107. ;DX    - Initial selector for allocated block
  2108. ;
  2109. ;If function was not successful:
  2110. ;Carry flag is set.
  2111. ;
  2112. ;AX    - DOS error code.
  2113. ;BX    - Size of largest available block in paragraphs.
  2114. ;
  2115. cwAPI_GetMemDOS proc near
  2116.     mov    bx,[ebp+Int_BX]
  2117.     mov    ax,0100h
  2118.     cwAPI_CallOld
  2119.     mov    [ebp+Int_AX],ax
  2120.     cwAPI_C2C
  2121.     jnc    @@0
  2122.     mov    [ebp+Int_BX],bx
  2123.     jmp    @@9
  2124. ;
  2125. @@0:    mov    [ebp+Int_DX],dx
  2126.     movzx    edx,dx
  2127.     movzx    ecx,bx
  2128.     shl    ecx,4
  2129.     mov    ax,Res_DOSMEM
  2130.     call    RegisterResource
  2131. ;
  2132. @@9:    ret
  2133. cwAPI_GetMemDOS endp
  2134.  
  2135.  
  2136. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2137. ;
  2138. ;Re-size a block of DOS (conventional) memory previously allocated with
  2139. ;GetMemDOS.
  2140. ;
  2141. ;On Entry:
  2142. ;
  2143. ;BX    - New block size in paragraphs
  2144. ;DX    - Selector of block to modify
  2145. ;
  2146. ;On Exit:
  2147. ;
  2148. ;If function was successful:
  2149. ;Carry flag is clear.
  2150. ;
  2151. ;If function was not successful:
  2152. ;Carry flag is set.
  2153. ;
  2154. ;AX    - DOS error code:
  2155. ;BX    - Maximum block size possible in paragraphs
  2156. ;
  2157. cwAPI_ResMemDOS proc near
  2158.     mov    bx,[ebp+Int_BX]
  2159.     mov    dx,[ebp+Int_DX]
  2160.     mov    ax,0102h
  2161.     cwAPI_CallOld
  2162.     jnc    @@0
  2163.     mov    [ebp+Int_AX],ax
  2164.     mov    [ebp+Int_BX],bx
  2165.     jmp    @@9
  2166. ;
  2167. @@0:    mov    ax,Res_DOSMEM
  2168.     movzx    edx,dx
  2169.     call    ReleaseResource
  2170.     movzx    ecx,bx
  2171.     shl    ecx,4
  2172.     call    RegisterResource
  2173.     clc
  2174. ;
  2175. @@9:    cwAPI_C2C
  2176.     ret
  2177. cwAPI_ResMemDOS endp
  2178.  
  2179.  
  2180. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2181. ;
  2182. ;Release a block of DOS (conventional) memory previously allocated with
  2183. ;GetMemDOS.
  2184. ;
  2185. ;On Entry:
  2186. ;
  2187. ;DX    - Selector of block to free.
  2188. ;
  2189. ;On Exit:
  2190. ;
  2191. ;If function was successful:
  2192. ;Carry flag is clear.
  2193. ;
  2194. ;If function was not successful:
  2195. ;Carry flag is set.
  2196. ;
  2197. ;AX    - DOS error code.
  2198. ;
  2199. cwAPI_RelMemDOS proc near
  2200.  
  2201.     mov    ds,w[ebp+INT_DS]
  2202.     mov    es,w[ebp+INT_ES]
  2203.     mov    fs,w[ebp+INT_FS]
  2204.     mov    gs,w[ebp+INT_GS]
  2205.  
  2206.     mov    dx,[ebp+Int_DX]
  2207.     mov    ax,0101h
  2208.     cwAPI_CallOld
  2209.     jnc    @@0
  2210.     mov    [ebp+Int_AX],ax
  2211.     jmp    @@9
  2212. ;
  2213. @@0:    mov    ax,Res_DOSMEM
  2214.     movzx    edx,dx
  2215.     call    ReleaseResource
  2216.     clc
  2217. ;
  2218. @@9:    cwAPI_C2C
  2219.  
  2220.     mov    w[ebp+INT_DS],ds
  2221.     mov    w[ebp+INT_ES],es
  2222.     mov    w[ebp+INT_FS],fs
  2223.     mov    w[ebp+INT_GS],gs
  2224.  
  2225.     ret
  2226. cwAPI_RelMemDOS endp
  2227.  
  2228.  
  2229. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2230. ;
  2231. ;Run another CauseWay program directly.
  2232. ;
  2233. ;On Entry:
  2234. ;
  2235. ;DS:EDX    - File name.
  2236. ;ES:ESI    - Command line. First byte is length, then real data.
  2237. ;CX    - Environment selector, 0 to use existing copy.
  2238. ;
  2239. ;On Exit:
  2240. ;
  2241. ;Carry set on error and AX = error code else AL=ErrorLevel
  2242. ;
  2243. cwAPI_Exec    proc    near
  2244.     mov    ds,[ebp+Int_DS]
  2245.     mov    edx,[ebp+Int_EDX]
  2246.     mov    es,[ebp+Int_ES]
  2247.     mov    esi,[ebp+Int_ESI]
  2248.     mov    cx,[ebp+Int_CX]
  2249.     mov    ebx,0
  2250.     push    ebp
  2251.     call    _Exec
  2252.     pop    ebp
  2253.     jnc    @@0
  2254.     mov    [ebp+Int_AX],ax
  2255.     jmp    @@9
  2256. ;
  2257. @@0:    mov    [ebp+Int_AL],al
  2258. ;
  2259. @@9:    cwAPI_C2C
  2260. IFDEF DEBUG2
  2261.     push    eax
  2262.     push    ebx
  2263.     push    ecx
  2264.     push    edx
  2265.     push    ds
  2266.     push    cs
  2267.     pop    ds
  2268.     mov    edx,OFFSET debugagtext1
  2269. debugagloop2:
  2270.     cmp    BYTE PTR ds:[edx],0
  2271.     je    debugagb
  2272.     mov    ecx,1
  2273.     mov    bx,1
  2274.     mov    ah,40h
  2275.     int    21h
  2276.     inc    edx
  2277.     jmp    debugagloop2
  2278. debugagb:
  2279.     mov    edx,OFFSET debugagtext2
  2280.     push    cs
  2281.     pop    ds
  2282.     mov    ecx,2
  2283.     mov    bx,1
  2284.     mov    ah,40h
  2285.     int    21h
  2286.     pop    ds
  2287.     pop    edx
  2288.     pop    ecx
  2289.     pop    ebx
  2290.     pop    eax
  2291.     jmp    debugagout
  2292.  
  2293. debugagtext1    DB    'Done with cwAPI_Exec...',0
  2294. debugagtext2    DB    13,10
  2295.  
  2296. debugagout:
  2297. ENDIF
  2298.  
  2299.     ret
  2300. cwAPI_Exec    endp
  2301.  
  2302.  
  2303. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2304. ;
  2305. ;Validate and get expanded length of a CWC'd file.
  2306. ;
  2307. ;On Entry:
  2308. ;
  2309. ;BX    - File handle.
  2310. ;
  2311. ;On Exit:
  2312. ;
  2313. ;Carry set if not a CWC'd file else,
  2314. ;
  2315. ;ECX    - Expanded data size.
  2316. ;
  2317. cwAPI_cwcInfo    proc    near
  2318.     mov    bx,[ebp+Int_BX]
  2319.     call    GetCWCInfo
  2320.     cwAPI_C2C
  2321.     mov    [ebp+Int_ECX],ecx
  2322.     mov    [ebp+Int_EAX],eax
  2323.     ret
  2324. cwAPI_cwcInfo    endp
  2325.  
  2326.  
  2327. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2328. ;
  2329. ;Load/Expand a CWC'd data file into memory.
  2330. ;
  2331. ;On Entry:
  2332. ;
  2333. ;BX    - Source file handle.
  2334. ;ES:EDI    - Destination memory.
  2335. ;
  2336. ;On Exit:
  2337. ;
  2338. ;Carry set on error and EAX is error code else,
  2339. ;
  2340. ;ECX    - Expanded data length.
  2341. ;
  2342. cwAPI_cwcLoad proc near
  2343.     mov    bx,[ebp+Int_BX]
  2344.     mov    es,[ebp+Int_ES]
  2345.     mov    edi,[ebp+Int_EDI]
  2346.     call    DecodeCWC
  2347.     mov    [ebp+Int_EAX],eax
  2348.     jc    @@9
  2349.     mov    [ebp+Int_ECX],ecx
  2350. @@9:    cwAPI_C2C
  2351.     ret
  2352. cwAPI_cwcLoad endp
  2353.  
  2354.  
  2355. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2356. cwAPI_LinearCheck proc near
  2357.     mov    esi,[ebp+Int_ESI]
  2358.     assume ds:nothing
  2359.     mov    ds,cs:apiDSeg
  2360.     assume ds:_cwMain
  2361.     ;
  2362.     mov    es,RealSegment
  2363.     xor    eax,eax
  2364.     mov    ax,es
  2365.     lsl    eax,eax
  2366.     cmp    eax,esi
  2367.     jc    @@3
  2368.     mov    LinearAddressCheck,1
  2369.     mov    al,es:[esi]
  2370.     cmp    LinearAddressCheck,0
  2371.     mov    LinearAddressCheck,0
  2372.     jnz    @@2
  2373. @@3:    stc
  2374.     jmp    @@1
  2375. @@2:    clc
  2376. @@1:    assume ds:_apiCode
  2377.     ;
  2378.     cwAPI_C2C
  2379.     ret
  2380. cwAPI_LinearCheck endp
  2381.  
  2382.  
  2383. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2384. cwAPI_ExecDebug proc near
  2385.     mov    ds,[ebp+Int_DS]
  2386.     mov    edx,[ebp+Int_EDX]
  2387.     mov    es,[ebp+Int_ES]
  2388.     mov    esi,[ebp+Int_ESI]
  2389.     mov    cx,[ebp+Int_CX]
  2390.     mov    ebx,1
  2391.     push    ebp
  2392.     call    _Exec
  2393.     jnc    @@0
  2394.     pop    ebp
  2395.     mov    [ebp+Int_AX],ax
  2396.     jmp    @@9
  2397. ;
  2398. @@0:    shl    esi,16
  2399.     mov    si,di
  2400.     mov    edi,ebp
  2401.     pop    ebp
  2402.     mov    [ebp+Int_EAX],eax
  2403.     mov    [ebp+Int_BX],bx
  2404.     mov    [ebp+Int_CX],cx
  2405.     mov    [ebp+Int_EDX],edx
  2406.     mov    [ebp+Int_DI],si
  2407.     shr    esi,16
  2408.     mov    [ebp+Int_SI],si
  2409.     mov    [ebp+Int_EBP],edi
  2410.     clc
  2411. ;
  2412. @@9:    cwAPI_C2C
  2413. IFDEF DEBUG2
  2414.     push    eax
  2415.     push    ebx
  2416.     push    ecx
  2417.     push    edx
  2418.     push    ds
  2419.     push    cs
  2420.     pop    ds
  2421.     mov    edx,OFFSET debugaitext1
  2422. debugailoop2:
  2423.     cmp    BYTE PTR ds:[edx],0
  2424.     je    debugaib
  2425.     mov    ecx,1
  2426.     mov    bx,1
  2427.     mov    ah,40h
  2428.     int    21h
  2429.     inc    edx
  2430.     jmp    debugailoop2
  2431. debugaib:
  2432.     mov    edx,OFFSET debugaitext2
  2433.     push    cs
  2434.     pop    ds
  2435.     mov    ecx,2
  2436.     mov    bx,1
  2437.     mov    ah,40h
  2438.     int    21h
  2439.     pop    ds
  2440.     pop    edx
  2441.     pop    ecx
  2442.     pop    ebx
  2443.     pop    eax
  2444.     jmp    debugaiout
  2445.  
  2446. debugaitext1    DB    'Done with cwAPI_ExecDebug...',0
  2447. debugaitext2    DB    13,10
  2448.  
  2449. debugaiout:
  2450. ENDIF
  2451.  
  2452.     ret
  2453. cwAPI_ExecDebug endp
  2454.  
  2455.  
  2456. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2457. ;
  2458. ;Load another CauseWay program as an overlay, ie, do relocations etc but don't
  2459. ;actually execute it.
  2460. ;
  2461. ;On Entry:
  2462. ;
  2463. ;DS:EDX    - File name.
  2464. ;
  2465. ;On Exit:
  2466. ;
  2467. ;Carry set on error and AX = error code else,
  2468. ;
  2469. ;CX:EDX    - Entry CS:EIP
  2470. ;BX:EAX    - Entry SS:ESP
  2471. ;SI    - PSP.
  2472. ;
  2473. cwAPI_cwLoad    proc near
  2474.     mov    ds,[ebp+Int_DS]
  2475.     mov    edx,[ebp+Int_EDX]
  2476.     mov    ebx,2
  2477.     xor    ax,ax
  2478.     mov    es,ax
  2479.     mov    fs,ax
  2480.     push    ebp
  2481.     call    _Exec
  2482.     pop    ebp
  2483.     jnc    @@0
  2484.     mov    [ebp+Int_AX],ax
  2485.     jmp    @@9
  2486. ;
  2487. @@0:    mov    [ebp+Int_CX],cx
  2488.     mov    [ebp+Int_EDX],edx
  2489.     mov    [ebp+Int_BX],bx
  2490.     mov    [ebp+Int_EAX],eax
  2491.     mov    [ebp+Int_SI],si
  2492. ;
  2493. @@9:    cwAPI_C2C
  2494. IFDEF DEBUG2
  2495.     push    eax
  2496.     push    ebx
  2497.     push    ecx
  2498.     push    edx
  2499.     push    ds
  2500.     push    cs
  2501.     pop    ds
  2502.     mov    edx,OFFSET debugahtext1
  2503. debugahloop2:
  2504.     cmp    BYTE PTR ds:[edx],0
  2505.     je    debugahb
  2506.     mov    ecx,1
  2507.     mov    bx,1
  2508.     mov    ah,40h
  2509.     int    21h
  2510.     inc    edx
  2511.     jmp    debugahloop2
  2512. debugahb:
  2513.     mov    edx,OFFSET debugahtext2
  2514.     push    cs
  2515.     pop    ds
  2516.     mov    ecx,2
  2517.     mov    bx,1
  2518.     mov    ah,40h
  2519.     int    21h
  2520.     pop    ds
  2521.     pop    edx
  2522.     pop    ecx
  2523.     pop    ebx
  2524.     pop    eax
  2525.     jmp    debugahout
  2526.  
  2527. debugahtext1    DB    'Done with cwAPI_cwLoad...',0
  2528. debugahtext2    DB    13,10
  2529.  
  2530. debugahout:
  2531. ENDIF
  2532.  
  2533.     ret
  2534. cwAPI_cwLoad    endp
  2535.  
  2536.  
  2537. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2538. cwAPI_Cleanup    proc    near
  2539.     assume ds:nothing
  2540.     mov    ds,cs:apiDSeg
  2541.     assume ds:_cwMain
  2542.     call    LoseFileHandles
  2543.     clc
  2544.     assume ds:_apiCode
  2545.     cwAPI_C2C
  2546.     ret
  2547. cwAPI_Cleanup    endp
  2548.  
  2549.  
  2550. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2551. ;
  2552. ;Use DPMI services to allocate a single selector and initialise base & limit
  2553. ;as specified with type=data/read/write.
  2554. ;
  2555. ;On Entry:-
  2556. ;
  2557. ;EAX    - Linear base.
  2558. ;EBX    - limit.
  2559. ;
  2560. ;On Exit:-
  2561. ;
  2562. ;BX    - Segment selector.
  2563. ;
  2564. _SetSelector    proc near
  2565.     call    DPMICopyCheck
  2566.     ;
  2567.     pushm    eax,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2568.     assume ds:nothing
  2569.     mov    ds,cs:apiDDSeg
  2570.     assume ds:_apiCode
  2571.     ;
  2572.     cmp    ebx,100000h
  2573.     jc    @@ok
  2574.     cmp    ebx,-1
  2575.     jz    @@ok
  2576.     add    ebx,4095
  2577.     and    ebx,0FFFFFFFFh-4095
  2578.     dec    ebx
  2579.     ;
  2580. @@ok:    mov    d[@@SelectorBase],eax
  2581.     mov    d[@@SelectorSize],ebx
  2582.     ;
  2583.     ;Get a new selector from DPMI.
  2584.     ;
  2585.     mov    ax,0000h
  2586.     mov    cx,1
  2587.     cwAPI_CallOld
  2588.     jc    @@9
  2589.     mov    bx,ax
  2590. @@GotSel:    ;
  2591.     push    bx
  2592.     mov    ecx,d[@@SelectorSize]
  2593.     mov    esi,d[@@SelectorBase]
  2594.     mov    ax,ds        ;need RPL to base DPL on.
  2595.     lar    ax,ax
  2596.     and    ah,DescPL3
  2597.     or    ah,DescPresent+DescMemory+DescRWData
  2598.     ;
  2599.     mov    dx,apiSystemFlags    ;use default setting.
  2600.     shr    dx,14
  2601.     mov    al,dl
  2602.     xor    al,1
  2603.     or    al,b[apiSystemFlags+2]
  2604.     and    al,1
  2605.     shl    al,6
  2606.     ;
  2607.     cmp    ecx,0fffffh      ; see if we need to set g bit
  2608.     jc    @@3
  2609.     jz    @@3
  2610.     shr    ecx,12           ; div by 4096
  2611.     or    al,80h           ; set g bit
  2612. @@3:    mov    w[DescriptorBuffer],cx    ;store low word of limit.
  2613.     shr    ecx,16
  2614.     or    cl,al
  2615.     mov    b[DescriptorBuffer+6],cl    ;store high bits of limit and gran/code size bits.
  2616.     mov    w[DescriptorBuffer+2],si    ;store low word of linear base.
  2617.     shr    esi,16
  2618.     mov    bx,si
  2619.     mov    b[DescriptorBuffer+4],bl    ;store mid byte of linear base.
  2620.     mov    b[DescriptorBuffer+7],bh    ;store high byte of linear base.
  2621.     mov    b[DescriptorBuffer+5],ah    ;store pp/dpl/dt/type bits.
  2622.     pop    bx
  2623.     ;
  2624.     ;Write new descriptor table entry.
  2625.     ;
  2626.     push    bx
  2627.     mov    ax,000ch
  2628.     mov    edi,offset DescriptorBuffer
  2629.     push    ds
  2630.     pop    es
  2631.     cwAPI_CallOld
  2632.     pop    bx
  2633.     jc    @@9
  2634.     ;
  2635.     movzx    edx,bx
  2636.     mov    ax,Res_SEL
  2637.     call    RegisterResource
  2638.     ;
  2639. @@8:    clc
  2640.     jmp    @@10
  2641.     ;
  2642. @@9:    stc
  2643. @@10:    popm    eax,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2644.     ret
  2645. @@SelectorBase:    ;
  2646.     dd ?
  2647. @@SelectorSize:    ;
  2648.     dd ?
  2649. _SetSelector    endp
  2650.  
  2651.  
  2652. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2653. _RelSelector    proc    near
  2654. ;
  2655. ;Release a segment selector table entry.
  2656. ;
  2657. ;On Entry:-
  2658. ;
  2659. ;BX    - Segment selector.
  2660. ;
  2661.     call    DPMICopyCheck
  2662.     ;
  2663.     ;Check segment registers for value we're releasing and clear
  2664.     ;if found.
  2665.     ;
  2666.     pushm    ax,bx,cx
  2667.     and    bx,0ffffh-3
  2668.     xor    cx,cx
  2669.     mov    ax,ds
  2670.     and    ax,0ffffh-3
  2671.     cmp    ax,bx
  2672.     jnz    @@0
  2673.     mov    ds,cx
  2674. @@0:    mov    ax,es
  2675.     and    ax,0ffffh-3
  2676.     cmp    ax,bx
  2677.     jnz    @@1
  2678.     mov    es,cx
  2679. @@1:    mov    ax,fs
  2680.     and    ax,0ffffh-3
  2681.     cmp    ax,bx
  2682.     jnz    @@2
  2683.     mov    fs,cx
  2684. @@2:    mov    ax,gs
  2685.     and    ax,0ffffh-3
  2686.     cmp    ax,bx
  2687.     jnz    @@3
  2688.     mov    gs,cx
  2689. @@3:    popm    ax,bx,cx
  2690.     ;
  2691.     pushm    eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2692.     assume ds:nothing
  2693.     mov    ds,cs:apiDDSeg
  2694.     assume ds:_apiCode
  2695.     ;
  2696.     pushad
  2697.     movzx    edx,bx
  2698.     mov    ax,Res_SEL
  2699.     call    ReleaseResource
  2700.     popad
  2701.     ;
  2702.     push    bx
  2703.     mov    ax,0001h
  2704.     cwAPI_CallOld
  2705.     pop    bx
  2706.     jc    @@9
  2707.     ;
  2708.     clc
  2709.     jmp    @@10
  2710.     ;
  2711. @@9:    stc
  2712. @@10:    popm    eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2713. @@11:    ret
  2714. _RelSelector    endp
  2715.  
  2716.  
  2717. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2718. _SizeSelector    proc near
  2719. ;
  2720. ;Set a segment selector table entry and return a suitable segment value. Will
  2721. ;use whatever method is apropriate to the system environment.
  2722. ;
  2723. ;On Entry:-
  2724. ;
  2725. ;EAX    - Linear base address.
  2726. ;EBX    - size in bytes.
  2727. ;CX    - Selector.
  2728. ;
  2729. ;On Exit:-
  2730. ;
  2731.     call    DPMICopyCheck
  2732.     ;
  2733.     pushm    eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2734.     assume ds:nothing
  2735.     mov    ds,cs:apiDDSeg
  2736.     assume ds:_apiCode
  2737.     ;
  2738.     mov    d[@@SelectorBase],eax
  2739.     mov    d[@@SelectorSize],ebx
  2740.     mov    bx,cx
  2741.     ;
  2742.     push    bx
  2743.     push    ds
  2744.     pop    es
  2745.     mov    edi,offset DescriptorBuffer
  2746.     mov    ax,000bh
  2747.     cwAPI_CallOld
  2748.     pop    bx
  2749.     ;
  2750.     push    bx
  2751.     mov    al,0
  2752.     mov    ecx,d[@@SelectorSize]
  2753.     mov    esi,d[@@SelectorBase]
  2754.     cmp    ecx,0fffffh      ; see if we need to set g bit
  2755.     jc    @@2
  2756.     jz    @@2
  2757.     shr    ecx,12           ; div by 4096
  2758.     or    al,80h           ; set g bit
  2759. @@2:    mov    w[DescriptorBuffer+0],cx        ;store low word of limit.
  2760.     shr    ecx,16
  2761.     or    cl,al
  2762.     and    b[DescriptorBuffer+6],01110000b    ;lose limit & G bit.
  2763.     or    b[DescriptorBuffer+6],cl        ;store high bits of limit and G bit.
  2764.     mov    w[DescriptorBuffer+2],si        ;store low word of linear base.
  2765.     shr    esi,16
  2766.     mov    bx,si
  2767.     mov    b[DescriptorBuffer+4],bl        ;store mid byte of linear base.
  2768.     mov    b[DescriptorBuffer+7],bh        ;store high byte of linear base.
  2769.     pop    bx
  2770.     ;
  2771.     ;Write new descriptor table entry.
  2772.     ;
  2773.     push    bx
  2774.     mov    ax,000ch
  2775.     mov    edi,offset DescriptorBuffer
  2776.     push    ds
  2777.     pop    es
  2778.     cwAPI_CallOld
  2779.     pop    bx
  2780.     jc    @@9
  2781.     ;
  2782.     clc
  2783.     jmp    @@10
  2784.     ;
  2785. @@9:    stc
  2786. @@10:    popm    eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2787.     ret
  2788. @@SelectorBase:    ;
  2789.     dd ?
  2790. @@SelectorSize:    ;
  2791.     dd ?
  2792. _SizeSelector    endp
  2793.  
  2794.  
  2795. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2796. _DetSelector    proc    near
  2797. ;
  2798. ;Fetch selector base & limit values.
  2799. ;
  2800. ;On Entry:-
  2801. ;
  2802. ;BX    - Selector.
  2803. ;
  2804. ;On Exit:-
  2805. ;
  2806. ;EAX    - Linear base address.
  2807. ;EBX    - size in bytes.
  2808. ;
  2809.     call    DPMICopyCheck
  2810.     ;
  2811.     pushm    ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2812.     assume ds:nothing
  2813.     mov    ds,cs:apiDDSeg
  2814.     assume ds:_apiCode
  2815.     ;
  2816.     push    bx
  2817.     push    ds
  2818.     pop    es
  2819.     mov    edi,offset DescriptorBuffer
  2820.     mov    ax,000bh
  2821.     cwAPI_CallOld
  2822.     pop    bx
  2823.     jc    @@9
  2824.     ;
  2825.     xor    eax,eax
  2826.     mov    al,DescriptorBuffer+7    ;base 31-24
  2827.     shl    eax,8
  2828.     mov    al,DescriptorBuffer+4    ;base 23-16
  2829.     shl    eax,8
  2830.     mov    al,DescriptorBuffer+3    ;base 15-8
  2831.     shl    eax,8
  2832.     mov    al,DescriptorBuffer+2    ;base 7-0
  2833.     ;
  2834.     xor    ebx,ebx
  2835.     mov    bl,DescriptorBuffer+6    ;limit 19-16
  2836.     and    bl,0fh
  2837.     shl    ebx,8
  2838.     mov    bl,DescriptorBuffer+1    ;limit 15-8
  2839.     shl    ebx,8
  2840.     mov    bl,DescriptorBuffer+0    ;limit 7-0
  2841.     test    DescriptorBuffer+6,128    ;granularity
  2842.     jz    @@0
  2843.     shl    ebx,12
  2844.     or    ebx,0FFFh
  2845. @@0:    clc
  2846.     jmp    @@10
  2847. @@9:    stc
  2848. @@10:    popm    ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2849.     ret
  2850. _DetSelector    endp
  2851.  
  2852.  
  2853. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2854. _CodeSelector    proc near
  2855.     call    DPMICopyCheck
  2856.     ;
  2857.     pushad
  2858.     call    _DSizeSelector
  2859.     popad
  2860.     ;
  2861.     pushm    eax,ebx,ecx,edx,esi,edi,ebp
  2862.     pushm    ds,es,fs,gs
  2863.     assume ds:nothing
  2864.     mov    ds,cs:apiDDSeg
  2865.     assume ds:_apiCode
  2866.     ;
  2867.     push    cx
  2868.     push    bx
  2869.     mov    ax,000bh
  2870.     push    ds
  2871.     pop    es
  2872.     mov    edi,offset DescriptorBuffer
  2873.     cwAPI_CallOld
  2874.     pop    bx
  2875.     pop    cx
  2876.     ;
  2877.     mov    ax,cs
  2878.     and    al,11b
  2879.     shl    al,5
  2880.     or    al,DescERCode
  2881.     and    DescriptorBuffer+5,10010000b
  2882.     or    DescriptorBuffer+5,al    ;
  2883.     and    DescriptorBuffer+6,255-(1 shl 6) ;clear code size bit.
  2884.     and    cl,1
  2885.     shl    cl,6
  2886.     or    DescriptorBuffer+6,cl    ;code size bit.
  2887.     ;
  2888.     mov    ax,000ch
  2889.     push    ds
  2890.     pop    es
  2891.     mov    edi,offset DescriptorBuffer
  2892.     cwAPI_CallOld
  2893.     clc
  2894.     jmp    @@10
  2895.     ;
  2896. @@9:    stc
  2897. @@10:    popm    ds,es,fs,gs
  2898.     popm    eax,ebx,ecx,edx,esi,edi,ebp
  2899. @@11:    ret
  2900. _CodeSelector    endp
  2901.  
  2902.  
  2903. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2904. _DSizeSelector    proc near
  2905.     pushm    eax,ebx,ecx,edx,esi,edi,ebp
  2906.     pushm    ds,es,fs,gs
  2907.     assume ds:nothing
  2908.     mov    ds,cs:apiDDSeg
  2909.     assume ds:_apiCode
  2910.     ;
  2911.     push    cx
  2912.     push    bx
  2913.     mov    ax,000bh
  2914.     push    ds
  2915.     pop    es
  2916.     mov    edi,offset DescriptorBuffer
  2917.     cwAPI_CallOld
  2918.     pop    bx
  2919.     pop    cx
  2920.     ;
  2921.     and    DescriptorBuffer+6,255-(1 shl 6) ;clear code size bit.
  2922.     and    cl,1
  2923.     shl    cl,6
  2924.     or    DescriptorBuffer+6,cl    ;code size bit.
  2925.     ;
  2926.     mov    ax,000ch
  2927.     push    ds
  2928.     pop    es
  2929.     mov    edi,offset DescriptorBuffer
  2930.     cwAPI_CallOld
  2931.     ;
  2932.     popm    ds,es,fs,gs
  2933.     popm    eax,ebx,ecx,edx,esi,edi,ebp
  2934.     ret
  2935. _DSizeSelector    endp
  2936.  
  2937.  
  2938. mcbChunkLast    equ    0    ;pointer to previous chunk in chain.
  2939. mcbChunkNext    equ    4    ;pointer to next chunk in chain.
  2940. mcbBiggest    equ    8    ;biggest free block in this chunk.
  2941. mcbChunkSize    equ    10    ;size of this chunk.
  2942. mcbChunkSel    equ    12    ;chunk's selector.
  2943. mcbChunkLen    equ    16    ;length of chunk control entry.
  2944.  
  2945. mcbID    equ    0    ;ID for corruption checking.
  2946. mcbLast    equ    1    ;previous MCB pointer status.
  2947. mcbLastSize    equ    2    ;pointer to previous MCB.
  2948. mcbFreeUsed    equ    4    ;free or used status.
  2949. mcbNext    equ    5    ;next MCB pointer status.
  2950. mcbNextSize    equ    6    ;pointer to next MCB.
  2951. mcbLen    equ    8    ;length of an MCB entry.
  2952.  
  2953.  
  2954. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2955. ;
  2956. ;Get current MCB memory allocation block size.
  2957. ;
  2958. ;On Exit:
  2959. ;
  2960. ;ECX    - Current threshold.
  2961. ;
  2962. cwAPI_GetMCBSize proc near
  2963.     assume ds:nothing
  2964.     mov    ds,cs:apiDSeg
  2965.     assume ds:_cwMain
  2966.     mov    ds,PSPSegment
  2967.     mov    ecx,ds:d[EPSP_mcbMaxAlloc]
  2968.     add    ecx,mcbChunkLen+mcbLen
  2969.     assume ds:_apiCode
  2970.     mov    [ebp+Int_ECX],ecx
  2971.     ret
  2972. cwAPI_GetMCBSize endp
  2973.  
  2974.  
  2975. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2976. ;
  2977. ;Set new MCB memory allocation block size.
  2978. ;
  2979. ;On Entry:
  2980. ;
  2981. ;ECX    - New value to set.
  2982. ;
  2983. ;On Exit:
  2984. ;
  2985. ;Carry set on error else new value will be used.
  2986. ;
  2987. cwAPI_SetMCBSize proc near
  2988.     mov    ecx,[ebp+Int_ECX]
  2989.     add    ecx,4095
  2990.     and    ecx,not 4095
  2991.     cmp    ecx,65536+1
  2992.     jc    @@1
  2993.     stc
  2994.     jmp    @@9
  2995.     ;
  2996. @@1:    assume ds:nothing
  2997.     mov    ds,cs:apiDSeg
  2998.     assume ds:_cwMain
  2999.     mov    ds,PSPSegment
  3000.     cmp    ecx,mcbChunkLen+mcbLen
  3001.     jc    @@9
  3002.     sub    ecx,mcbChunkLen+mcbLen
  3003. @@0:    mov    ds:d[EPSP_mcbMaxAlloc],ecx
  3004.     assume ds:_apiCode
  3005.     clc
  3006. ;
  3007. @@9:    cwAPI_C2C
  3008.     ret
  3009. cwAPI_SetMCBSize endp
  3010.  
  3011.  
  3012. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  3013. ;
  3014. ;Replacement for CauseWay API GetMemLinear32 function.
  3015. ;
  3016. mcbGetMemLinear32 proc near
  3017.     push    ds
  3018.     push    es
  3019.     push    fs
  3020.     push    eax
  3021.     push    ebx
  3022.     push    ecx
  3023.     push    edx
  3024.     push    edi
  3025.     push    ebp
  3026.     assume ds:nothing
  3027.     mov    ds,cs:apiDSeg
  3028.     assume ds:_cwMain
  3029.     mov    fs,PSPSegment
  3030.     push    ds
  3031.     assume ds:nothing
  3032.     mov    ds,cs:apiDDSEg
  3033.     assume ds:_apiCode
  3034.     mov    mcbLastChunk,0
  3035.     assume ds:_cwMain
  3036.     pop    ds
  3037. ;
  3038. ;Round size up to next dword to keep things aligned.
  3039. ;
  3040.     cmp    ecx,-1
  3041.     jz    @@GetMax
  3042.     cmp    ecx,-2
  3043.     jz    @@GetMax
  3044.     add    ecx,3
  3045.     and    ecx,not 3
  3046. ;
  3047. ;Check MCB allocation system is enabled.
  3048. ;
  3049.     cmp    mcbAllocations,0
  3050.     jz    @@GetMax
  3051. ;
  3052. ;Check block size is small enough for these functions.
  3053. ;
  3054.     cmp    ecx,fs:d[EPSP_mcbMaxAlloc]
  3055.     jc    mGML32_0
  3056. ;
  3057. ;Size is above threshold so use normal API service for this request.
  3058. ;
  3059. @@GetMax:    mov    ebx,ecx
  3060.     call    _GetMemory
  3061.     jnc    mGML32_9
  3062.     cmp    ecx,-2
  3063.     jz    @@RetMax
  3064.     cmp    ecx,-1
  3065.     stc
  3066.     jnz    mGML32_9
  3067. @@RetMax:    pop    ebp
  3068.     pop    edi
  3069.     pop    edx
  3070.     pop    ecx
  3071.     mov    ecx,ebx
  3072.     push    ecx
  3073.     push    edx
  3074.     push    edi
  3075.     push    ebp
  3076.     stc
  3077.     jmp    mGML32_9
  3078. ;
  3079. ;Size is below threshold so use local allocation scheme.
  3080. ;
  3081. mGML32_0:
  3082. ;
  3083. ;Check if initial block has been claimed yet, allocate and initialise one if not.
  3084. ;
  3085.     cmp    fs:d[EPSP_mcbHead],0
  3086.     jnz    mGML32_10
  3087.     mov    ebx,fs:d[EPSP_mcbMaxAlloc]
  3088.     add    ebx,mcbChunkLen+mcbLen    ;chunk size.
  3089.     call    _GetMemory        ;allocate it.
  3090.     jc    mGML32_9        ;oops, appear to be out of memory.
  3091.     mov    fs:d[EPSP_mcbHead],esi
  3092. ;
  3093. ;Initialise this chunk.
  3094. ;
  3095.     mov    es,RealSegment
  3096.     sub    ebx,mcbChunkLen+mcbLen    ;chunk size.
  3097.     mov    es:w[esi+mcbChunkSize],bx
  3098.     mov    es:d[esi+mcbChunkNext],0    ;set forward link address.
  3099.     mov    es:d[esi+mcbChunkLast],0    ;store back link address.
  3100.     mov    eax,fs:d[EPSP_mcbMaxAlloc]
  3101.     mov    es:w[esi+mcbBiggest],ax    ;set biggest chunk size.
  3102.     sys    GetSel
  3103.     jc    mGML32_9
  3104.     mov    es:w[esi+mcbChunkSel],bx
  3105.     pushm    edx,ecx
  3106.     mov    edx,esi
  3107.     mov    ecx,fs:d[EPSP_mcbMaxAlloc]
  3108.     add    ecx,mcbChunkLen+mcbLen
  3109.     sys    SetSelDet32
  3110.     popm    edx,ecx
  3111.     add    esi,mcbChunkLen    ;skip chunk link info.
  3112.     mov    es:b[esi+mcbID],"C"    ;set ID byte.
  3113.     mov    es:b[esi+mcbLast],"D"    ;mark it as last block in back link.
  3114.     mov    es:w[esi+mcbLastSize],0    ;clear back link entry.
  3115.     mov    es:b[esi+mcbFreeUsed],"J"    ;mark it as a free block,
  3116.     mov    es:b[esi+mcbNext],"D"    ;last block in MCB chain,
  3117.     mov    eax,fs:d[EPSP_mcbMaxAlloc]
  3118.     mov    es:w[esi+mcbNextSize],ax
  3119. ;
  3120. ;Scan through all mcb's in all chunks looking for a big enough block.
  3121. ;
  3122. mGML32_10:    mov    es,RealSegment    ;0-4G selector.
  3123.     mov    esi,fs:d[EPSP_mcbHead]    ;start of local allocation trail.
  3124. mGML32_1:    mov    edi,esi        ;keep a copy for chunk chaining.
  3125.     mov    ebp,edi        ;keep a copy for mcbBiggest
  3126.     ;
  3127.     cmp    es:w[edi+mcbBiggest],cx    ;check if this chunk has a big
  3128.     jc    mGML32_6_0        ;enough free block.
  3129.     add    esi,mcbChunkLen
  3130. ;
  3131. ;Find first free and big enough block.
  3132. ;
  3133. mGML32_2:    cmp    es:b[esi+mcbFreeUsed],"J"    ;Free block?
  3134.     jz    mGML32_5
  3135. mGML32_6:    cmp    es:b[esi+mcbNext],"M"    ;Normal block (not end of chain)?
  3136.     jz    mGML32_4
  3137. ;
  3138. ;Reached the end of the chain for this chunk so we need to move onto the next
  3139. ;chunk in the chain.
  3140. ;
  3141. mGML32_6_0:    cmp    es:d[edi+mcbChunkNext],0    ;already have a link?
  3142.     jnz    mGML32_3
  3143. ;
  3144. ;Need another chunk to put in the chain so try and allocate it via normal
  3145. ;CauseWay API.
  3146. ;
  3147.     mov    ebx,fs:d[EPSP_mcbMaxAlloc]
  3148.     add    ebx,mcbChunkLen+mcbLen    ;chunk size.
  3149.     call    _GetMemory
  3150.     jc    mGML32_9        ;oops, appear to be out of memory.
  3151. ;
  3152. ;Update current chunk with address of new chunk and initialise new chunk.
  3153. ;
  3154.     sub    ebx,mcbChunkLen+mcbLen    ;chunk size.
  3155.     mov    es:w[esi+mcbChunkSize],bx
  3156.     mov    es:d[edi+mcbChunkNext],esi ;store forward link address.
  3157.     mov    es:d[esi+mcbChunkLast],edi ;store back link address.
  3158.     mov    es:d[esi+mcbChunkNext],0    ;clear new forward link address.
  3159.     mov    eax,fs:d[EPSP_mcbMaxAlloc]
  3160.     mov    es:w[esi+mcbBiggest],ax    ;set biggest chunk size.
  3161.     sys    GetSel
  3162.     jc    mGML32_9
  3163.     mov    es:w[esi+mcbChunkSel],bx
  3164.     pushm    edx,ecx
  3165.     mov    edx,esi
  3166.     mov    ecx,fs:d[EPSP_mcbMaxAlloc]
  3167.     add    ecx,mcbChunkLen+mcbLen
  3168.     sys    SetSelDet32
  3169.     popm    edx,ecx
  3170.     add    esi,mcbChunkLen    ;skip chunk link info.
  3171.     mov    es:b[esi+mcbID],"C"    ;set ID.
  3172.     mov    es:b[esi+mcbLast],"D"    ;mark it as last block in back link.
  3173.     mov    es:w[esi+mcbLastSize],0    ;clear back link entry.
  3174.     mov    es:b[esi+mcbFreeUsed],"J"    ;mark it as a free block,
  3175.     mov    es:b[esi+mcbNext],"D"    ;last block in MCB chain,
  3176.     mov    eax,fs:d[EPSP_mcbMaxAlloc]
  3177.     mov    es:w[esi+mcbNextSize],ax
  3178. ;
  3179. ;Chain to next chunk.
  3180. ;
  3181. mGML32_3:    mov    esi,es:d[edi+mcbChunkNext] ;pickup forward link address.
  3182.     jmp    mGML32_1        ;scan this MCB chain.
  3183. ;
  3184. ;Move to next MCB.
  3185. ;
  3186. mGML32_4:    movzx    eax,es:w[esi+mcbNextSize]    ;get block length.
  3187.     add    eax,mcbLen        ;include size of an MCB.
  3188.     add    esi,eax
  3189.     jmp    mGML32_2
  3190. ;
  3191. ;Check if this block is big enough.
  3192. ;
  3193. mGML32_5:    cmp    es:w[esi+mcbNextSize],cx    ;Big enough block?
  3194.     jc    mGML32_6
  3195. ;
  3196. ;Found a big enough free block so make use of it.
  3197. ;
  3198.     mov    es:b[esi+mcbFreeUsed],"W"    ;mark it as used.
  3199.     movzx    ebx,es:w[esi+mcbNextSize]
  3200.     sub    ebx,ecx        ;get spare size.
  3201.     cmp    ebx,mcbLen+1        ;smaller than an MCB?
  3202.     jc    mGML32_8
  3203. ;
  3204. ;Create a new MCB from whats left over.
  3205. ;
  3206.     sub    bx,mcbLen        ;MCB comes out of this size.
  3207.     mov    es:[esi+mcbNextSize],cx    ;set allocated block's size.
  3208.     mov    al,es:b[esi+mcbNext]    ;get next status.
  3209.     mov    es:b[esi+mcbNext],"M"    ;make sure its not end of chain now.
  3210.     mov    edi,esi
  3211.     add    edi,ecx
  3212.     add    edi,mcbLen        ;move to where new MCB will be.
  3213.     mov    es:b[edi+mcbID],"C"
  3214.     mov    es:b[edi+mcbLast],"M"    ;not last in back link chain.
  3215.     mov    es:[edi+mcbLastSize],cx    ;set back link size.
  3216.     mov    es:b[edi+mcbFreeUsed],"J"    ;mark as free,
  3217.     mov    es:[edi+mcbNext],al    ;set end of chain status.
  3218.     mov    es:[edi+mcbNextSize],bx    ;and new block size.
  3219. ;
  3220. ;Check if old block used to be end of chain.
  3221. ;
  3222.     cmp    al,"D"        ;end of chain?
  3223.     jz    mGML32_8
  3224. ;
  3225. ;Update back link size of next block.
  3226. ;
  3227.     movzx    eax,es:w[edi+mcbNextSize]
  3228.     add    eax,mcbLen        ;include MCB size.
  3229.     add    edi,eax
  3230.     mov    es:[edi+mcbLastSize],ax
  3231.     sub    es:w[edi+mcbLastSize],mcbLen
  3232. ;
  3233. ;Time to exit.
  3234. ;
  3235. mGML32_8:    add    esi,mcbLen        ;skip the MCB.
  3236.     push    ds
  3237.     assume ds:nothing
  3238.     mov    ds,cs:apiDDSeg
  3239.     assume ds:_apiCode
  3240.     mov    mcbLastChunk,ebp
  3241.     assume ds:_cwMain
  3242.     pop    ds
  3243.     call    mcbSetBiggest
  3244.     clc
  3245. ;
  3246. ;Restore stacked registers.
  3247. ;
  3248. mGML32_9:    pop    ebp
  3249.     pop    edi
  3250.     pop    edx
  3251.     pop    ecx
  3252.     pop    ebx
  3253.     pop    eax
  3254.     pop    fs
  3255.     pop    es
  3256.     pop    ds
  3257.     ret
  3258.     assume ds:_apiCode
  3259. mcbGetMemLinear32 endp
  3260.  
  3261.  
  3262. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  3263. ;
  3264. ;Replacement for CauseWay API ResMemLinear32 function.
  3265. ;
  3266. mcbResMemLinear32 proc near
  3267.     push    ds
  3268.     push    es
  3269.     push    fs
  3270.     push    eax
  3271.     push    ebx
  3272.     push    ecx
  3273.     push    edi
  3274.     push    ebp
  3275.     assume ds:nothing
  3276.     mov    ds,cs:apiDSeg
  3277.     assume ds:_cwMain
  3278.     mov    fs,PSPSegment
  3279.     push    ds
  3280.     assume ds:nothing
  3281.     mov    ds,cs:apiDDSeg
  3282.     assume ds:_apiCode
  3283.     mov    mcbLastChunk,0
  3284.     assume ds:_cwMain
  3285.     pop    ds
  3286.     ;
  3287.     mov    edi,esi
  3288.     add    ecx,3
  3289.     and    ecx,not 3
  3290. ;
  3291. ;See if MCB allocations are enabled.
  3292. ;
  3293.     cmp    mcbAllocations,0
  3294.     jz    mRsML32_30
  3295. ;
  3296. ;See if EDI is within the range of any of the chunks in the list.
  3297. ;
  3298.     mov    es,RealSegment
  3299.     mov    esi,fs:d[EPSP_mcbHead]
  3300.     or    esi,esi        ;check mcb's are active.
  3301.     jz    mRsML32_8
  3302.     ;
  3303. mRsML32_0:    cmp    edi,esi
  3304.     jc    mRsML32_1
  3305.     movzx    eax,es:w[esi+mcbChunkSize]
  3306.     add    eax,esi
  3307.     add    eax,mcbChunkLen+mcbLen    ;chunk size.
  3308.     cmp    edi,eax
  3309.     jc    mRsML32_2
  3310. mRsML32_1:    cmp    es:d[esi+mcbChunkNext],0    ;Next link field set?
  3311.     jz    mRsML32_8
  3312.     mov    esi,es:d[esi+mcbChunkNext]
  3313.     jmp    mRsML32_0
  3314. ;
  3315. ;In range of a chunk so deal with it here.
  3316. ;
  3317. mRsML32_2:    xchg    edi,esi
  3318.     mov    ebp,edi
  3319. ;
  3320. ;Check block size is small enough for these functions.
  3321. ;
  3322.     cmp    ecx,fs:d[EPSP_mcbMaxAlloc]
  3323.     jc    mRsML32_3
  3324. ;
  3325. ;Can't deal with a block this big so convert it to a normal API block.
  3326. ;
  3327.     mov    edi,esi
  3328.     mov    ebx,ecx
  3329.     call    _GetMemory        ;try and allocate a normal block.
  3330.     jc    mRsML32_9
  3331. ;
  3332. ;Copy existing block to new block.
  3333. ;
  3334.     push    ecx
  3335.     push    esi
  3336.     push    edi
  3337.     xchg    esi,edi
  3338.     sub    esi,mcbLen
  3339.     movzx    ecx,es:w[esi+mcbNextSize]
  3340.     add    esi,mcbLen
  3341.     push    ds
  3342.     mov    ds,RealSegment
  3343.     ;
  3344.     push    ecx
  3345.     shr    ecx,2
  3346.     rep    movsd
  3347.     pop    ecx
  3348.     and    ecx,3
  3349.     rep    movsb
  3350.     pop    ds
  3351.     pop    esi
  3352. ;
  3353. ;Release origional block and return address of new block.
  3354. ;
  3355.     call    mcbRelMemLinear32
  3356.     pop    esi
  3357.     pop    ecx
  3358.     jmp    mRsML32_9
  3359. ;
  3360. ;Get block's current size.
  3361. ;
  3362. mRsML32_3:    sub    esi,mcbLen        ;move back to MCB.
  3363.     cmp    cx,es:[esi+mcbNextSize]
  3364.     jz    mRsML32_7
  3365.     jnc    mRsML32_4        ;extending block.
  3366. ;
  3367. ;Block is shrinking so build another MCB at the end of this one.
  3368. ;
  3369.     movzx    ebx,es:w[esi+mcbNextSize]
  3370.     sub    ebx,ecx        ;get size differance.
  3371.     cmp    ebx,mcbLen+1        ;enough for a new MCB?
  3372.     jnc    @@0
  3373. ;
  3374. ;Before we abandon this block size change as too small we should check if the
  3375. ;next block is free and join the new space onto that if it is.
  3376. ;
  3377.     cmp    es:b[esi+mcbNext],"M"    ;end of the chain?
  3378.     jnz    mRsML32_7        ;yep, can't be another block.
  3379.     mov    edi,esi
  3380.     movzx    eax,es:w[esi+mcbNextSize]
  3381.     add    eax,mcbLen
  3382.     add    edi,eax        ;point to the next block.
  3383.     cmp    es:b[edi+mcbFreeUsed],"J"    ;Free block?
  3384.     jnz    mRsML32_7        ;no, so leave things alone.
  3385.     mov    es:[esi+mcbNextSize],cx    ;set new size.
  3386.     push    esi
  3387.     push    ecx
  3388.     mov    eax,ecx
  3389.     add    eax,mcbLen
  3390.     add    esi,eax
  3391.     xchg    esi,edi
  3392.     mov    ecx,mcbLen
  3393.     pushm    ds,es
  3394.     pop    ds
  3395.     rep    movsb
  3396.     pop    ds
  3397.     sub    edi,mcbLen
  3398.     add    es:[edi+mcbNextSize],bx    ;update block size.
  3399.     sub    es:[edi+mcbLastSize],bx    ;update last size.
  3400.     pop    ecx
  3401.     pop    esi
  3402.     cmp    es:b[edi+mcbNext],"M"    ;end of chain?
  3403.     jnz    mRsML32_7
  3404.     movzx    eax,es:w[edi+mcbNextSize]
  3405.     add    edi,eax
  3406.     add    edi,mcbLen
  3407.     mov    es:[edi+mcbLastSize],ax
  3408.     jmp    mRsML32_7        ;leave things as they are.
  3409.     ;
  3410. @@0:    sub    ebx,mcbLen        ;need space for a new MCB.
  3411.     mov    es:[esi+mcbNextSize],cx    ;set new size.
  3412.     mov    al,es:[esi+mcbNext]    ;get next status.
  3413.     mov    es:b[esi+mcbNext],"M"    ;force not end of chain.
  3414.     mov    edi,esi
  3415.     add    edi,ecx
  3416.     add    edi,mcbLen        ;move to new MCB.
  3417.     mov    es:b[edi+mcbID],"C"    ;set ID.
  3418.     mov    es:b[edi+mcbLast],"M"    ;not last in last chain.
  3419.     mov    es:[edi+mcbLastSize],cx    ;set last link size.
  3420.     mov    es:b[edi+mcbNext],al    ;set next status.
  3421.     mov    es:b[edi+mcbFreeUsed],"J"    ;mark it as free.
  3422.     mov    es:[edi+mcbNextSize],bx    ;set next link size.
  3423.     cmp    al,"D"        ;end of chain?
  3424.     jz    mRsML32_7
  3425. ;
  3426. ;Update last link size of next MCB.
  3427. ;
  3428.     movzx    eax,es:w[edi+mcbNextSize]
  3429.     mov    ebx,edi
  3430.     add    ebx,eax
  3431.     add    ebx,mcbLen        ;move to next block.
  3432.     mov    es:[ebx+mcbLastSize],ax
  3433. ;
  3434. ;Check if next block is free and join it to the newly created block if it is,
  3435. ;
  3436.     cmp    es:b[ebx+mcbFreeUsed],"J"    ;Free block?
  3437.     jnz    mRsML32_7
  3438. ;
  3439. ;Join next block to this one.
  3440. ;
  3441.     movzx    eax,es:w[ebx+mcbNextSize]    ;get block's size.
  3442.     add    eax,mcbLen        ;include size of an mcb.
  3443.     add    es:[edi+mcbNextSize],ax
  3444.     mov    al,es:[ebx+mcbNext]
  3445.     mov    es:[edi+mcbNext],al    ;copy next status.
  3446.     cmp    al,"D"        ;end of chain?
  3447.     jz    mRsML32_7
  3448. ;
  3449. ;Update next blocks last link size.
  3450. ;
  3451.     movzx    eax,es:w[edi+mcbNextSize]
  3452.     add    edi,eax
  3453.     add    edi,mcbLen        ;move to next block.
  3454.     mov    es:[edi+mcbLastSize],ax
  3455.     jmp    mRsML32_7
  3456. ;
  3457. ;Need to expand the block so check out the block above this one.
  3458. ;
  3459. mRsML32_4:    cmp    es:b[esi+mcbNext],"D"    ;end of the chain?
  3460.     jz    mRsML32_6
  3461.     mov    edi,esi
  3462.     movzx    eax,es:w[esi+mcbNextSize]
  3463.     add    eax,mcbLen        ;move to next block.
  3464.     add    edi,eax
  3465.     cmp    es:b[edi+mcbFreeUsed],"J"    ;This block free?
  3466.     jnz    mRsML32_6
  3467.     mov    ebx,ecx
  3468.     sub    bx,es:w[esi+mcbNextSize]    ;Get size needed.
  3469.     movzx    eax,es:w[edi+mcbNextSize]
  3470.     add    eax,mcbLen
  3471.     cmp    eax,ebx        ;Big enough block?
  3472.     jc    mRsML32_6
  3473. ;
  3474. ;Next block is big enough, is it big enough to leave a free block behind still?
  3475. ;
  3476.     sub    eax,ebx        ;Get size differance.
  3477.     cmp    eax,mcbLen+1
  3478.     jnc    mRsML32_5
  3479. ;
  3480. ;Swollow new block whole and update next blocks last link entry.
  3481. ;
  3482.     movzx    eax,es:w[edi+mcbNextSize]
  3483.     add    eax,mcbLen
  3484.     add    es:[esi+mcbNextSize],ax    ;update block size.
  3485.     mov    al,es:[edi+mcbNext]    ;get next status.
  3486.     mov    es:[esi+mcbNext],al
  3487.     cmp    al,"D"        ;end of the chain?
  3488.     jz    mRsML32_7
  3489.     movzx    eax,es:w[esi+mcbNextSize]
  3490.     mov    edi,esi
  3491.     add    edi,eax
  3492.     add    edi,mcbLen
  3493.     mov    es:[edi+mcbLastSize],ax
  3494.     jmp    mRsML32_7
  3495. ;
  3496. ;Create a new MCB in the right place.
  3497. ;
  3498. mRsML32_5:    mov    al,es:[edi+mcbNext]    ;Get next status.
  3499.     movzx    ebx,es:w[edi+mcbNextSize]    ;Get size of this block.
  3500.     add    bx,es:w[esi+mcbNextSize]
  3501.     mov    es:[esi+mcbNextSize],cx    ;set new size of this block.
  3502.     sub    ebx,ecx        ;get size remaining.
  3503.     mov    edi,esi
  3504.     add    edi,ecx
  3505.     add    edi,mcbLen
  3506.     mov    es:b[edi+mcbID],"C"    ;set ID.
  3507.     mov    es:b[edi+mcbLast],"M"    ;not last in last chain.
  3508.     mov    es:[edi+mcbLastSize],cx    ;last link size.
  3509.     mov    es:b[edi+mcbFreeUsed],"J"    ;mark it as free again.
  3510.     mov    es:[edi+mcbNext],al    ;set next status.
  3511.     mov    es:[edi+mcbNextSize],bx    ;set next link size.
  3512.     cmp    al,"D"        ;end of the chain?
  3513.     jz    mRsML32_7
  3514.     add    edi,ebx
  3515.     add    edi,mcbLen        ;move to next block.
  3516.     mov    es:[edi+mcbLastSize],bx
  3517.     jmp    mRsML32_7
  3518. ;
  3519. ;Have to try and allocate another block and copy the current blocks contents.
  3520. ;
  3521. mRsML32_6:    add    esi,mcbLen
  3522.     mov    edi,esi
  3523.     call    mcbGetMemLinear32
  3524.     jc    mRsML32_9
  3525.     push    ecx
  3526.     push    esi
  3527.     push    edi
  3528.     xchg    esi,edi
  3529.     sub    esi,mcbLen
  3530.     movzx    ecx,es:w[esi+mcbNextSize]
  3531.     add    esi,mcbLen
  3532.     push    ds
  3533.     mov    ds,RealSegment
  3534.     push    ecx
  3535.     shr    ecx,2
  3536.     rep    movsd
  3537.     pop    ecx
  3538.     and    ecx,3
  3539.     rep    movsb
  3540.     pop    ds
  3541.     pop    esi
  3542.     call    mcbRelMemLinear32    ;release origional block.
  3543.     pop    esi
  3544.     pop    ecx
  3545.     clc
  3546.     jmp    mRsML32_9
  3547. ;
  3548. ;Setup block address to return and exit.
  3549. ;
  3550. mRsML32_7:    add    esi,mcbLen
  3551.     push    ds
  3552.     assume ds:nothing
  3553.     mov    ds,cs:apiDDSeg
  3554.     assume ds:_apiCode
  3555.     mov    mcbLastChunk,ebp
  3556.     assume ds:_cwMain
  3557.     pop    ds
  3558.     call    mcbSetBiggest
  3559.     clc
  3560.     jmp    mRsML32_9
  3561. ;
  3562. ;Not in range of any local chunks so pass it to CauseWay API function.
  3563. ;
  3564. mRsML32_8:    cmp    ecx,fs:d[EPSP_mcbMaxAlloc]
  3565.     jc    mRsML32_11
  3566. mRsML32_30:    mov    esi,edi
  3567.     mov    ebx,ecx
  3568.     call    _ResMemory
  3569.     jmp    mRsML32_9
  3570. ;
  3571. ;Convert normal API block to local MCB block. This assumes that a none MCB block
  3572. ;comeing through here is bigger than mcbMaxAlloc and therefore is shrinking.
  3573. ;
  3574. mRsML32_11:    call    mcbGetMemLinear32
  3575.     jc    mRsML32_9
  3576. ;
  3577. ;Copy origional block contents.
  3578. ;
  3579.     push    esi
  3580.     push    edi
  3581.     xchg    esi,edi
  3582.     push    ds
  3583.     mov    ds,RealSegment
  3584.     push    ecx
  3585.     shr    ecx,2
  3586.     rep    movsd
  3587.     pop    ecx
  3588.     and    ecx,3
  3589.     rep    movsb
  3590.     pop    ds
  3591.     pop    esi
  3592.     call    _RelMemory        ;release origional block.
  3593.     pop    esi
  3594. ;
  3595. ;Return to caller.
  3596. ;
  3597. mRsML32_9:    pop    ebp
  3598.     pop    edi
  3599.     pop    ecx
  3600.     pop    ebx
  3601.     pop    eax
  3602.     pop    fs
  3603.     pop    es
  3604.     pop    ds
  3605.     ret
  3606.     assume ds:_apiCode
  3607. mcbResMemLinear32 endp
  3608.  
  3609.  
  3610. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  3611. ;
  3612. ;Replacement for CauseWay API RelMemLinear32 function.
  3613. ;
  3614. mcbRelMemLinear32 proc near
  3615.     push    ds
  3616.     push    es
  3617.     push    fs
  3618.     pushad
  3619.     assume ds:nothing
  3620.     mov    ds,cs:apiDSeg
  3621.     assume ds:_cwMain
  3622.     mov    fs,PSPSegment
  3623.     mov    edi,esi
  3624. ;
  3625. ;See if MCB blocks are enabled.
  3626. ;
  3627.     cmp    mcbAllocations,0
  3628.     jz    mRML32_8
  3629. ;
  3630. ;See if EDI is within the range of any of the chunks in the list.
  3631. ;
  3632.     mov    es,RealSegment
  3633.     mov    esi,fs:d[EPSP_mcbHead]
  3634.     or    esi,esi        ;check mcb's are active.
  3635.     jz    mRML32_8
  3636.     ;
  3637. mRML32_0:    cmp    edi,esi
  3638.     jc    mRML32_1
  3639.     movzx    eax,es:w[esi+mcbChunkSize]
  3640.     add    eax,esi
  3641.     add    eax,mcbChunkLen+mcbLen    ;chunk size.
  3642.     cmp    edi,eax
  3643.     jc    mRML32_2
  3644. mRML32_1:    cmp    es:d[esi+mcbChunkNext],0    ;Next link field set?
  3645.     jz    mRML32_8
  3646.     mov    esi,es:d[esi+mcbChunkNext]
  3647.     jmp    mRML32_0
  3648. ;
  3649. ;In range of a chunk so deal with it here.
  3650. ;
  3651. mRML32_2:    xchg    edi,esi
  3652.     mov    ebp,edi
  3653.     sub    esi,mcbLen
  3654.     mov    es:b[esi+mcbFreeUsed],"J"    ;mark it as free.
  3655. ;
  3656. ;Check if next block is free and join it to this one if it is.
  3657. ;
  3658. mRML32_11:    cmp    es:b[esi+mcbNext],"D"    ;last block in chain?
  3659.     jz    mRML32_3
  3660.     movzx    eax,es:w[esi+mcbNextSize]
  3661.     mov    ebx,esi
  3662.     add    eax,mcbLen
  3663.     add    ebx,eax
  3664.     cmp    es:b[ebx+mcbFreeUsed],"J"    ;free block?
  3665.     jnz    mRML32_3
  3666.     movzx    eax,es:w[ebx+mcbNextSize]
  3667.     add    eax,mcbLen
  3668.     add    es:[esi+mcbNextSize],ax    ;update block size.
  3669.     mov    al,es:[ebx+mcbNext]
  3670.     mov    es:[esi+mcbNext],al    ;copy next status.
  3671.     cmp    al,"D"        ;last block in chain?
  3672.     jz    mRML32_3
  3673. ;
  3674. ;Update next blocks last block pointer.
  3675. ;
  3676.     movzx    eax,es:w[esi+mcbNextSize]
  3677.     add    eax,mcbLen
  3678.     add    esi,eax
  3679.     mov    es:[esi+mcbLastSize],ax
  3680.     sub    es:w[esi+mcbLastSize],mcbLen
  3681.     sub    esi,eax
  3682. ;
  3683. ;Check if current block is end of next chain and end of last chain. If it
  3684. ;is we can release this chunk because it isn't being used anymore.
  3685. ;
  3686. mRML32_3:    cmp    es:b[esi+mcbNext],"M"
  3687.     jz    mRML32_4
  3688.     cmp    es:b[esi+mcbLast],"M"
  3689.     jz    mRML32_4
  3690. ;
  3691. ;Un-link and release this chunk, its not being used.
  3692. ;
  3693.     mov    esi,edi        ;Get chunk address.
  3694.     mov    edi,es:[esi+mcbChunkLast]
  3695.     mov    eax,es:[esi+mcbChunkNext]
  3696.     or    edi,edi        ;First chunk?
  3697.     jnz    mRML32_5
  3698.     mov    fs:d[EPSP_mcbHead],eax    ;Set new head chunk, 0 is valid.
  3699.     jmp    mRML32_6
  3700. mRML32_5:    mov    es:[edi+mcbChunkNext],eax    ;link to next chunk.
  3701. mRML32_6:    xchg    eax,edi
  3702.     or    edi,edi        ;is there a next chunk?
  3703.     jz    mRML32_7
  3704.     mov    es:[edi+mcbChunkLast],eax    ;link to last chunk.
  3705. mRML32_7:    mov    bx,es:[esi+mcbChunkSel]
  3706.     sys    RelSel        ;release this selector.
  3707.     call    _RelMemory        ;release this memory for real.
  3708.     jmp    mRML32_9        ;exit, we're all done.
  3709. ;
  3710. ;Check if previous block is free and join this one to it if it is.
  3711. ;
  3712. mRML32_4:    cmp    es:b[esi+mcbLast],"M"    ;last block in last chain?
  3713.     jnz    mRML32_10
  3714. ;
  3715. ;Move back to previous block, see if its free and let the next block join code
  3716. ;deal with it if it is.
  3717. ;
  3718.     movzx    eax,es:w[esi+mcbLastSize]
  3719.     add    eax,mcbLen
  3720.     sub    esi,eax
  3721.     cmp    es:b[esi+mcbFreeUsed],"J"
  3722.     jz    mRML32_11
  3723. ;
  3724. ;Finished but we couldn't release this chunk.
  3725. ;
  3726. mRML32_10:    call    mcbSetBiggest
  3727.     clc
  3728.     jmp    mRML32_9
  3729. ;
  3730. ;Not in range of any local chunks so pass it to CauseWay API function.
  3731. ;
  3732. mRML32_8:    mov    esi,edi
  3733.     call    _RelMemory
  3734.     ;
  3735. mRML32_9:    popad
  3736.     pop    fs
  3737.     pop    es
  3738.     pop    ds
  3739.     ret
  3740.     assume ds:_apiCode
  3741. mcbRelMemLinear32 endp
  3742.  
  3743.  
  3744. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  3745. ;
  3746. ;Set mcbBiggest entry in chunk header.
  3747. ;
  3748. ;On Entry:
  3749. ;
  3750. ;ES:EBP    - Chunk header.
  3751. ;
  3752. mcbSetBiggest    proc    near
  3753.     pushm    eax,ecx,esi
  3754.     mov    esi,ebp
  3755.     add    esi,mcbChunkLen
  3756.     xor    ecx,ecx
  3757. @@0:    cmp    es:b[esi+mcbFreeUsed],"J"
  3758.     jnz    @@1
  3759.     cmp    cx,es:w[esi+mcbNextSize]
  3760.     jnc    @@1
  3761.     mov    cx,es:w[esi+mcbNextSize]
  3762. @@1:    cmp    es:b[esi+mcbNext],"M"    ;last block in last chain?
  3763.     jnz    @@2
  3764.     movzx    eax,es:w[esi+mcbNextSize]
  3765.     add    esi,eax
  3766.     add    esi,mcbLen
  3767.     jmp    @@0
  3768. @@2:    mov    es:w[ebp+mcbBiggest],cx
  3769.     popm    eax,ecx,esi
  3770.     ret
  3771. mcbSetBiggest    endp
  3772.  
  3773.  
  3774. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  3775. _GetMemory    proc    near
  3776. ;
  3777. ;Attempt to allocate a block of memory.
  3778. ;
  3779. ;On Entry:-
  3780. ;
  3781. ;EBX    - Size of block required. (-1 to get size of free memory).
  3782. ;
  3783. ;On Exit:-
  3784. ;
  3785. ;Carry set on error, else:-
  3786. ;
  3787. ;ESI    - linear address of memory.
  3788. ;
  3789. ;ALL registers may be corrupted.
  3790. ;
  3791.     call    DPMICopyCheck
  3792.     ;
  3793.     pushm    ecx,edx,edi,ebp,ds,es
  3794.     assume ds:nothing
  3795.     mov    ds,cs:apiDDSeg
  3796.     assume ds:_apiCode
  3797.     pushm    d[@@BlockSize],d[@@BlockBase],d[@@BlockHandle]
  3798.     ;
  3799.     cmp    ebx,-2
  3800.     jz    @@Special
  3801.     cmp    ebx,-1        ;special value to get memory free?
  3802.     jnz    @@NotSpecial
  3803. @@Special:    call    _GetMemoryMax    ;call free memory code.
  3804.     stc
  3805.     popm    d[@@BlockSize],d[@@BlockBase],d[@@BlockHandle]
  3806.     popm    ecx,edx,edi,ebp,ds,es
  3807.     ret
  3808.     ;
  3809. @@NotSpecial:    mov    d[@@BlockSize],ebx    ;store real block size.
  3810.     ;
  3811.     mov    cx,bx
  3812.     shr    ebx,16
  3813.     mov    ax,0501h        ;Allocate memory block.
  3814.     cwAPI_CallOld
  3815.     jc    @@9
  3816.     shl    ebx,16
  3817.     mov    bx,cx
  3818.     mov    d[@@BlockBase],ebx    ;store linear base address.
  3819.     shl    esi,16
  3820.     mov    si,di
  3821.     mov    d[@@BlockHandle],esi    ;store access handle.
  3822.     ;
  3823.     mov    ax,Res_MEM
  3824.     mov    edx,ebx
  3825.     mov    ecx,esi
  3826.     mov    ebx,d[@@BlockSize]
  3827.     call    RegisterResource
  3828.     ;
  3829.     mov    esi,edx
  3830.     clc
  3831.     jmp    @@10
  3832.     ;
  3833. @@9:    stc
  3834. @@10:    popm    d[@@BlockSize],d[@@BlockBase],d[@@BlockHandle]
  3835.     popm    ecx,edx,edi,ebp,ds,es
  3836.     ret
  3837. @@BlockBase:    ;
  3838.     dd ?
  3839. @@BlockHandle:    ;
  3840.     dd ?
  3841. @@BlockSize:    ;
  3842.     dd ?
  3843. _GetMemory    endp
  3844.  
  3845.  
  3846. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  3847. _GetMemoryMax proc near
  3848. ;
  3849. ;Work out biggest memory block remaining.
  3850. ;
  3851.     call    DPMICopyCheck
  3852.     ;
  3853.     push    ds
  3854.     assume ds:nothing
  3855.     mov    ds,cs:apiDDSeg
  3856.     assume ds:_apiCode
  3857.     ;
  3858.  
  3859. COMMENT ! MED 02/15/96
  3860.     cmp    ebx,-1        ;normal max reporting?
  3861.     jz    @@normal
  3862.  
  3863.     push    ds
  3864.     mov    ds,apiDSeg
  3865.     assume ds:_cwMain
  3866.     cmp    ProtectedType,2
  3867.     assume ds:_apiCode
  3868.     pop    ds
  3869.     jz    @@normal
  3870.  
  3871.     ;
  3872.     ;Get free disk space remaining.
  3873.     ;
  3874.     push    ds
  3875.     mov    ax,KernalDS
  3876.     mov    ds,ax
  3877.     assume ds:_cwRaw
  3878.  
  3879.     pushm    eax,ebx,ecx,esi,edi
  3880.     xor    edx,edx
  3881.     cmp    VMMHandle,0
  3882.     jz    @@500_1
  3883.     mov    dl,VMMName        ;get drive letter for this media.
  3884.     sub    dl,'A'        ;make it real.
  3885.     inc    dl        ;adjust for current type select.
  3886.     mov    ah,36h        ;get free space.
  3887.     int    21h        ;/
  3888.     xor    edx,edx
  3889.     cmp    ax,-1        ;invalid drive?
  3890.     jz    @@500_1
  3891.     mul    cx        ;Get bytes per cluster.
  3892.     mul    bx        ;Get bytes available.
  3893.     shl    edx,16
  3894.     mov    dx,ax
  3895.     add    edx,SwapFileLength    ;include current size.
  3896.     shr    edx,12
  3897.     ;
  3898.     ;Work out how much of the VMM space is extra.
  3899.     ;
  3900.     mov    eax,LinearLimit
  3901.     sub    eax,LinearBase
  3902.     shr    eax,12
  3903.     sub    edx,eax
  3904.     jmp    @@500_2
  3905.     ;
  3906. @@500_1:
  3907.     mov    edx,TotalPhysical
  3908. @@500_2:    add    edx,FreePages
  3909.     ;
  3910.     popm    eax,ebx,ecx,esi,edi
  3911.  
  3912.     assume ds:_apiCode
  3913.     pop    ds
  3914.     mov    ebx,edx
  3915.     shl    ebx,12
  3916.     jmp    @@exit
  3917. END COMMENT !
  3918.  
  3919. @@normal:    push    es
  3920.     mov    edi,offset @@dpmembuff
  3921.     push    ds
  3922.     pop    es
  3923.     push    ebx
  3924.     mov    ax,0500h
  3925.     cwAPI_CallOld
  3926.     pop    ebx
  3927.     pop    es
  3928.  
  3929.     cmp    ebx,-2
  3930.     jnz    @@normal2
  3931.  
  3932.     mov    ebx,d[@@dpmembuff+1Ch]
  3933.     shl    ebx,12
  3934.     jmp    @@exit
  3935.  
  3936. @@normal2:    mov    ebx,d[@@dpmembuff]
  3937.     ;
  3938. @@exit:    pop    ds
  3939.     ret
  3940. @@dpmembuff:    ;
  3941.     db 30h dup (0)
  3942. _GetMemoryMax    endp
  3943.  
  3944.  
  3945. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  3946. _ResMemory    proc    near
  3947. ;
  3948. ;Re-size a block of memory.
  3949. ;
  3950. ;On Entry:-
  3951. ;
  3952. ;ESI    - Linear address of memory.
  3953. ;EBX    - New size.
  3954. ;
  3955. ;On Exit:-
  3956. ;
  3957. ;ESI    - New linear address of memory.
  3958. ;
  3959.     call    DPMICopyCheck
  3960.     ;
  3961.     pushm    eax,ebx,ecx,edx,edi,ebp,ds,es
  3962.     assume ds:nothing
  3963.     mov    ds,cs:apiDDSeg
  3964.     assume ds:_apiCode
  3965.     push    d[@@OldESI]
  3966.     mov    d[@@OldESI],esi
  3967.     push    d[@@OldEBX]
  3968.     mov    d[@@OldEBX],ebx
  3969.     pushm    LastResource,LastResource+4
  3970.     ;
  3971.     mov    edx,esi
  3972.     mov    ax,Res_MEM
  3973.     call    FindResource
  3974.     jc    @@9
  3975.     ;
  3976.     mov    ebx,d[@@OldEBX]
  3977.     mov    esi,ecx
  3978.     mov    di,si
  3979.     shr    esi,16
  3980.     mov    cx,bx
  3981.     shr    ebx,16        ;set block size.
  3982.     mov    ax,0503h        ;release the block.
  3983.     cwAPI_CallOld
  3984.     jc    @@9
  3985.     shl    ebx,16
  3986.     mov    bx,cx
  3987.     shl    esi,16
  3988.     mov    si,di
  3989.     xchg    esi,ebx
  3990.     ;
  3991.     mov    es,apiDSeg
  3992.     assume es:_cwMain
  3993.     mov    es,es:RealSegment
  3994.     assume es:nothing
  3995.     mov    edx,LastResource
  3996.     mov    es:[edx],esi        ;update base.
  3997.     add    edx,4
  3998.     mov    es:[edx],ebx        ;update handle.
  3999.     add    edx,4
  4000.     mov    ebx,d[@@OldEBX]
  4001.     mov    es:[edx],ebx        ;update size.
  4002.     ;
  4003.     clc
  4004.     jmp    @@10
  4005.     ;
  4006. @@9:    stc
  4007. @@10:    popm    LastResource,LastResource+4
  4008.     pop    d[@@OldEBX]
  4009.     pop    d[@@OldESI]
  4010.     popm    eax,ebx,ecx,edx,edi,ebp,ds,es
  4011.     ret
  4012. @@OldEBX:    ;
  4013.     dd 0
  4014. @@OldESI:    ;
  4015.     dd 0
  4016. _ResMemory    endp
  4017.  
  4018.  
  4019. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  4020. _RelMemory    proc    near
  4021. ;
  4022. ;Release a previously allocated block of memory.
  4023. ;
  4024. ;On Entry:-
  4025. ;
  4026. ;ESI    - Near DS pointer.
  4027. ;
  4028.     call    DPMICopyCheck
  4029.     ;
  4030.     pushm    ds,es
  4031.     pushad
  4032.     assume ds:nothing
  4033.     mov    ds,cs:apiDDSeg
  4034.     assume ds:_apiCode
  4035.     pushm    LastResource,LastResource+4
  4036.     ;
  4037.     mov    edx,esi
  4038.     mov    ax,Res_MEM
  4039.     call    FindResource
  4040.     jc    @@9
  4041.     ;
  4042.     mov    esi,ecx
  4043.     mov    di,si
  4044.     shr    esi,16
  4045.     mov    ax,0502h        ;release the block.
  4046.     cwAPI_CallOld
  4047.     jc    @@9
  4048.     ;
  4049.     mov    di,bx
  4050.     shr    ebx,16
  4051.     mov    si,bx
  4052.     mov    cx,dx
  4053.     shr    edx,16
  4054.     mov    bx,dx
  4055.     mov    ax,0703h        ;discard the block.
  4056.     cwAPI_CallOld
  4057.     ;
  4058.     mov    es,apiDSeg
  4059.     assume es:_cwMain
  4060.     mov    es,es:RealSegment
  4061.     assume es:nothing
  4062.     mov    esi,LastResource
  4063.     mov    edi,LastResource+4
  4064.     xor    eax,eax
  4065.     mov    es:[edi],ax
  4066.     mov    es:[edi+2],al
  4067.     mov    es:[esi],eax
  4068.     mov    es:[esi+4],eax
  4069.     mov    es:[esi+8],eax
  4070.     ;
  4071.     clc
  4072.     ;
  4073. @@9:    popm    LastResource,LastResource+4
  4074.     popad
  4075.     popm    ds,es
  4076.     ret
  4077. _RelMemory    endp
  4078.  
  4079.  
  4080. ;-------------------------------------------------------------------------
  4081. ;
  4082. ;Register a new resource.
  4083. ;
  4084. ;On Entry:
  4085. ;
  4086. ;AL    - Resource type to register.
  4087. ;EDX    - Key value.
  4088. ;ECX    - optional second value.
  4089. ;EBX    - optional third value.
  4090. ;
  4091. RegisterResource proc near
  4092.     pushm    ds,es,fs
  4093.     pushad
  4094.     assume ds:nothing
  4095.     mov    ds,cs:apiDSeg
  4096.     assume ds:_cwMain
  4097.     mov    es,RealSegment
  4098.     mov    fs,PSPSegment
  4099.     ;
  4100.     cmp    ResourceTracking,0
  4101.     jz    @@9
  4102.     cmp    fs:d[EPSP_Resource],0    ;allocated memory for list yet?
  4103.     jnz    @@0
  4104.     ;
  4105.     ;Allocate initial resource list space.
  4106.     ;
  4107.     pushad
  4108.     call    @@GetAndInit
  4109.     jc    @@1
  4110.     mov    fs:d[EPSP_Resource],esi
  4111. @@1:    popad
  4112.     cmp    fs:d[EPSP_Resource],0
  4113.     jz    @@90
  4114.     ;
  4115. @@0:    ;Search list for free slot.
  4116.     ;
  4117.     cld
  4118.     mov    ebp,ecx        ;Copy value 2.
  4119.     mov    ah,al        ;Copy type.
  4120.     mov    esi,fs:d[EPSP_Resource]
  4121. @@FreeLoop:    mov    edi,esi
  4122.     add    edi,ResHead        ;point to types.
  4123.     mov    ecx,ResCount        ;get number of entries.
  4124. @@2:    or    ecx,ecx
  4125.     jz    @@2_0
  4126.     js    @@2_0
  4127.     xor    al,al
  4128.     repne    scasb        ;Find NULL entry.
  4129.     jz    @@3
  4130. @@2_0:    cmp    es:d[esi+8],0    ;link field setup?
  4131.     jz    @@Extend
  4132.     mov    esi,es:[esi+8]    ;link to next block.
  4133.     jmp    @@FreeLoop
  4134.     ;
  4135. @@Extend:    ;Extend the list.
  4136.     ;
  4137.     push    esi
  4138.     call    @@GetAndInit
  4139.     pop    ecx
  4140.     jc    @@90
  4141.     mov    es:[esi+4],ecx    ;store back link address.
  4142.     mov    es:[ecx+8],esi    ;store forward link address.
  4143.     jmp    @@FreeLoop
  4144. ;
  4145. ;Check if enough entries are free.
  4146. ;
  4147. @@3:    cmp    ah,Res_SEL
  4148.     jz    @@sel
  4149.     cmp    ah,Res_MEM
  4150.     jz    @@mem
  4151.     cmp    ah,Res_LOCK
  4152.     jz    @@lock
  4153.     cmp    ah,Res_DOSMEM
  4154.     jz    @@dosmem
  4155.     cmp    ah,Res_CALLBACK
  4156.     jz    @@callback
  4157.     cmp    ah,Res_PSP
  4158.     jz    @@psp
  4159.     jmp    @@sel
  4160. ;
  4161. ;Check for 2 free entries for DOS memory.
  4162. ;
  4163. @@dosmem:    cmp    es:b[edi],0
  4164.     jnz    @@2
  4165.     dec    edi
  4166.     mov    ecx,edi
  4167.     sub    ecx,ResHead        ;Get offset from list start.
  4168.     sub    ecx,esi
  4169.     shl    ecx,2
  4170.     add    ecx,ResNum+ResHead
  4171.     add    ecx,esi
  4172.     mov    es:b[edi],ah        ;Store type.
  4173.     mov    es:d[ecx],edx
  4174.     inc    edi
  4175.     add    ecx,4
  4176.     mov    ah,Res_CHAIN
  4177.     mov    es:b[edi],ah
  4178.     mov    es:d[ecx],ebp
  4179.     jmp    @@9
  4180. ;
  4181. ;Check for 3 free entries for callback.
  4182. ;
  4183. @@callback:    cmp    es:w[edi],0        ;2 more entries?
  4184.     jnz    @@2
  4185.     dec    edi
  4186.     mov    ecx,edi
  4187.     sub    ecx,ResHead        ;Get offset from list start.
  4188.     sub    ecx,esi
  4189.     shl    ecx,2
  4190.     add    ecx,ResNum+ResHead
  4191.     add    ecx,esi
  4192.     mov    es:b[edi],ah        ;Store type.
  4193.     mov    es:d[ecx],edx
  4194.     inc    edi
  4195.     add    ecx,4
  4196.     mov    ah,Res_CHAIN
  4197.     mov    es:b[edi],ah
  4198.     mov    es:d[ecx],ebp
  4199.     inc    edi
  4200.     add    ecx,4
  4201.     mov    es:b[edi],ah
  4202.     mov    es:d[ecx],ebx
  4203.     jmp    @@9
  4204. ;
  4205. ;Check for 3 free entries for memory.
  4206. ;
  4207. @@mem:    cmp    es:w[edi],0        ;2 more entries?
  4208.     jnz    @@2
  4209.     dec    edi
  4210.     mov    ecx,edi
  4211.     sub    ecx,ResHead        ;Get offset from list start.
  4212.     sub    ecx,esi
  4213.     shl    ecx,2
  4214.     add    ecx,ResNum+ResHead
  4215.     add    ecx,esi
  4216.     mov    es:b[edi],ah        ;Store type.
  4217.     mov    es:d[ecx],edx
  4218.     inc    edi
  4219.     add    ecx,4
  4220.     mov    ah,Res_CHAIN
  4221.     mov    es:b[edi],ah
  4222.     mov    es:d[ecx],ebp
  4223.     inc    edi
  4224.     add    ecx,4
  4225.     mov    es:b[edi],ah
  4226.     mov    es:d[ecx],ebx
  4227.     jmp    @@9
  4228. ;
  4229. ;Check for 2 free entries for lock's.
  4230. ;
  4231. @@lock:    cmp    es:b[edi],0
  4232.     jnz    @@2
  4233.     dec    edi
  4234.     mov    ecx,edi
  4235.     sub    ecx,ResHead        ;Get offset from list start.
  4236.     sub    ecx,esi
  4237.     shl    ecx,2
  4238.     add    ecx,ResNum+ResHead
  4239.     add    ecx,esi
  4240.     mov    es:b[edi],ah        ;Store type.
  4241.     mov    es:d[ecx],edx
  4242.     inc    edi
  4243.     add    ecx,4
  4244.     mov    ah,Res_CHAIN
  4245.     mov    es:b[edi],ah
  4246.     mov    es:d[ecx],ebp
  4247.     jmp    @@9
  4248. ;
  4249. ;Only one free entry needed for selectors.
  4250. ;
  4251. @@psp:    ;
  4252. @@sel:    dec    edi
  4253.     mov    ecx,edi
  4254.     sub    ecx,ResHead        ;Get offset from list start.
  4255.     sub    ecx,esi
  4256.     shl    ecx,2
  4257.     add    ecx,ResNum+ResHead
  4258.     add    ecx,esi
  4259.     mov    es:b[edi],ah        ;Store type.
  4260.     mov    es:d[ecx],edx
  4261.     jmp    @@9
  4262.     ;
  4263. @@90:    stc
  4264.     jmp    @@100
  4265.     ;
  4266. @@9:    clc
  4267. @@100:    popad
  4268.     popm    ds,es,fs
  4269.     ret
  4270.     ;
  4271. @@GetAndInit:    pushm    eax,ebx,ecx,edx,ebp
  4272.     mov    cx,4096
  4273.     xor    bx,bx
  4274.     mov    ax,0501h        ;Allocate memory block.
  4275.     cwAPI_CallOld
  4276.     jc    @@GAIerror
  4277.     shl    esi,16
  4278.     mov    si,di
  4279.     shl    ebx,16
  4280.     mov    bx,cx
  4281.     xchg    esi,ebx
  4282.     mov    edi,esi
  4283.     xor    eax,eax
  4284.     mov    ecx,ResSize/4
  4285.     cld
  4286.     rep    stosd        ;init memory.
  4287.     mov    es:d[esi+12],ebx    ;store the handle.
  4288.     clc
  4289. @@GAIerror:    popm    eax,ebx,ecx,edx,ebp
  4290.     ret
  4291.     assume ds:_apiCode
  4292. RegisterResource endp
  4293.  
  4294.  
  4295. ;-------------------------------------------------------------------------
  4296. ;
  4297. ;Release a resource entry. If it's a PSP then release its resources.
  4298. ;
  4299. ;On Entry:
  4300. ;
  4301. ;AL    - Resource type.
  4302. ;EDX    - Key value.
  4303. ;
  4304. ReleaseResource proc near
  4305.     pushm    ds,es,fs
  4306.     pushad
  4307.     assume ds:nothing
  4308.     mov    ds,cs:apiDSeg
  4309.     assume ds:_cwMain
  4310.     mov    fs,PSPSegment
  4311.     cmp    ResourceTracking,0
  4312.     jz    @@9
  4313.     cmp    fs:d[EPSP_Resource],0
  4314.     jz    @@9
  4315.     xchg    eax,edx
  4316.     mov    es,RealSegment
  4317.     cld
  4318.     mov    esi,fs:d[EPSP_Resource]
  4319. @@LookLoop:    mov    edi,esi
  4320.     add    edi,ResHead+ResNum
  4321.     mov    ecx,ResNum        ;get number of entries.
  4322. @@2:    repne    scasd
  4323.     jz    @@0
  4324.     mov    esi,es:[esi+8]    ;link to next list.
  4325.     or    esi,esi
  4326.     jz    @@9
  4327.     jmp    @@LookLoop
  4328.     ;
  4329. @@0:    mov    ebx,edi
  4330.     sub    ebx,4+ResHead+ResNum
  4331.     sub    ebx,esi
  4332.     shr    ebx,2
  4333.     add    ebx,esi
  4334.     add    ebx,ResHead
  4335.     cmp    es:b[ebx],dl        ;Right type?
  4336.     jz    @@1
  4337.     cmp    dl,Res_SEL        ;Selector?
  4338.     jnz    @@2
  4339.     cmp    es:b[ebx],Res_PSP
  4340.     jnz    @@2
  4341.     ;
  4342. @@1:    ;At this point we have a match.
  4343.     ;
  4344.     xor    eax,eax
  4345.     sub    edi,4
  4346.     mov    dl,es:[ebx]
  4347.     xor    dh,dh
  4348.     cmp    dl,Res_SEL
  4349.     jz    @@rel_1
  4350.     cmp    dl,Res_LOCK
  4351.     jz    @@Rel_2
  4352.     cmp    dl,Res_MEM
  4353.     jz    @@Rel_3
  4354.     cmp    dl,Res_DOSMEM
  4355.     jz    @@Rel_2
  4356.     cmp    dl,Res_CALLBACK
  4357.     jz    @@Rel_3
  4358.     cmp    dl,Res_PSP
  4359.     jz    @@psp
  4360.     jmp    @@9
  4361. ;
  4362. @@Rel_3:    mov    es:b[ebx],dh
  4363.     mov    es:d[edi],eax
  4364.     inc    ebx
  4365.     add    edi,4
  4366. @@Rel_2:    mov    es:b[ebx],dh
  4367.     mov    es:d[edi],eax
  4368.     inc    ebx
  4369.     add    edi,4
  4370. @@Rel_1:    mov    es:b[ebx],dh
  4371.     mov    es:d[edi],eax
  4372.     jmp    @@9
  4373. ;
  4374. ;Release a PSP. Assumes that the PSP memory will be released by the caller.
  4375. ;
  4376. @@psp:    mov    es:[ebx],dh
  4377.     push    w[PSPSegment]
  4378.     mov    bx,es:[edi]
  4379.     mov    fs,bx
  4380. ;
  4381. ;Remove links to all other modules.
  4382. ;
  4383.     cmp    fs:d[EPSP_Imports],0
  4384.     jz    @@no_imports
  4385.     pushm    ecx,esi,edi
  4386.     mov    esi,fs:d[EPSP_Imports]
  4387.     mov    ecx,es:[esi]
  4388.     add    esi,4
  4389. @@imp0:    or    ecx,ecx
  4390.     jz    @@imp1
  4391.     mov    edi,es:[esi]
  4392.     call    UnFindModule
  4393.     add    esi,4
  4394.     dec    ecx
  4395.     jmp    @@imp0
  4396. @@imp1:    popm    ecx,esi,edi
  4397. @@no_imports:
  4398.  
  4399.     cmp    fs:[EPSP_Resource],0
  4400.     jnz    @@normal_res
  4401.     ;
  4402.     ;This must be a cwLoad PSP.
  4403.     ;
  4404.     ;release program selectors and memory manually.
  4405.     ;
  4406.     pushad
  4407.     movzx    ecx,fs:w[EPSP_SegSize]
  4408.     shr    ecx,3
  4409.     mov    bx,fs:w[EPSP_SegBase]
  4410.     or    ecx,ecx
  4411.     jz    @@frelsel9
  4412. @@frelsel:    sys    RelSel
  4413.     add    bx,8
  4414.     dec    ecx
  4415.     jnz    @@frelsel
  4416. @@frelsel9:    mov    esi,fs:[EPSP_MemBase]
  4417.     sys    RelMemLinear32
  4418.     mov    esi,fs:[EPSP_Exports]
  4419.     or    esi,esi
  4420.     jz    @@frelsel0
  4421.     sys    RelMemLinear32
  4422. @@frelsel0:    popad
  4423.     ;
  4424. @@normal_res:    ;Take this PSP out of the linked list.
  4425.     ;
  4426.     pushad
  4427.     mov    bx,fs
  4428.     sys    GetSelDet32
  4429.     mov    esi,es:EPSP_NextPSP[edx]
  4430.     mov    edi,es:EPSP_LastPSP[edx]
  4431.     or    esi,esi
  4432.     jz    @@ChainPSP0
  4433.     mov    es:EPSP_LastPSP[esi],edi
  4434. @@ChainPSP0:    or    edi,edi
  4435.     jz    @@ChainPSP1
  4436.     mov    es:EPSP_NextPSP[edi],esi
  4437. @@ChainPSP1:    popad
  4438.     ;
  4439.     mov    ah,50h
  4440.     int    21h        ;set new PSP.
  4441.     ;
  4442.     ;Search for PSP's and release them first.
  4443.     ;
  4444.     mov    esi,fs:[EPSP_Resource]    ;Get resource pointer.
  4445. @@fPSP0:    or    esi,esi
  4446.     jz    @@NoPSPSearch
  4447.     mov    ebp,ResNum
  4448.     mov    edi,esi
  4449.     add    edi,16
  4450.     mov    edx,esi
  4451.     add    edx,ResHead+ResNum
  4452. @@fPSP1:    cmp    es:b[edi],Res_PSP
  4453.     jnz    @@fPSP2
  4454.     push    ebx
  4455.     mov    ebx,es:[edx]        ;Get selector.
  4456.     sys    RelMem
  4457.     pop    ebx
  4458. @@fPSP2:    inc    edi
  4459.     add    edx,4
  4460.     dec    ebp
  4461.     jnz    @@fPSP1
  4462.     mov    esi,es:[esi+8]    ;link to next list.
  4463.     jmp    @@fPSP0
  4464.     ;
  4465. @@NoPSPSearch:    ;Now release all other types of resource.
  4466.     ;
  4467.     cmp    fs:w[EPSP_DPMIMem],0    ;Any DPMI save buffer?
  4468.     jz    @@psp_0
  4469.     xor    bx,bx
  4470.     xchg    bx,fs:w[EPSP_DPMIMem]
  4471.     sys    RelMem
  4472. @@psp_0:    ;
  4473.     cmp    fs:d[EPSP_INTMem],0    ;Any int/excep vector memory?
  4474.     jz    @@psp_1
  4475.     xor    esi,esi
  4476.     xchg    esi,fs:d[EPSP_INTMem]
  4477.     sys    RelMemLinear32
  4478. @@psp_1:    ;
  4479.     mov    esi,fs:[EPSP_Resource]    ;Get resource pointer.
  4480.     or    esi,esi
  4481.     jz    @@psp_9
  4482. @@psp_2:    cmp    es:d[esi+8],0    ;Found last entry in chain?
  4483.     jz    @@psp_3
  4484.     mov    esi,es:d[esi+8]
  4485.     jmp    @@psp_2
  4486. @@psp_3:    ;
  4487.     mov    ebp,ResNum
  4488.     mov    edi,esi
  4489.     add    edi,16
  4490.     mov    edx,esi
  4491.     add    edx,ResHead+ResNum
  4492. @@psp_4:    cmp    es:b[edi],Res_NULL
  4493.     jz    @@psp_5
  4494.     cmp    es:b[edi],Res_SEL
  4495.     jz    @@sel
  4496.     cmp    es:b[edi],Res_MEM
  4497.     jz    @@mem
  4498.     cmp    es:b[edi],Res_LOCK
  4499.     jz    @@lock
  4500.     cmp    es:b[edi],Res_DOSMEM
  4501.     jz    @@dosmem
  4502.     cmp    es:b[edi],Res_CALLBACK
  4503.     jz    @@callback
  4504.     cmp    es:b[edi],Res_PSP
  4505.     jz    @@rel_psp
  4506.     jmp    @@psp_5
  4507. ;
  4508. ;Release a selector.
  4509. ;
  4510. @@sel:    mov    es:b[edi],Res_NULL
  4511.     pushm    esi,edi,ebp,edx
  4512.     mov    ebx,es:[edx]
  4513.     push    ResourceTracking
  4514.     mov    ResourceTracking,0
  4515.     call    _RelSelector
  4516.     pop    ResourceTracking
  4517.     popm    esi,edi,ebp,edx
  4518.     jmp    @@psp_5
  4519. ;
  4520. ;Release some memory.
  4521. ;
  4522. @@mem:    mov    ForcedFind,edx
  4523.     mov    ForcedFind+4,edi
  4524.     mov    es:b[edi],Res_NULL
  4525.     mov    eax,es:[edx]
  4526.     inc    edi
  4527.     add    edx,4
  4528.     mov    es:b[edi],Res_NULL
  4529.     inc    edi
  4530.     add    edx,4
  4531.     mov    es:b[edi],Res_NULL
  4532.     pushm    esi,edi,ebp,edx
  4533.     mov    esi,eax
  4534.     call    _RelMemory
  4535.     popm    esi,edi,ebp,edx
  4536.     sub    ebp,2
  4537.     jmp    @@psp_5
  4538. ;
  4539. ;Release a lock.
  4540. ;
  4541. @@lock:    mov    es:b[edi],Res_NULL
  4542.     mov    eax,es:[edx]
  4543.     inc    edi
  4544.     add    edx,4
  4545.     mov    es:b[edi],Res_NULL
  4546.     pushm    esi,edi,ebp,edx
  4547.     mov    ecx,es:[edx]
  4548.     mov    esi,eax
  4549.     push    ResourceTracking
  4550.     mov    ResourceTracking,0
  4551.     sys    UnLockMem32
  4552.     pop    ResourceTracking
  4553.     popm    esi,edi,ebp,edx
  4554.     dec    ebp
  4555.     jmp    @@psp_5
  4556. ;
  4557. ;Release DOS memory.
  4558. ;
  4559. @@dosmem:    mov    es:b[edi],Res_NULL
  4560.     mov    eax,es:[edx]
  4561.     inc    edi
  4562.     add    edx,4
  4563.     mov    es:b[edi],Res_NULL
  4564.     pushm    eax,edx
  4565.     mov    edx,eax
  4566.     push    ResourceTracking
  4567.     mov    ResourceTracking,0
  4568.     sys    RelMemDOS
  4569.     pop    ResourceTracking
  4570.     popm    eax,edx
  4571.     dec    ebp
  4572.     jmp    @@psp_5
  4573. ;
  4574. ;Release a call-back.
  4575. ;
  4576. @@callback:    mov    es:b[edi],Res_NULL
  4577.     mov    eax,es:[edx]
  4578.     inc    edi
  4579.     add    edx,4
  4580.     mov    es:b[edi],Res_NULL
  4581.     inc    edi
  4582.     add    edx,4
  4583.     mov    es:b[edi],Res_NULL
  4584.     pushm    eax,ecx,edx
  4585.     mov    ecx,eax
  4586.     mov    dx,cx
  4587.     shr    ecx,16
  4588.     mov    ax,0304h
  4589.     push    ResourceTracking
  4590.     mov    ResourceTracking,0
  4591.     cwAPI_CallOld
  4592.     assume ds:_cwMain
  4593.     pop    ResourceTracking
  4594.     popm    eax,ecx,edx
  4595.     sub    ebp,2
  4596.     jmp    @@psp_5
  4597. ;
  4598. ;Release another PSP.
  4599. ;
  4600. @@rel_psp:    pushm    esi,edi,ebp,edx
  4601.     mov    ebx,es:[edx]
  4602.     sys    RelMem
  4603.     popm    esi,edi,ebp,edx
  4604. ;
  4605. @@psp_5:    inc    edi
  4606.     add    edx,4
  4607.     dec    ebp
  4608.     jnz    @@psp_4
  4609.     mov    eax,es:d[esi+4]    ;get back link pointer.
  4610.     push    eax
  4611.     push    esi
  4612.     mov    esi,es:[esi+12]    ;get memory handle.
  4613.     mov    di,si
  4614.     shr    esi,16
  4615.     mov    ax,0502h        ;release the block.
  4616.     cwAPI_CallOld
  4617.     pop    esi
  4618.     pushm    ebx,ecx,edi
  4619.     mov    cx,si
  4620.     shr    esi,16
  4621.     mov    bx,si
  4622.     xor    si,si
  4623.     mov    di,4096
  4624.     mov    ax,0703h        ;discard the block.
  4625.     cwAPI_CallOld
  4626.     popm    ebx,ecx,edi
  4627.     pop    esi
  4628.     or    esi,esi
  4629.     jz    @@psp_9
  4630.     mov    es:d[esi+8],0    ;make sure link pointer is clear
  4631.     jmp    @@psp_3
  4632. @@psp_9:    ;
  4633.     ;Switch back to the old PSP
  4634.     ;
  4635.     pop    bx
  4636.     mov    ah,50h
  4637.     int    21h        ;go back to old PSP.
  4638.     ;
  4639. @@9:    popad
  4640.     popm    ds,es,fs
  4641.     ret
  4642.     assume ds:_apiCode
  4643. ReleaseResource endp
  4644.  
  4645.  
  4646. ;-------------------------------------------------------------------------
  4647. ;
  4648. ;Check if a resource exists.
  4649. ;
  4650. ;On Entry:
  4651. ;
  4652. ;AL    - Resource type.
  4653. ;EDX    - Key value.
  4654. ;
  4655. ;On Exit:
  4656. ;
  4657. ;Carry clear if it does and,
  4658. ;
  4659. ;ECX    - Optional second value.
  4660. ;EBX    - Optional third value.
  4661. ;
  4662. FindResource    proc    near
  4663.     pushm    ds,es,fs
  4664.     pushm    eax,edx,esi,edi,ebp
  4665.     assume ds:nothing
  4666.     mov    ds,cs:apiDSeg
  4667.     assume ds:_cwMain
  4668.     mov    es,RealSegment
  4669.     mov    fs,PSPSegment
  4670.     xchg    eax,edx
  4671.     xor    edi,edi
  4672.     xchg    edi,ForcedFind
  4673.     mov    ebp,ForcedFind+4
  4674.     or    edi,edi
  4675.     jnz    @@Found
  4676.     cmp    ResourceTracking,0
  4677.     jz    @@8
  4678.     cmp    fs:d[EPSP_Resource],0
  4679.     jz    @@8
  4680.     ;
  4681.     mov    esi,fs:d[EPSP_Resource]
  4682. @@LookLoop:    mov    ecx,ResNum        ;get number of entries.
  4683.     mov    edi,esi
  4684.     add    edi,ResHead+ResNum
  4685.     cld
  4686. @@0:    repne    scasd
  4687.     jz    @@1
  4688.     mov    esi,es:[esi+8]    ;link to next list.
  4689.     or    esi,esi
  4690.     jnz    @@LookLoop
  4691.     stc
  4692.     jmp    @@9
  4693. @@1:    mov    ebp,edi
  4694.     sub    ebp,4+ResHead+ResNum
  4695.     sub    ebp,esi
  4696.     shr    ebp,2
  4697.     add    ebp,ResHead
  4698.     add    ebp,esi
  4699.     cmp    es:[ebp],dl
  4700.     jnz    @@0
  4701.     sub    edi,4
  4702.     ;
  4703. @@Found:    cmp    dl,Res_SEL
  4704.     jz    @@8
  4705.     cmp    dl,Res_MEM
  4706.     jz    @@2
  4707.     cmp    dl,Res_LOCK
  4708.     jz    @@8
  4709.     cmp    dl,Res_DOSMEM
  4710.     jz    @@8
  4711.     cmp    dl,Res_CALLBACK
  4712.     jz    @@8
  4713.     cmp    dl,Res_PSP
  4714.     jz    @@8
  4715.     stc
  4716.     jmp    @@9
  4717.     ;
  4718. @@2:    assume ds:nothing
  4719.     mov    ds,cs:apiDDSeg
  4720.     assume ds:_apiCode
  4721.     mov    LastResource,edi
  4722.     mov    LastResource+4,ebp
  4723.     add    edi,4
  4724.     mov    ecx,es:[edi]
  4725.     add    edi,4
  4726.     mov    ebx,es:[edi]
  4727.     ;
  4728. @@8:    clc
  4729.     ;
  4730. @@9:    popm    eax,edx,esi,edi,ebp
  4731.     popm    ds,es,fs
  4732.     ret
  4733. FindResource    endp
  4734.  
  4735.  
  4736. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  4737. SaveExecState    proc    near
  4738.     push    es
  4739.     push    ds
  4740.     assume ds:nothing
  4741.     mov    ds,cs:apiDSeg
  4742.     assume ds:_cwMain
  4743. ;
  4744. ;Get memory for the interrupt/exception vector save buffer.
  4745. ;
  4746.     mov    ecx,(256*6)+(256*4)+(32*6)
  4747.     sys    GetMemLinear32
  4748.     jc    @@9
  4749.     mov    es,PSPSegment
  4750.     mov    es:d[EPSP_INTMem],esi
  4751.     mov    edi,esi
  4752.     mov    es,RealSegment
  4753. ;
  4754. ;Get protected mode interrupt vectors.
  4755. ;
  4756.     mov    bl,0
  4757.     mov    bp,256
  4758. @@GetPVect:    pushm    bx,edi,bp,es
  4759.     sys    GetVect
  4760.     popm    bx,edi,bp,es
  4761.     mov    es:d[edi],edx
  4762.     mov    es:w[edi+4],cx
  4763.     add    edi,6
  4764.     inc    bl
  4765.     dec    bp
  4766.     jnz    @@GetPVect
  4767. ;
  4768. ;Get protected mode exception vectors.
  4769. ;
  4770.     mov    bp,32
  4771.     mov    bl,0
  4772. @@GetEVect:    pushm    bx,edi,bp,es
  4773.     sys    GetEVect
  4774.     popm    bx,edi,bp,es
  4775.     mov    es:d[edi],edx
  4776.     mov    es:w[edi+4],cx
  4777.     add    edi,6
  4778.     inc    bl
  4779.     dec    bp
  4780.     jnz    @@GetEVect
  4781. ;
  4782. ;Get real mode interrupt vectors.
  4783. ;
  4784.     mov    bp,256
  4785.     mov    bl,0
  4786. @@GetRVect:    pushm    bx,edi,bp,es
  4787.     sys    GetRVect
  4788.     popm    bx,edi,bp,es
  4789.     mov    es:w[edi],dx
  4790.     mov    es:w[edi+2],cx
  4791.     add    edi,4
  4792.     inc    bl
  4793.     dec    bp
  4794.     jnz    @@GetRVect
  4795. ;
  4796. ;Get memory for DPMI state buffer.
  4797. ;
  4798.     cmp    d[DPMIStateSize],0
  4799.     jz    @@NoDPMISave
  4800.     mov    ecx,d[DPMIStateSize]
  4801.     sys    GetMem32
  4802.     jc    @@9
  4803. ;
  4804. ;Save DPMI state.
  4805. ;
  4806.     mov    es,PSPSegment
  4807.     mov    es:w[EPSP_DPMIMem],bx
  4808.     mov    es,bx
  4809.     xor    edi,edi
  4810.     mov    al,0
  4811.     test    SystemFlags,1
  4812.     jz    @@DPMISave32
  4813.     db 66h
  4814.     call    f[DPMIStateAddr]
  4815.     jmp    @@NoDPMISave
  4816. @@DPMISave32:    call    f[DPMIStateAddr]
  4817. @@NoDPMISave:    ;
  4818.     clc
  4819. @@9:    pop    ds
  4820.     assume ds:_apiCode
  4821.     pop    es
  4822.     ret
  4823. SaveExecState    endp
  4824.  
  4825.  
  4826. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  4827. LoadExecState    proc    near
  4828.     push    es
  4829.     push    ds
  4830.     assume ds:nothing
  4831.     mov    ds,cs:apiDSeg
  4832.     assume ds:_cwMain
  4833. ;
  4834. ;Set protected mode interrupt vectors.
  4835. ;
  4836.     mov    es,PSPSegment
  4837.     mov    edi,es:d[EPSP_INTMem]
  4838.     or    edi,edi
  4839.     jz    @@NoIntRel
  4840.     mov    es,RealSegment
  4841.     mov    bl,0
  4842.     mov    bp,256
  4843. @@SetPVect:    pushm    bx,edi,bp,es
  4844.     sys    GetVect
  4845.     pushm    ecx,edx
  4846.     mov    edx,es:d[edi]
  4847.     mov    cx,es:w[edi+4]
  4848.     sys    SetVect
  4849.     popm    ecx,edx
  4850.     cmp    edx,es:d[edi]
  4851.     jnz    @@Pdiff
  4852.     cmp    cx,es:w[edi+4]
  4853.     jnz    @@Pdiff
  4854.     mov    es:w[edi+4],-1
  4855.     jmp    @@Pdone
  4856. @@Pdiff:    mov    es:d[edi],edx
  4857.     mov    es:w[edi+4],cx
  4858. @@Pdone:    popm    bx,edi,bp,es
  4859.     add    edi,6
  4860.     inc    bl
  4861.     dec    bp
  4862.     jnz    @@SetPVect
  4863. ;
  4864. ;Set protected mode exception vectors.
  4865. ;
  4866.     mov    bp,32
  4867.     mov    bl,0
  4868. @@SetEVect:    pushm    bx,edi,bp,es
  4869.     sys    GetEVect
  4870.     pushm    ecx,edx
  4871.     mov    edx,es:d[edi]
  4872.     mov    cx,es:w[edi+4]
  4873.     sys    SetEVect
  4874.     popm    ecx,edx
  4875.     cmp    edx,es:[edi]
  4876.     jnz    @@Ediff
  4877.     cmp    cx,es:[edi+4]
  4878.     jnz    @@Ediff
  4879.     mov    es:w[edi+4],-1
  4880.     jmp    @@Edone
  4881. @@Ediff:    mov    es:[edi],edx
  4882.     mov    es:[edi+4],cx
  4883. @@Edone:    popm    bx,edi,bp,es
  4884.     add    edi,6
  4885.     inc    bl
  4886.     dec    bp
  4887.     jnz    @@SetEVect
  4888. ;
  4889. ;Set real mode interrupt vectors.
  4890. ;
  4891.     mov    bp,256
  4892.     mov    bl,0
  4893. @@SetRVect:    pushm    bx,edi,bp,es
  4894.     sys    GetRVect
  4895.     pushm    cx,dx
  4896.     mov    dx,es:w[edi]
  4897.     mov    cx,es:w[edi+2]
  4898.     sys    SetRVect
  4899.     popm    cx,dx
  4900.     cmp    dx,es:[edi]
  4901.     jnz    @@Rdiff
  4902.     cmp    cx,es:[edi+2]
  4903.     jnz    @@Rdiff
  4904.     mov    es:w[edi+2],-1
  4905.     jmp    @@Rdone
  4906. @@Rdiff:    mov    es:[edi],dx
  4907.     mov    es:[edi+2],cx
  4908. @@Rdone:    popm    bx,edi,bp,es
  4909.     add    edi,4
  4910.     inc    bl
  4911.     dec    bp
  4912.     jnz    @@SetRVect
  4913. ;
  4914. ;Restore DPMI stack state.
  4915. ;
  4916. @@NoIntRel:    mov    es,PSPSegment
  4917.     mov    ax,es:w[EPSP_DPMIMem]
  4918.     or    ax,ax
  4919.     jz    @@NoDPMIRel
  4920.     jmp    @@NoDPMIRel
  4921.     mov    es,ax
  4922.     xor    edi,edi
  4923.     mov    al,1
  4924.     test    SystemFlags,1
  4925.     jz    @@SaveDPMI32
  4926.     db 66h
  4927.     call    f[DPMIStateAddr]
  4928.     jmp    @@NoDPMIRel
  4929. @@SaveDPMI32:    call    f[DPMIStateAddr]
  4930. @@NoDPMIRel:    ;
  4931.     pop    ds
  4932.     assume ds:_apiCode
  4933.     pop    es
  4934.     ret
  4935. LoadExecState    endp
  4936.  
  4937.  
  4938. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  4939. ;
  4940. ;Create a new PSP complete with command line, environment & saved state.
  4941. ;
  4942. ;On Entry:
  4943. ;
  4944. ;EBX    - flags, as passed to _Exec
  4945. ;DS:EDX    - program name
  4946. ;ES:ESI    - command line.
  4947. ;CX    - environment.
  4948. ;
  4949. ;On Exit:
  4950. ;
  4951. ;Carry set on error &,
  4952. ;
  4953. ;BX    - new PSP (zero if error).
  4954. ;
  4955. CreatePSP    proc    near
  4956.     mov    ax,ds
  4957.     pushm    ds,es,fs,gs
  4958.     assume ds:nothing
  4959.     mov    ds,cs:apiDDSeg
  4960.     assume ds:_apiCode
  4961.     ;
  4962.     mov    d[@@Name],edx
  4963.     mov    w[@@Name+4],ax
  4964.     mov    d[@@Flags],ebx
  4965.     mov    d[@@Command],esi
  4966.     mov    w[@@Command+4],es
  4967.     mov    w[@@Environment],cx
  4968.     ;
  4969.     mov    w[@@PSP],0
  4970. ;
  4971. ;Allocate PSP memory.
  4972. ;
  4973.     mov    ecx,(size PSP_Struc)+(size EPSP_Struc)
  4974.     sys    GetMemLinear32
  4975.     jc    @@error        ;Not enough memory.
  4976.     push    ds
  4977.     mov    ds,apiDSeg
  4978.     assume ds:_cwMain
  4979.     push    ResourceTracking
  4980.     mov    ResourceTracking,0
  4981.     sys    GetSel
  4982.     jnc    @@memOK
  4983.     pop    ResourceTracking
  4984.     pop    ds
  4985.     sys    RelMemLinear32
  4986.     jmp    @@error
  4987. @@memOK:    mov    edx,esi
  4988.     mov    ecx,(size PSP_Struc)+(size EPSP_Struc)
  4989.     sys    SetSelDet32
  4990.     pop    ResourceTracking
  4991.     assume ds:_apiCode
  4992.     pop    ds
  4993. ;
  4994. ;Register this selector as a PSP.
  4995. ;
  4996.     mov    ax,Res_PSP
  4997.     movzx    edx,bx
  4998.     call    RegisterResource    ;register this PSP.
  4999.     jnc    @@memOK2
  5000.     ;
  5001.     push    ds
  5002.     mov    ds,apiDSeg
  5003.     assume ds:_cwMain
  5004.     push    ResourceTracking
  5005.     mov    ResourceTracking,0
  5006.     sys    RelSel
  5007.     sys    RelMemLinear32
  5008.     pop    ResourceTracking
  5009.     assume ds:_apiCode
  5010.     pop    ds
  5011.     jmp    @@error
  5012.     ;
  5013. @@memOK2:    mov    w[@@PSP],bx
  5014. ;
  5015. ;Copy parent PSP to this PSP.
  5016. ;
  5017.     push    ds
  5018.     mov    es,bx
  5019.     mov    ds,apiDSeg
  5020.     assume ds:_cwMain
  5021.     mov    ds,PSPSegment
  5022.     assume ds:_apiCode
  5023.     xor    esi,esi
  5024.     xor    edi,edi
  5025.     mov    ecx,256/4
  5026.     cld
  5027.     rep    movsd
  5028.     mov    ax,ds:[EPSP_RealENV]    ;copy real mode environment
  5029.     mov    es:[EPSP_RealENV],ax    ;segment.
  5030.     mov    eax,ds:[EPSP_ExecCount]
  5031.     mov    es:[EPSP_ExecCount],eax
  5032.     pop    ds
  5033. ;
  5034. ;Initialise PSP fields.
  5035. ;
  5036.     push    fs
  5037.     mov    fs,apiDSeg
  5038.     assume fs:_cwMain
  5039.     mov    fs,fs:PSPSegment
  5040.     assume fs:nothing
  5041.     mov    es,bx
  5042.     mov    es:d[EPSP_Resource],0    ;Clear memory fields.
  5043.     mov    es:d[EPSP_INTMem],0
  5044.     mov    es:d[EPSP_DPMIMem],0
  5045.     mov    es:w[EPSP_Parent],fs    ;set parent PSP.
  5046.     mov    es:d[EPSP_DTA],80h    ;Use default PSP DTA.
  5047.     mov    es:w[EPSP_DTA+4],es
  5048.     mov    ax,fs:w[EPSP_TransProt]    ;inherit current transfer buffer.
  5049.     mov    es:w[EPSP_TransProt],ax
  5050.     mov    ax,fs:w[EPSP_TransReal]
  5051.     mov    es:w[EPSP_TransReal],ax
  5052.     mov    eax,fs:d[EPSP_TransSize]
  5053.     mov    es:d[EPSP_TransSize],eax
  5054.     mov    eax,fs:d[EPSP_mcbMaxAlloc]
  5055.     mov    es:d[EPSP_mcbMaxAlloc],eax
  5056.     mov    es:d[EPSP_mcbHead],0
  5057.     cmp    d[@@Flags],2        ;cwLoad?
  5058.     jz    @@NoNext
  5059.     mov    fs:w[EPSP_Next],es
  5060. @@NoNext:    mov    es:w[EPSP_Next],0
  5061.     mov    es:w[PSP_Environment],0
  5062.     mov    es:w[EPSP_SegBase],0
  5063.     mov    es:w[EPSP_SegSize],0
  5064.     mov    es:d[EPSP_Exports],0
  5065.     mov    es:d[EPSP_Imports],0
  5066.     mov    es:d[EPSP_Links],0
  5067.     mov    es:w[EPSP_EntryCSEIP+4],0
  5068.     mov    es:w[EPSP_PSPSel],es
  5069.     pop    fs
  5070. ;
  5071. ;Update PSP linked list.
  5072. ;
  5073.     push    es
  5074.     mov    es,apiDSeg
  5075.     assume es:_cwMain
  5076.     mov    esi,es:BasePSPAddress
  5077.     mov    es,es:RealSegment
  5078.     assume es:nothing
  5079. @@ChainPSP0:    cmp    es:EPSP_NextPSP[esi],0
  5080.     jz    @@ChainPSP1
  5081.     mov    esi,es:EPSP_NextPSP[esi]
  5082.     jmp    @@ChainPSP0
  5083. @@ChainPSP1:    sys    GetSelDet32
  5084.     mov    es:EPSP_NextPSP[esi],edx
  5085.     mov    es:EPSP_LastPSP[edx],esi
  5086.     mov    es:EPSP_NextPSP[edx],0
  5087.     pop    es
  5088. ;
  5089. ;Switch to this PSP.
  5090. ;
  5091.     cmp    d[@@Flags],2        ;cwLoad?
  5092.     jz    @@NoPSwitch0
  5093.     mov    ah,50h
  5094.     int    21h        ;set new PSP.
  5095. ;
  5096. ;Set new DTA address.
  5097. ;
  5098. @@NoPSwitch0:    cmp    d[@@Flags],2
  5099.     jz    @@NoDTA
  5100.     push    ds
  5101.     lds    edx,es:f[EPSP_DTA]
  5102.     mov    ah,1ah
  5103.     int    21h
  5104.     pop    ds
  5105. ;
  5106. ;Preserve current state.
  5107. ;
  5108. @@NoDTA:    cmp    d[@@Flags],2
  5109.     jz    @@NoSave
  5110.     call    SaveExecState    ;do old state save.
  5111.     jc    @@error        ;Not enough memory.
  5112. ;
  5113. ;Build command line.
  5114. ;
  5115. @@NoSave:    cmp    w[@@Command+4],0
  5116.     jz    @@NoCommand
  5117.     mov    es,w[@@PSP]
  5118.     mov    edi,80h
  5119.     mov    es:d[edi],0
  5120.     push    ds
  5121.     lds    esi,f[@@Command]
  5122.     movzx    ecx,b[esi]
  5123.     inc    ecx
  5124.     cld
  5125.     rep    movsb
  5126.     mov    es:b[edi],13
  5127.     pop    ds
  5128. ;
  5129. ;Check what's needed with the environment selector.
  5130. ;
  5131. @@NoCommand:    cmp    d[@@Flags],2        ;cwLoad?
  5132.     jz    @@CopyEnv    ;NoEnv
  5133.     mov    ax,w[@@Environment]
  5134.     or    ax,ax
  5135.     jz    @@ParentEnv
  5136.     mov    es,apiDSeg
  5137.     assume es:_cwMain
  5138.     mov    es,es:PSPSegment
  5139.     assume es:nothing
  5140.     mov    es:w[PSP_Environment],ax
  5141.     jmp    @@GotEnv
  5142.  
  5143. @@CopyEnv:    push    es
  5144.     mov    es,apiDSeg
  5145.     assume es:_cwMain
  5146.     mov    ax,es:PSPSegment
  5147.     assume es:nothing
  5148.     mov    es,w[@@PSP]
  5149.     mov    es:w[PSP_Environment],ax
  5150.     pop    es
  5151.     jmp    @@NoEnv
  5152.  
  5153. ;
  5154. ;Need to make a copy of the parent environment string.
  5155. ;
  5156. @@ParentEnv:    mov    es,apiDSeg
  5157.     assume es:_cwMain
  5158.     mov    es,es:PSPSegment
  5159.     assume es:nothing
  5160.     mov    es,es:w[EPSP_Parent]    ;Get parent PSP.
  5161.     mov    es,es:w[PSP_Environment]    ;Get parents environment.
  5162. ;
  5163. ;Find out how long current environment is.
  5164. ;
  5165.     xor    esi,esi
  5166. @@gp2:    mov    al,es:[esi]        ;Get a byte.
  5167.     inc    esi        ;/
  5168.     or    al,al        ;End of a string?
  5169.     jnz    @@gp2        ;keep looking.
  5170.     mov    al,es:[esi]        ;Double zero?
  5171.     or    al,al        ;/
  5172.     jnz    @@gp2        ;keep looking.
  5173.     add    esi,3        ;Skip last 0 and word count.
  5174.     mov    ecx,esi
  5175.     add    ecx,256        ;allow for exec name length.
  5176.     sys    GetMem32
  5177.     jc    @@error
  5178.     mov    ax,es
  5179.     mov    es,apiDSeg
  5180.     assume es:_cwMain
  5181.     mov    es,es:PSPSegment
  5182.     assume es:nothing
  5183.     mov    es:w[PSP_Environment],bx
  5184.     mov    ecx,esi        ;get length again.
  5185.     push    ds
  5186.     mov    ds,ax
  5187.     mov    es,bx
  5188.     xor    esi,esi
  5189.     xor    edi,edi
  5190.     rep    movsb        ;copy current strings.
  5191.     pop    ds
  5192. ;
  5193. ;Add execution path and name to environment strings.
  5194. ;
  5195. @@GotEnv:    mov    es,apiDSeg
  5196.     assume es:_cwMain
  5197.     mov    es,es:PSPSegment
  5198.     assume es:nothing
  5199.     mov    es,es:w[PSP_Environment]
  5200.     xor    esi,esi
  5201. @@gp0:    mov    al,es:[esi]        ;Get a byte.
  5202.     inc    esi        ;/
  5203.     or    al,al        ;End of a string?
  5204.     jnz    @@gp0        ;keep looking.
  5205.     mov    al,es:[esi]        ;Double zero?
  5206.     or    al,al        ;/
  5207.     jnz    @@gp0        ;keep looking.
  5208.     add    esi,3        ;Skip last 0 and word count.
  5209.     mov    ebp,esi
  5210. ;
  5211. ;Now build the file name.
  5212. ;
  5213.     push    ds
  5214.     lds    esi,f[@@Name]
  5215.     mov    al,b[esi+1]
  5216.     pop    ds
  5217.     mov    edi,ebp
  5218.     cmp    al,":"        ;drive specification?
  5219.     jz    @@NoGetPath
  5220.     push    edi
  5221.     mov    ah,19h    ;get current disc
  5222.     int    21h
  5223.     mov    dl,al
  5224.     add    al,'A'    ;make it a character
  5225.     pop    esi
  5226.     mov    es:[esi],al
  5227.     inc    esi
  5228.     mov    es:b[esi],":"
  5229.     inc    esi
  5230.     ;
  5231.     push    ds
  5232.     push    esi
  5233.     lds    esi,f[@@Name]
  5234.     mov    al,b[esi]
  5235.     pop    esi
  5236.     pop    ds
  5237.     mov    edi,esi
  5238.     cmp    al,"\"
  5239.     jz    @@NoGetPath
  5240.     ;
  5241.     mov    es:b[esi],"\"
  5242.     inc    esi
  5243.     mov    es:b[esi],0
  5244.     mov    ah,47h    ;get current directory
  5245.     xor    dl,dl    ;default drive
  5246.     push    ds
  5247.     push    es
  5248.     pop    ds
  5249.     int    21h    ;get text
  5250.     pop    ds
  5251.     mov    esi,ebp
  5252.     push    ds
  5253.     push    es
  5254.     pop    ds
  5255. @@gp1:    lodsb
  5256.     or    al,al
  5257.     jnz    @@gp1
  5258.     pop    ds
  5259.     dec    esi
  5260.     mov    edi,esi
  5261.     mov    al,"\"
  5262.     stosb
  5263. ;
  5264. ;Append EXE file name to EDI.
  5265. ;
  5266. @@NoGetPath:    push    ds
  5267.     lds    esi,f[@@Name]
  5268. @@gp3:    lodsb
  5269.     stosb
  5270.     or    al,al
  5271.     jnz    @@gp3
  5272.     pop    ds
  5273. ;
  5274. ;Return to caller.
  5275. ;
  5276. @@NoEnv:    clc
  5277.     jmp    @@exit
  5278. ;
  5279. ;Not enough memory.
  5280. ;
  5281. @@error:    stc
  5282. ;
  5283. @@exit:    mov    bx,w[@@PSP]
  5284.     popm    ds,es,fs,gs
  5285.     ret
  5286. ;
  5287. @@PSP:    ;
  5288.     dw 0
  5289. @@Command:    ;
  5290.     df 0
  5291. @@Name:    ;
  5292.     df 0
  5293. @@Environment:    ;
  5294.     dw 0
  5295. @@Flags:    ;
  5296.     dd 0
  5297. CreatePSP    endp
  5298.  
  5299.  
  5300. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  5301. DeletePSP    proc    near
  5302.     pushm    ds,es,fs,gs
  5303.     assume ds:nothing
  5304.     mov    ds,cs:apiDDSeg
  5305.     assume ds:_apiCode
  5306.     ;
  5307.     mov    d[@@Flags],eax
  5308.     mov    w[@@PSP],bx
  5309. ;
  5310.     cmp    d[@@Flags],2
  5311.     jz    @@NoIRel
  5312.     call    LoadExecState
  5313. ;
  5314. ;Close all open files.
  5315. ;
  5316.     call    LoseFileHandles
  5317. ;
  5318. ;Restore resources.
  5319. ;
  5320. @@NoIRel:    mov    es,apiDSeg
  5321.     assume es:_cwMain
  5322.     cmp    es:w[TerminationHandler],offset cwClose
  5323.     jnz    @@YesRelRes
  5324.     cmp    es:DebugDump,0
  5325.     jnz    @@NoNRel
  5326. @@YesRelRes:    assume es:nothing
  5327.     mov    es,w[@@PSP]
  5328.     mov    bx,es:w[EPSP_Parent]
  5329.     cmp    d[@@Flags],2
  5330.     jz    @@NoPRel
  5331.     mov    ah,50h
  5332.     int    21h        ;restore old PSP.
  5333. @@NoPRel:    mov    bx,es
  5334.     sys    RelMem
  5335.     cmp    d[@@Flags],2
  5336.     jz    @@NoNRel
  5337.     mov    es,apiDSeg
  5338.     assume es:_cwMain
  5339.     mov    es,es:PSPSegment
  5340.     assume es:nothing
  5341.     mov    es:w[EPSP_Next],0
  5342. @@NoNRel:    ;
  5343.     popm    ds,es,fs,gs
  5344.     ret
  5345. ;
  5346. @@PSP:    ;
  5347.     dw ?
  5348. @@Flags:    ;
  5349.     dd ?
  5350. DeletePSP    endp
  5351.  
  5352.  
  5353. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  5354. ;
  5355. ;Find a module with the right main EXPORT name. If it's not already resident
  5356. ;search for it on disk and load it if found.
  5357. ;
  5358. ;On Entry:
  5359. ;
  5360. ;ES:ESI    - Module name linear address (ES must address 0-4G)
  5361. ;
  5362. ;On Exit:
  5363. ;
  5364. ;Carry set on error & EAX is error code else,
  5365. ;
  5366. ;EDI    - Linear address of modules PSP.
  5367. ;
  5368. ;Error codes match cwLoad values.
  5369. ;
  5370. ;All other registers preserved.
  5371. ;
  5372. FindModule    proc    near
  5373.     pushm    ebx,ecx,edx,esi,ebp,ds,es
  5374.     assume ds:nothing
  5375.     mov    ds,cs:apiDDSeg
  5376.     assume ds:_apiCode
  5377.  
  5378. ;
  5379. ;Search resident modules first.
  5380. ;
  5381.     push    fs
  5382.     mov    fs,apiDSeg
  5383.     assume fs:_cwMain
  5384.     mov    edi,fs:BasePSPAddress    ;Point to start of PSP chain.
  5385.     assume fs:nothing
  5386.     pop    fs
  5387.     ;
  5388.     ;Skip partial path if there is one.
  5389.     ;
  5390.     push    esi
  5391.     movzx    ecx,es:b[esi]
  5392.     inc    esi
  5393.     mov    ebx,esi
  5394.     mov    ebp,ecx
  5395. @@5:    inc    esi
  5396.     cmp    es:b[esi-1],"\"
  5397.     jnz    @@6
  5398.     mov    ebx,esi
  5399.     mov    ebp,ecx
  5400. @@6:    dec    ecx
  5401.     jnz    @@5
  5402.     mov    esi,ebx
  5403.     ;
  5404. @@imp1:    mov    ebx,esi
  5405.     mov    edx,es:EPSP_Exports[edi]    ;Point to export memory.
  5406.     or    edx,edx        ;Any exports?
  5407.     jz    @@imp3
  5408.     mov    edx,es:[edx+4]    ;Point to module name.
  5409.     mov    ecx,ebp
  5410.     cmp    cl,es:[edx]        ;Right name length?
  5411.     jnz    @@imp3
  5412.     inc    edx
  5413. @@imp2:    mov    al,es:[ebx]
  5414.     cmp    al,es:[edx]        ;right char?
  5415.     jnz    @@imp3
  5416.     inc    ebx
  5417.     inc    edx
  5418.     dec    ecx
  5419.     jnz    @@imp2
  5420.     ;
  5421.     pop    esi
  5422.     jmp    @@imp5        ;got it!
  5423.     ;
  5424. @@imp3:    mov    edi,es:EPSP_NextPSP[edi]
  5425.     or    edi,edi        ;check there is something else to look at.
  5426.     jnz    @@imp1
  5427.     pop    esi
  5428. ;
  5429. ;Shit, not a resident module so look for it on disk.
  5430. ;
  5431. IFDEF DEBUG2
  5432.     push    eax
  5433.     push    ebx
  5434.     push    ecx
  5435.     push    edx
  5436.     push    ds
  5437.     push    cs
  5438.     pop    ds
  5439.     mov    edx,OFFSET debugaatext1
  5440. debugaaloop2:
  5441.     cmp    BYTE PTR ds:[edx],0
  5442.     je    debugaab
  5443.     mov    ecx,1
  5444.     mov    bx,1
  5445.     mov    ah,40h
  5446.     int    21h
  5447.     inc    edx
  5448.     jmp    debugaaloop2
  5449. debugaab:
  5450.     mov    edx,OFFSET debugaatext2
  5451.     push    cs
  5452.     pop    ds
  5453.     mov    ecx,2
  5454.     mov    bx,1
  5455.     mov    ah,40h
  5456.     int    21h
  5457.     pop    ds
  5458.     pop    edx
  5459.     pop    ecx
  5460.     pop    ebx
  5461.     pop    eax
  5462.     jmp    debugaaout
  5463.  
  5464. debugaatext1    DB    'Not a resident module...',0
  5465. debugaatext2    DB    13,10
  5466.  
  5467. debugaaout:
  5468. ENDIF
  5469.  
  5470. ;
  5471. ;Try current PSP's execution path.
  5472. ;
  5473.     push    esi
  5474.     push    es
  5475.     mov    es,apiDSeg
  5476.     assume es:_cwMain
  5477.     mov    es,es:PSPSegment
  5478.     assume es:nothing
  5479.     mov    bx,es:w[PSP_Environment]
  5480.     pop    es
  5481.     pushm    edx,ecx
  5482.     sys    GetSelDet32
  5483.     mov    esi,edx
  5484.     popm    edx,ecx
  5485. @@imp3_0:
  5486.     mov    al,es:[esi]        ;Get a byte.
  5487.     inc    esi        ;/
  5488.     or    al,al        ;End of a string?
  5489.     jnz    @@imp3_0        ;keep looking.
  5490.     mov    al,es:[esi]        ;Double zero?
  5491.     or    al,al        ;/
  5492.     jnz    @@imp3_0        ;keep looking.
  5493.     add    esi,3        ;Skip last 0 and word count.
  5494.     ;
  5495.     ;Copy up to last "\"
  5496.     ;
  5497.     mov    edi,offset DLLNameSpace
  5498.     mov    ebp,edi
  5499. @@imp3_1:    mov    al,es:[esi]
  5500.     inc    esi
  5501.     mov    [edi],al
  5502.     inc    edi
  5503.     cmp    al,"\"
  5504.     jnz    @@imp3_2
  5505.     mov    ebp,edi
  5506. @@imp3_2:    or    al,al
  5507.     jnz    @@imp3_1
  5508.     mov    edi,ebp
  5509.     pop    esi
  5510.  
  5511.     cmp    BYTE PTR es:[esi+2],':'    ; see if module name has absolute path
  5512.     jne    chkmodname
  5513.     cmp    BYTE PTR es:[esi],4
  5514.     jb    chkmodname        ; name not long enough for absolute path
  5515.     mov    edi,offset DLLNameSpace    ; reset DLL path to receive module name path only
  5516.  
  5517.     ;
  5518.     ;Check if module name has any path in it.
  5519.     ;
  5520. chkmodname:
  5521.     push    esi
  5522.     movzx    ecx,es:b[esi]
  5523.     inc    esi
  5524.     mov    ebp,esi
  5525. @@0:
  5526.     inc    esi
  5527.     cmp    es:b[esi-1],"\"
  5528.     jnz    @@1
  5529.     mov    ebp,esi
  5530. @@1:
  5531.     dec    ecx
  5532.     jnz    @@0
  5533.     mov    ecx,esi
  5534.     sub    ecx,ebp
  5535.     pop    esi
  5536.     push    esi
  5537.     inc    esi
  5538. @@2:
  5539.     cmp    esi,ebp
  5540.     jnc    @@3
  5541.     mov    al,es:[esi]
  5542.     mov    [edi],al
  5543.     inc    esi
  5544.     inc    edi
  5545.     jmp    @@2
  5546. @@3:
  5547.     mov    b[edi],0
  5548.     ;
  5549.     ;Copy module name into work space.
  5550.     ;
  5551.     mov    edi,offset MODNameSpace
  5552.     mov    [edi],cl
  5553.     inc    edi
  5554. @@4:
  5555.     mov    al,es:[esi]
  5556.     mov    [edi],al
  5557.     inc    esi
  5558.     inc    edi
  5559.     dec    ecx
  5560.     jnz    @@4
  5561.     pop    esi
  5562.     ;
  5563.     ;Try and find the module.
  5564.     ;
  5565.     push    es
  5566.     push    ds
  5567.     pop    es
  5568.     mov    esi,offset MODNameSpace
  5569.     mov    edi,offset DLLNameSpace
  5570.     call    SearchModule        ;look for module with right name.
  5571.     pop    es
  5572.     jnc    @@8
  5573. ;
  5574. ;Couldn't find the module so return an error.
  5575. ;
  5576.     mov    eax,1
  5577.     jmp    @@error
  5578. ;
  5579. ;Try loading the module found.
  5580. ;
  5581. @@8:
  5582.     push    ExecMCount
  5583.     mov    ExecMCount,ecx
  5584. ;
  5585. ;Set master PSP.
  5586. ;
  5587.     assume ds:nothing
  5588.     mov    ds,apiDSeg
  5589.     assume ds:_cwMain
  5590.     push    PSPSegment
  5591.     mov    bx,BasePSP
  5592.     mov    ah,50h
  5593.     int    21h
  5594. ;
  5595.     assume ds:nothing
  5596.     mov    ds,cs:apiDDSeg
  5597.     assume ds:_apiCode
  5598.     mov    edx,offset DLLNameSpace
  5599.     sys    cwLoad        ;call ourselves.
  5600. ;
  5601. ;Go back to origional PSP
  5602. ;
  5603.     assume ds:nothing
  5604.     mov    ds,cs:apiDSeg
  5605.     assume ds:_cwMain
  5606.     pop    PSPSegment
  5607.     assume ds:nothing
  5608.     mov    ds,cs:apiDDSeg
  5609.     assume ds:_apiCode
  5610.     pop    ExecMCount
  5611.     jc    @@error
  5612. ;
  5613.     mov    bx,si        ;get the PSP
  5614.     pushm    ecx,edx
  5615.     sys    GetSelDet32        ;need a 32-bit address for it.
  5616.     mov    edi,edx
  5617.     popm    ecx,edx
  5618. ;
  5619. ;Call DLL's initialisation code.
  5620. ;
  5621.     mov    es:w[edi+EPSP_EntryCSEIP+4],cx
  5622.     mov    es:d[edi+EPSP_EntryCSEIP],edx
  5623.     or    cx,cx
  5624.     jz    @@imp5
  5625.     xor    eax,eax
  5626.     mov    ax,es:w[edi+EPSP_EntryCSEIP+4]
  5627.     lar    eax,eax
  5628.     test    eax,00400000h
  5629.     jnz    @@imp6_0
  5630.     mov    es:w[edi+EPSP_EntryCSEIP+2],cx
  5631. @@imp6_0:    pushm    ds,es,fs,gs
  5632.     pushad
  5633.     push    es
  5634.     pop    fs
  5635.     mov    ds,si
  5636.     mov    es,si
  5637.     test    eax,00400000h
  5638.     mov    eax,0
  5639.     jnz    @@imp6
  5640.     db 66h
  5641. @@imp6:    call    fs:f[edi+EPSP_EntryCSEIP]
  5642.     or    ax,ax
  5643.     popad
  5644.     popm    ds,es,fs,gs
  5645.     mov    eax,1
  5646.     jnz    @@error
  5647. ;
  5648. ;Update modules referance count.
  5649. ;
  5650. @@imp5:    inc    es:EPSP_Links[edi]
  5651. ;
  5652. ;Return module PSP address to caller.
  5653. ;
  5654.     xor    eax,eax
  5655.     clc
  5656.     jmp    @@imp10
  5657. ;
  5658. ;Couldn't find name so return error to caller.
  5659. ;
  5660. @@error:    stc
  5661. ;
  5662. @@imp10:    popm    ebx,ecx,edx,esi,ebp,ds,es
  5663.     ret
  5664. ;
  5665. DLLNameSpace    db 256 dup (0)
  5666. MODNameSpace    db 256 dup (0)
  5667. FindModule    endp
  5668.  
  5669.  
  5670. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  5671. ;
  5672. ;Reverse the FindModule process.
  5673. ;
  5674. ;On Entry:
  5675. ;
  5676. ;ES:EDI    - module PSP (ES must address 0-4G)
  5677. ;
  5678. ;This basicly DEC's the modules referance count and if it becomes zero it
  5679. ;removes the module from memory.
  5680. ;
  5681. UnFindModule    proc    near
  5682.     pushm    ds,es,fs,gs
  5683.     pushad
  5684. ;
  5685.     dec    es:EPSP_Links[edi]
  5686.     jnz    @@8
  5687. ;
  5688. ;Get this PSP's selector.
  5689. ;
  5690.     mov    fs,es:EPSP_PSPSel[edi]
  5691. ;
  5692. ;Call DLL's exit code.
  5693. ;
  5694.     cmp    fs:w[EPSP_EntryCSEIP+4],0
  5695.     jz    @@imp5
  5696.     xor    eax,eax
  5697.     mov    ax,fs:w[EPSP_EntryCSEIP+4]
  5698.     lar    eax,eax
  5699.     pushm    ds,es,fs,gs
  5700.     pushad
  5701.     mov    ax,fs
  5702.     mov    ds,ax
  5703.     mov    es,ax
  5704.     test    eax,00400000h
  5705.     mov    eax,1
  5706.     jnz    @@imp6
  5707.     db 66h
  5708. @@imp6:    call    fs:f[EPSP_EntryCSEIP]
  5709.     or    ax,ax
  5710.     popad
  5711.     popm    ds,es,fs,gs
  5712. ;
  5713. ;Switch to the master PSP.
  5714. ;
  5715. @@imp5:    assume ds:nothing
  5716.     mov    ds,apiDSeg
  5717.     assume ds:_cwMain
  5718.     push    PSPSegment
  5719.     mov    bx,BasePSP
  5720.     mov    ah,50h
  5721.     int    21h
  5722. ;
  5723. ;Release module.
  5724. ;
  5725.     mov    bx,fs
  5726.     sys    RelSel
  5727. ;
  5728. ;Go back to origional PSP
  5729. ;
  5730.     pop    PSPSegment
  5731.     assume ds:_apiCode
  5732. ;
  5733. @@8:    clc
  5734.     popad
  5735.     popm    ds,es,fs,gs
  5736.     ret
  5737. UnFindModule    endp
  5738.  
  5739.  
  5740. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  5741. ;
  5742. ;Search specified path for a file with the right module name.
  5743. ;
  5744. ;On Entry:
  5745. ;
  5746. ;DS:EDI    - path string.
  5747. ;ES:ESI    - module name.
  5748. ;
  5749. ;On Exit:
  5750. ;
  5751. ;Carry set on error else,
  5752. ;
  5753. ;Path string specified in DS:EDI has file name appended to it.
  5754. ;
  5755. ;ECX    - module number within file.
  5756. ;
  5757. SearchModule    proc    near
  5758.     mov    ax,ds
  5759.     pushm    ds,es
  5760.     pushad
  5761.     assume ds:nothing
  5762.     mov    ds,cs:apiDDSeg
  5763.     assume ds:_apiCode
  5764.     mov    d[@@Path],edi
  5765.     mov    w[@@Path+4],ax
  5766.     mov    d[@@Name],esi
  5767.     mov    w[@@Name+4],es
  5768.  
  5769. ; MED 01/05/96
  5770.     push    eax
  5771.     push    es
  5772.     mov    ah,2fh    ; get DTA in es:ebx
  5773.     int    21h
  5774.     mov    DWORD PTR EntryDTAAddress,ebx
  5775.     mov    WORD PTR EntryDTAAddress+4,es
  5776.     pop    es
  5777.  
  5778.     mov    edx,OFFSET TemporaryDTA
  5779.     mov    ah,1ah    ; set DTA in ds:edx
  5780.     int    21h
  5781.     pop    eax
  5782.  
  5783. ;
  5784. ;Get path length so we don't have to keep scanning the string.
  5785. ;
  5786.     push    ds
  5787.     mov    ds,ax
  5788.     xor    ecx,ecx
  5789. @@0:    cmp    b[edi],0
  5790.     jz    @@1
  5791.     inc    edi
  5792.     inc    ecx
  5793.     jmp    @@0
  5794. @@1:    pop    ds
  5795.     mov    d[@@Length],ecx
  5796. ;
  5797. ;Setup initial mask pointer.
  5798. ;
  5799.     mov    d[@@Mask],offset @@Masks
  5800. ;
  5801. ;Get DTA address.
  5802. ;
  5803.     push    es
  5804.     mov    ah,2fh
  5805.     int    21h
  5806.     mov    d[@@Dta],ebx
  5807.     mov    w[@@Dta+4],es
  5808.     pop    es
  5809. ;
  5810. ;Work through all mask types.
  5811. ;
  5812. @@2:    mov    esi,d[@@Mask]
  5813.     cmp    b[esi],0        ;end of the list?
  5814.     jz    @@9
  5815. ;
  5816. ;Add new mask to path string.
  5817. ;
  5818.     add    d[@@Mask],4        ;move to next mask.
  5819.     les    edi,f[@@Path]
  5820.     add    edi,d[@@Length]    ;point to end of path string.
  5821.     mov    es:b[edi],"*"
  5822.     inc    edi
  5823.     movsd            ;copy extension.
  5824.     mov    es:b[edi],0
  5825. ;
  5826. ;Work through all files with the right extension.
  5827. ;
  5828.     push    ds
  5829.     lds    edx,f[@@Path]
  5830.     xor    cx,cx
  5831.     mov    ah,4eh        ;find first file
  5832.     int    21h
  5833.     pop    ds
  5834.     jc    @@2
  5835.     jmp    @@4
  5836. ;
  5837. @@3:    mov    ah,4fh
  5838.     int    21h
  5839.     jc    @@2
  5840. ;
  5841. ;Add this name to the path string?
  5842. ;
  5843. @@4:    les    edi,f[@@DTA]
  5844.     test    es:b[edi+21],16    ;DIR?
  5845.     jnz    @@3
  5846.     push    ds
  5847.     mov    eax,d[@@Length]    ;point to end of path string.
  5848.     lds    esi,f[@@Path]
  5849.     add    esi,eax
  5850.     lea    edi,[edi+1eh]    ;point to file name.
  5851.     mov    ecx,13
  5852.     cld
  5853. @@5:    mov    al,es:[edi]
  5854.     mov    [esi],al
  5855.     inc    esi
  5856.     inc    edi
  5857.     or    al,al
  5858.     jz    @@6
  5859.     dec    ecx
  5860.     jnz    @@5
  5861. @@6:    mov    b[esi],0        ;terminate the name.
  5862.     pop    ds
  5863. ;
  5864. ;Find out what the files "module" name is.
  5865. ;
  5866.     ;
  5867.     ;Open the file.
  5868.     ;
  5869.     push    ds
  5870.     lds    edx,f[@@Path]
  5871.     mov    ax,3d00h
  5872.     int    21h
  5873.     pop    ds
  5874.     jc    @@7
  5875.     mov    w[@@Handle],ax
  5876.     mov    bx,ax
  5877.     mov    d[@@Count],0
  5878.     ;
  5879. @@11:    ;See what sort of file it is.
  5880.     ;
  5881.     mov    edx,offset @@ID
  5882.     mov    ecx,2
  5883.     mov    ah,3fh
  5884.     int    21h
  5885.     jc    @@7
  5886.     cmp    ax,cx
  5887.     jnz    @@7
  5888.     cmp    w[@@ID],"ZM"
  5889.     jz    @@MZ
  5890.     cmp    w[@@ID],"P3"
  5891.     jz    @@3P
  5892.     jmp    @@7
  5893. ;
  5894. ;Process an MZ section.
  5895. ;
  5896. @@MZ:    mov    edx,offset @@ID+2
  5897.     mov    ecx,1bh-2
  5898.     mov    ah,3fh
  5899.     int    21h
  5900.     jc    @@7
  5901.     cmp    ax,cx
  5902.     jnz    @@7
  5903.     cmp    w[@@ID+18h],40h
  5904.     jz    @@LE
  5905.     ;
  5906.     ;Find out how long the MZ bit is.
  5907.     ;
  5908.     mov    ax,w[@@ID+2+2]    ;get length in 512 byte blocks
  5909.  
  5910. ; MED 04/26/96
  5911.     cmp    WORD PTR [@@ID+2],0
  5912.     je    medexe4    ; not rounded if no modulo
  5913.  
  5914.     dec    ax        ;lose 1 cos its rounded up
  5915.  
  5916. medexe4:
  5917.     add    ax,ax        ;mult by 2
  5918.     mov    dh,0
  5919.     mov    dl,ah
  5920.     mov    ah,al
  5921.     mov    al,dh        ;mult by 256=*512
  5922.     add    ax,w[@@ID+2]        ;add length mod 512
  5923.     adc    dx,0        ;add any carry to dx
  5924.     mov    cx,ax
  5925.     sub    cx,1bh        ;account for the header.
  5926.     sbb    dx,0
  5927.     xchg    cx,dx        ;swap round for DOS.
  5928.     mov    ax,4201h        ;set new file offset.
  5929.     int    21h
  5930.     jmp    @@11
  5931. ;
  5932. ;Process what should be an LE section.
  5933. ;
  5934. @@LE:    mov    ecx,3ch
  5935.     mov    dx,cx
  5936.     shr    ecx,16
  5937.     mov    ax,4200h
  5938.     int    21h        ;move to LE offset.
  5939.     mov    edx,offset @@ID
  5940.     mov    ecx,4
  5941.     mov    ah,3fh
  5942.     int    21h        ;read LE offset.
  5943.     jc    @@7
  5944.     cmp    ax,4
  5945.     jnz    @@7
  5946.     cmp    d[@@ID],0
  5947.     jz    @@7
  5948.     mov    ecx,d[@@ID]
  5949.     mov    dx,cx
  5950.     shr    ecx,16
  5951.     mov    ax,4200h
  5952.     int    21h        ;point to LE section.
  5953.     mov    edx,offset @@ID+4
  5954.     mov    ah,3fh
  5955.     mov    ecx,2
  5956.     int    21h        ;read ID string.
  5957.     jc    @@7
  5958.     cmp    ax,2
  5959.     jnz    @@7
  5960.  
  5961.     cmp    w[@@ID+4],"EL"
  5962.     jz    medle1
  5963.  
  5964. IFDEF LXWORK
  5965.     mov    eax,DWORD PTR [@@ID+4]
  5966.     mov    cs:[0],al
  5967.     cmp    w[@@ID+4],"XL"    ; MED
  5968.     jnz    @@7
  5969.     mov    cs:[0],bl
  5970. ENDIF
  5971.     jmp    @@7
  5972.  
  5973.     ;
  5974.     ;Process an LE section.
  5975.     ;
  5976. medle1:
  5977.     mov    ecx,LE_ResidentNames-2
  5978.     mov    dx,cx
  5979.     shr    ecx,16
  5980.     mov    ax,4201h
  5981.     int    21h        ;move to module name offset.
  5982.     mov    edx,offset @@ID+4
  5983.     mov    ecx,4
  5984.     mov    ah,3fh
  5985.     int    21h        ;read module name offset.
  5986.     jc    @@7
  5987.     cmp    ax,4
  5988.     jnz    @@7
  5989.     mov    ecx,d[@@ID]
  5990.     add    ecx,d[@@ID+4]
  5991.     mov    dx,cx
  5992.     shr    ecx,16
  5993.     mov    ax,4200h
  5994.     int    21h        ;move to module name.
  5995.     mov    edx,offset @@ID
  5996.     mov    ecx,256
  5997.     mov    ah,3fh
  5998.     int    21h        ;read the module name.
  5999.     ;
  6000.     ;See if this module has right name.
  6001.     ;
  6002.     push    es
  6003.     les    edx,f[@@Name]    ;point to name we're looking for.
  6004.     mov    edi,offset @@ID
  6005.     movzx    ecx,b[edi]
  6006.     cmp    cl,es:[edx]        ;right length?
  6007.     jnz    @@le7
  6008. @@le5:    inc    edx
  6009.     inc    edi
  6010.     mov    al,es:[edx]
  6011.     cmp    al,[edi]
  6012.     jnz    @@le7
  6013.     dec    ecx
  6014.     jnz    @@le5
  6015.     pop    es
  6016.     ;
  6017.     ;Close the file.
  6018.     ;
  6019.     xor    bx,bx
  6020.     xchg    bx,w[@@Handle]
  6021.     mov    ah,3eh
  6022.     int    21h
  6023.     jmp    @@8
  6024.     ;
  6025. @@le7:    pop    es
  6026.     jmp    @@7
  6027. ;
  6028. ;Process a 3P section.
  6029. ;
  6030. @@3P:    mov    edx,offset @@ID+2
  6031.     mov    ecx,size NewHeaderStruc-2
  6032.     mov    ah,3fh
  6033.     int    21h
  6034.     jc    @@7
  6035.     cmp    ax,cx
  6036.     jnz    @@7
  6037.     sub    d[NewSize+@@ID],size NewHeaderStruc
  6038.     ;
  6039.     ;Check this file has exports.
  6040.     ;
  6041.     cmp    d[NewExports+@@ID],0
  6042.     jz    @@3p6
  6043.     ;
  6044.     ;Skip segment definitions.
  6045.     ;
  6046.     movzx    edx,w[NewSegments+@@ID]
  6047.     shl    edx,3
  6048.     sys    cwcInfo
  6049.     jc    @@3p0
  6050.     mov    edx,eax
  6051. @@3p0:    sub    d[NewSize+@@ID],edx
  6052.     mov    cx,dx
  6053.     shr    edx,16
  6054.     xchg    cx,dx
  6055.     mov    ax,4201h
  6056.     int    21h
  6057.     ;
  6058.     ;Skip relocations.
  6059.     ;
  6060.     mov    edx,d[NewRelocs+@@ID]
  6061.     shl    edx,2
  6062.     or    edx,edx
  6063.     jz    @@3p1
  6064.     sys    cwcInfo
  6065.     jc    @@3p1
  6066.     mov    edx,eax
  6067. @@3p1:    sub    d[NewSize+@@ID],edx
  6068.     mov    cx,dx
  6069.     shr    edx,16
  6070.     xchg    cx,dx
  6071.     mov    ax,4201h
  6072.     int    21h
  6073.     ;
  6074.     ;Load export details.
  6075.     ;
  6076.     mov    ecx,d[NewExports+@@ID]
  6077.     sys    GetMemLinear32
  6078.     jc    @@7        ;treat memory error as no file.
  6079.     mov    edx,ecx
  6080.     push    ds
  6081.     mov    ds,apiDSeg
  6082.     assume ds:_cwMain
  6083.     mov    ds,RealSegment
  6084.     assume ds:_apiCode
  6085.     sys    cwcInfo
  6086.     jc    @@3p2
  6087.  
  6088.     push    ds
  6089.     assume ds:nothing
  6090.     mov    ds,cs:apiDDSeg
  6091.     assume ds:_apiCode
  6092.     sub    d[NewSize+@@ID],ecx
  6093.     pop    ds
  6094.  
  6095.     push    es
  6096.     mov    ax,ds
  6097.     mov    es,ax
  6098.     mov    edi,esi
  6099.     sys    cwcLoad
  6100.     pop    es
  6101.     jc    @@3p3
  6102.     jmp    @@3p4
  6103.  
  6104. @@3p2:    push    ds
  6105.     assume ds:nothing
  6106.     mov    ds,cs:apiDDSeg
  6107.     assume ds:_apiCode
  6108.     sub    d[NewSize+@@ID],edx
  6109.     pop    ds
  6110.  
  6111.     mov    ecx,edx
  6112.     mov    edx,esi
  6113.     call    ReadFile
  6114.     jc    @@3p3
  6115.     cmp    eax,ecx
  6116.     jz    @@3p4
  6117. @@3p3:    pop    ds
  6118.     sys    RelMemLinear32
  6119.     jmp    @@7
  6120. @@3p4:    mov    ax,ds
  6121.     mov    es,ax
  6122.     pop    ds
  6123.     ;
  6124.     ;See if this module has right name.
  6125.     ;
  6126.     push    ds
  6127.     lds    edx,f[@@Name]    ;point to name we're looking for.
  6128.     mov    edi,esi
  6129.     add    edi,es:[edi+4]    ;get offset of module name.
  6130.     movzx    ecx,es:b[edi]
  6131.     cmp    cl,[edx]        ;right length?
  6132.     jnz    @@3p7
  6133. @@3p5:    inc    edx
  6134.     inc    edi
  6135.     mov    al,[edx]
  6136.     cmp    al,es:[edi]
  6137.     jnz    @@3p7
  6138.     dec    ecx
  6139.     jnz    @@3p5
  6140.     pop    ds
  6141.     ;
  6142.     ;Release EXPORT record memory.
  6143.     ;
  6144.     sys    RelMemLinear32
  6145.     ;
  6146.     ;Close the file.
  6147.     ;
  6148.     xor    bx,bx
  6149.     xchg    bx,w[@@Handle]
  6150.     mov    ah,3eh
  6151.     int    21h
  6152.     jmp    @@8
  6153. ;
  6154. ;Not this one, move to next part of the file.
  6155. ;
  6156. @@3p7:    pop    ds
  6157.     sys    RelMemLinear32
  6158. @@3p6:    mov    edx,d[NewSize+@@ID]
  6159.     mov    cx,dx
  6160.     shr    edx,16
  6161.     xchg    cx,dx
  6162.     mov    ax,4201h
  6163.     int    21h
  6164.     inc    d[@@Count]
  6165.     jmp    @@11
  6166. ;
  6167. ;Make sure file is closed.
  6168. ;
  6169. @@7:    xor    bx,bx
  6170.     xchg    bx,w[@@Handle]
  6171.     or    bx,bx
  6172.     jz    @@3
  6173.     mov    ah,3eh
  6174.     int    21h
  6175.     jmp    @@3
  6176. ;
  6177. @@8:    clc
  6178.     jmp    @@10
  6179. ;
  6180. @@9:    stc
  6181. ;
  6182. @@10:
  6183.  
  6184. ; MED 01/05/96
  6185.     pushf
  6186.     push    ds
  6187.     lds    edx,EntryDTAAddress
  6188.     mov    ah,1ah    ; set DTA in ds:edx
  6189.     int    21h
  6190.     pop    ds
  6191.     popf
  6192.  
  6193.     popad
  6194.     mov    ecx,d[@@Count]
  6195.     popm    ds,es
  6196.     ret
  6197. ;
  6198. @@ID:    ;
  6199.     db 256 dup (0)
  6200. @@Handle:    ;
  6201.     dw 0
  6202. @@DTA:    ;
  6203.     df 0
  6204. @@Path:    ;
  6205.     df 0
  6206. @@Name:    ;
  6207.     df 0
  6208. @@Length:    ;
  6209.     dd 0
  6210. @@Count:    ;
  6211.     dd 0
  6212. @@Mask:    ;
  6213.     dd 0
  6214. @@Masks:    ;
  6215.     db ".DLL"
  6216.     db ".EXE"
  6217.     db 0
  6218. ; temporary DTA storage so PSP isn't munged, MED 01/03/96
  6219. TemporaryDTA    DB    80h DUP (?)
  6220. EntryDTAAddress    DF    0    ; Entry DTA address
  6221. SearchModule    endp
  6222.  
  6223.  
  6224. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  6225. ;
  6226. ;Search a modules export table for name specified.
  6227. ;
  6228. ;On Entry:
  6229. ;
  6230. ;ES:EDI    - Export table.
  6231. ;ES:EBP    - function name.
  6232. ;
  6233. ;On Exit:
  6234. ;
  6235. ;Carry set on error else,
  6236. ;
  6237. ;ES:EDI    - matched export entry.
  6238. ;
  6239. ;All other registers preserved.
  6240. ;
  6241. FindFunction    proc    near
  6242. IFDEF DEBUG2
  6243.     push    eax
  6244.     push    ebx
  6245.     push    ecx
  6246.     push    edx
  6247.     push    ds
  6248.     push    cs
  6249.     pop    ds
  6250.     mov    edx,OFFSET debugamtext1
  6251. debugamloop2:
  6252.     cmp    BYTE PTR ds:[edx],0
  6253.     je    debugamb
  6254.     mov    ecx,1
  6255.     mov    bx,1
  6256.     mov    ah,40h
  6257.     int    21h
  6258.     inc    edx
  6259.     jmp    debugamloop2
  6260. debugamb:
  6261.     mov    edx,OFFSET debugamtext2
  6262.     push    cs
  6263.     pop    ds
  6264.     mov    ecx,2
  6265.     mov    bx,1
  6266.     mov    ah,40h
  6267.     int    21h
  6268.     pop    ds
  6269.     pop    edx
  6270.     pop    ecx
  6271.     pop    ebx
  6272.     pop    eax
  6273.     jmp    debugamout
  6274.  
  6275. debugamtext1    DB    'Entering FindFunction...',0
  6276. debugamtext2    DB    13,10
  6277.  
  6278. debugamout:
  6279. ENDIF
  6280.  
  6281.     pushm    eax,ebx,ecx,edx,esi,ebp
  6282.     ;
  6283.     mov    edx,es:[edi]        ;get number of exports.
  6284.     add    edi,4+4        ;skip entry count and module name.
  6285.     ;
  6286. @@imp11:    push    edi
  6287.     mov    edi,es:[edi]        ;point to name string.
  6288.     mov    ebx,ebp
  6289.     xor    ecx,ecx
  6290.     mov    cl,es:[edi+6]
  6291.     cmp    cl,es:[ebx]
  6292.     jnz    @@imp13
  6293.     add    edi,6+1
  6294.  
  6295. COMMENT !
  6296. IFDEF DEBUG2
  6297.     push    eax
  6298.     push    ebx
  6299.     push    ecx
  6300.     push    edx
  6301.     push    edi
  6302.     push    ds
  6303.     push    cs
  6304.     pop    ds
  6305.     mov    edx,OFFSET debugaktext1
  6306.     push    cx
  6307. debugakloop2:
  6308.     cmp    BYTE PTR ds:[edx],0
  6309.     je    debugakb
  6310.     mov    ecx,1
  6311.     mov    bx,1
  6312.     mov    ah,40h
  6313.     int    21h
  6314.     inc    edx
  6315.     jmp    debugakloop2
  6316. debugakb:
  6317.     pop    cx
  6318.     push    es
  6319.     pop    ds
  6320. debugakloop1:
  6321.     mov    edx,edi
  6322.     mov    bx,1
  6323.     mov    ah,40h
  6324.     int    21h
  6325. debugaka:
  6326.     mov    edx,OFFSET debugaktext2
  6327.     push    cs
  6328.     pop    ds
  6329.     mov    ecx,2
  6330.     mov    bx,1
  6331.     mov    ah,40h
  6332.     int    21h
  6333.     pop    ds
  6334.     pop    edi
  6335.     pop    edx
  6336.     pop    ecx
  6337.     pop    ebx
  6338.     pop    eax
  6339.     jmp    debugakout
  6340.  
  6341. debugaktext1    DB    'Checking against function: ',0
  6342. debugaktext2    DB    13,10
  6343.  
  6344. debugakout:
  6345. ENDIF
  6346. END COMMENT !
  6347.  
  6348.     inc    ebx
  6349.     ;
  6350. @@imp12:    mov    al,es:[edi]
  6351.     cmp    al,es:[ebx]
  6352.     jnz    @@imp13
  6353.     inc    edi
  6354.     inc    ebx
  6355.     dec    ecx
  6356.     jnz    @@imp12
  6357.     jmp    @@imp14
  6358.     ;
  6359. @@imp13:    pop    edi
  6360.     add    edi,4
  6361.     dec    edx
  6362.     jnz    @@imp11
  6363.     jmp    @@error
  6364.     ;
  6365. @@imp14:    pop    edi
  6366.     mov    edi,es:[edi]
  6367.     clc
  6368.     jmp    @@10
  6369.     ;
  6370. @@error:    stc
  6371. @@10:    popm    eax,ebx,ecx,edx,esi,ebp
  6372. IFDEF DEBUG2
  6373.     push    eax
  6374.     push    ebx
  6375.     push    ecx
  6376.     push    edx
  6377.     push    ds
  6378.     push    cs
  6379.     pop    ds
  6380.     mov    edx,OFFSET debugaltext1
  6381. debugalloop2:
  6382.     cmp    BYTE PTR ds:[edx],0
  6383.     je    debugalb
  6384.     mov    ecx,1
  6385.     mov    bx,1
  6386.     mov    ah,40h
  6387.     int    21h
  6388.     inc    edx
  6389.     jmp    debugalloop2
  6390. debugalb:
  6391.     mov    edx,OFFSET debugaltext2
  6392.     push    cs
  6393.     pop    ds
  6394.     mov    ecx,2
  6395.     mov    bx,1
  6396.     mov    ah,40h
  6397.     int    21h
  6398.     pop    ds
  6399.     pop    edx
  6400.     pop    ecx
  6401.     pop    ebx
  6402.     pop    eax
  6403.     jmp    debugalout
  6404.  
  6405. debugaltext1    DB    'Done with FindFunction...',0
  6406. debugaltext2    DB    13,10
  6407.  
  6408. debugalout:
  6409. ENDIF
  6410.  
  6411.     ret
  6412. FindFunction    endp
  6413.  
  6414.  
  6415. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  6416. ;
  6417. ;Load, relocate and execute the application code. All format loader.
  6418. ;
  6419. ;On Entry:
  6420. ;
  6421. ;EBX    - Mode.
  6422. ;    0 - Normal EXEC.
  6423. ;    1 - Load for debug.
  6424. ;    2 - Load for overlay.
  6425. ;DS:EDX    - File name.
  6426. ;ES:ESI    - Command line.
  6427. ;CX    - Environment selector, 0 to use existing copy.
  6428. ;
  6429. ;On Exit:
  6430. ;
  6431. ;Carry set on error and AX = error code else,
  6432. ;
  6433. ;If Mode=0
  6434. ;
  6435. ;AL = ErrorLevel (returned by child's terminate)
  6436. ;
  6437. ;If Mode=1
  6438. ;
  6439. ;CX:EDX    - Entry CS:EIP
  6440. ;BX:EAX    - Entry SS:ESP
  6441. ;SI    - PSP.
  6442. ;DI    - Auto DS.
  6443. ;EBP    - Segment definition memory.
  6444. ;
  6445. ;If Mode=2
  6446. ;
  6447. ;CX:EDX    - Entry CS:EIP
  6448. ;BX:EAX    - Entry SS:ESP
  6449. ;SI    - PSP.
  6450. ;
  6451. ;Error codes:
  6452. ;
  6453. ;1    - DOS file access error.
  6454. ;2    - Not a recognisable format.
  6455. ;3    - Not enough memory.
  6456. ;
  6457. _Exec    proc    near
  6458.     mov    ax,ds
  6459.     push    ds
  6460.     assume ds:nothing
  6461.     mov    ds,cs:apiDDSeg
  6462.     assume ds:_apiCode
  6463.     call    DPMICopyCheck
  6464. ;
  6465. ;Preserve details.
  6466. ;
  6467.     mov    d[@@Name],edx
  6468.     mov    w[@@Name+4],ax
  6469.     mov    d[@@Flags],ebx
  6470.     mov    d[@@Command],esi
  6471.     mov    w[@@Command+4],es
  6472.     mov    w[@@Environment],cx
  6473.     mov    w[@@Handle],0
  6474. ;
  6475. ;Try and open the file.
  6476. ;
  6477.     push    ds
  6478.     lds    edx,f[@@Name]
  6479.     mov    ax,3d00h        ;open, read only.
  6480.     int    21h
  6481.     pop    ds
  6482.     jc    @@no_file_error
  6483.     mov    w[@@Handle],ax    ;store the handle.
  6484. ;
  6485. ;Find out what format the current section is.
  6486. ;
  6487. @@0:    mov    bx,w[@@Handle]
  6488.     mov    edx,offset @@Temp
  6489.     mov    ecx,2
  6490.     mov    ah,3fh
  6491.     int    21h
  6492.     jc    @@file_error
  6493.     cmp    ax,cx
  6494.     jnz    @@file_error
  6495.     ;
  6496.     cmp    w[@@Temp],"ZM"    ;MZ EXE?
  6497.     jz    @@MZ
  6498.     cmp    w[@@Temp],"EL"    ;LE EXE?
  6499.     jz    @@LE
  6500.     cmp    w[@@Temp],"P3"    ;3P EXE?
  6501.     jz    @@3P
  6502.  
  6503. IFDEF LXWORK
  6504.     cmp    w[@@Temp],"XL"    ;LX EXE? -- MED
  6505.     jz    @@LE
  6506.     mov    cs:[0],dl
  6507. ENDIF
  6508.  
  6509.     jmp    @@file_error
  6510.     ;
  6511. @@MZ:    ;Look for an LE offset.
  6512.     ;
  6513.     mov    bx,w[@@Handle]
  6514.     mov    dx,18h
  6515.     xor    cx,cx
  6516.     mov    ax,4200h
  6517.     int    21h
  6518.     mov    edx,offset @@Temp
  6519.     mov    ecx,2
  6520.     mov    ah,3fh
  6521.     int    21h        ;Fetch LE offset.
  6522.     jc    @@file_error
  6523.     cmp    ax,cx
  6524.     jnz    @@file_error
  6525.     cmp    w[@@Temp],40h    ;LE offset present?
  6526.     jnz    @@MZ2
  6527.     ;
  6528.     ;Fetch the NE/LE/LX offset.
  6529.     ;
  6530.     mov    bx,w[@@Handle]
  6531.     mov    dx,3ch
  6532.     xor    cx,cx
  6533.     mov    ax,4200h
  6534.     int    21h
  6535.     mov    edx,offset @@Temp
  6536.     mov    ecx,4
  6537.     mov    ah,3fh
  6538.     int    21h        ;Fetch LE offset.
  6539.     jc    @@file_error
  6540.     cmp    ax,cx
  6541.     jnz    @@file_error
  6542.     cmp    d[@@Temp],0        ;any offset?
  6543.     jz    @@MZ2
  6544.     mov    eax,d[@@Temp]
  6545.     mov    dx,ax
  6546.     shr    eax,16
  6547.     mov    cx,ax
  6548.     mov    bx,w[@@Handle]
  6549.     mov    ax,4200h
  6550.     int    21h
  6551.     jmp    @@0
  6552.     ;
  6553. @@MZ2:    ;Get MZ length and skip it.
  6554.     ;
  6555.     mov    dx,2
  6556.     xor    cx,cx
  6557.     mov    ax,4200h
  6558.     mov    bx,w[@@Handle]
  6559.     int    21h
  6560.     mov    edx,offset @@Temp
  6561.     mov    ecx,4
  6562.     mov    ah,3fh
  6563.     mov    bx,w[@@Handle]
  6564.     int    21h
  6565.     jc    @@file_error
  6566.     cmp    ax,cx
  6567.     jnz    @@file_error
  6568.     mov    ax,w[@@Temp+2]    ;get length in 512 byte blocks
  6569.  
  6570. ; MED 04/26/96
  6571.     cmp    WORD PTR [@@Temp],0
  6572.     je    medexe5    ; not rounded if no modulo
  6573.  
  6574.     dec    ax        ;lose 1 cos its rounded up
  6575.  
  6576. medexe5:
  6577.     add    ax,ax        ;mult by 2
  6578.     mov    dh,0
  6579.     mov    dl,ah
  6580.     mov    ah,al
  6581.     mov    al,dh        ;mult by 256=*512
  6582.     add    ax,w[@@Temp]        ;add length mod 512
  6583.     adc    dx,0        ;add any carry to dx
  6584.     mov    cx,ax
  6585.     xchg    cx,dx        ;swap round for DOS.
  6586.     mov    ax,4200h        ;set absolute position.
  6587.     mov    bx,w[@@Handle]
  6588.     int    21h
  6589.     jmp    @@0
  6590. ;
  6591. ;Run an LE format program.
  6592. ;
  6593. @@LE:    mov    d[@@ExecAdd],offset LoadLE
  6594.     jmp    @@exec
  6595. ;
  6596. ;Run a 3P format program.
  6597. ;
  6598. @@3P:    mov    d[@@ExecAdd],offset Load3P
  6599. ;
  6600. ;Close the file.
  6601. ;
  6602. @@exec:    mov    bx,w[@@Handle]
  6603.     mov    w[@@Handle],0
  6604.     mov    ah,3eh
  6605.     int    21h
  6606. ;
  6607. ;Fetch registers & call format specific loader.
  6608. ;
  6609.     mov    edx,d[@@Name]
  6610.     mov    ax,w[@@Name+4]
  6611.     mov    ebx,d[@@Flags]
  6612.     mov    esi,d[@@Command]
  6613.     mov    es,w[@@Command+4]
  6614.     mov    cx,w[@@Environment]
  6615.     mov    ds,ax
  6616.     assume ds:nothing
  6617.     call    cs:d[@@ExecAdd]
  6618.  
  6619.     mov    ds,cs:apiDDSeg
  6620.     assume ds:_apiCode
  6621. ;
  6622. @@exit:    pushf
  6623.     push    eax
  6624.     cmp    w[@@Handle],0
  6625.     jz    @@e0
  6626.     mov    bx,w[@@Handle]
  6627.     mov    ah,3eh
  6628.     int    21h
  6629. @@e0:    pop    eax
  6630.     popf
  6631. ;
  6632.     pop    ds
  6633.  
  6634. IFDEF DEBUG2
  6635.     push    eax
  6636.     push    ebx
  6637.     push    ecx
  6638.     push    edx
  6639.     push    ds
  6640.     push    cs
  6641.     pop    ds
  6642.     mov    edx,OFFSET debugajtext1
  6643. debugajloop2:
  6644.     cmp    BYTE PTR ds:[edx],0
  6645.     je    debugajb
  6646.     mov    ecx,1
  6647.     mov    bx,1
  6648.     mov    ah,40h
  6649.     int    21h
  6650.     inc    edx
  6651.     jmp    debugajloop2
  6652. debugajb:
  6653.     mov    edx,OFFSET debugajtext2
  6654.     push    cs
  6655.     pop    ds
  6656.     mov    ecx,2
  6657.     mov    bx,1
  6658.     mov    ah,40h
  6659.     int    21h
  6660.     pop    ds
  6661.     pop    edx
  6662.     pop    ecx
  6663.     pop    ebx
  6664.     pop    eax
  6665.     jmp    debugajout
  6666.  
  6667. debugajtext1    DB    'Done with _Exec...',0
  6668. debugajtext2    DB    13,10
  6669.  
  6670. debugajout:
  6671. ENDIF
  6672.  
  6673.     ret
  6674. ;
  6675. @@no_file_error: mov    eax,1
  6676.     stc
  6677.     jmp    @@exit
  6678. @@file_error:    mov    eax,2
  6679.     stc
  6680.     jmp    @@exit
  6681. @@mem_error:    mov    eax,3
  6682.     stc
  6683.     jmp    @@exit
  6684. ;
  6685. @@Name:    ;
  6686.     df 0
  6687. @@Flags:    ;
  6688.     dd 0
  6689. @@Command:    ;
  6690.     df 0
  6691. @@Environment:    ;
  6692.     dw 0
  6693. @@Handle:    ;
  6694.     dw 0
  6695. @@Temp:    ;
  6696.     dd 0
  6697. @@ExecAdd:    ;
  6698.     dd 0
  6699. _Exec    endp
  6700.  
  6701.  
  6702. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  6703. ;
  6704. ;Load, relocate and execute the application code. 3P format loader.
  6705. ;
  6706. ;On Entry:
  6707. ;
  6708. ;EBX    - Mode.
  6709. ;    0 - Normal EXEC.
  6710. ;    1 - Load for debug.
  6711. ;    2 - Load for overlay.
  6712. ;DS:EDX    - File name.
  6713. ;ES:ESI    - Command line.
  6714. ;CX    - Environment selector, 0 to use existing copy.
  6715. ;
  6716. ;On Exit:
  6717. ;
  6718. ;Carry set on error and AX = error code else,
  6719. ;
  6720. ;If Mode=0
  6721. ;
  6722. ;AL = ErrorLevel (returned by child's terminate)
  6723. ;
  6724. ;If Mode=1
  6725. ;
  6726. ;CX:EDX    - Entry CS:EIP
  6727. ;BX:EAX    - Entry SS:ESP
  6728. ;SI    - PSP.
  6729. ;DI    - Auto DS.
  6730. ;EBP    - Segment definition memory.
  6731. ;
  6732. ;If Mode=2
  6733. ;
  6734. ;CX:EDX    - Entry CS:EIP
  6735. ;BX:EAX    - Entry SS:ESP
  6736. ;SI    - PSP.
  6737. ;
  6738. ;Error codes:
  6739. ;
  6740. ;1    - DOS file access error.
  6741. ;2    - Not a 3P file.
  6742. ;3    - Not enough memory.
  6743. ;
  6744. Load3P    proc    near
  6745.     mov    ax,ds
  6746.     pushm    ds,es,fs,gs
  6747.     assume ds:nothing
  6748.     mov    ds,cs:apiDDSeg
  6749.     assume ds:_apiCode
  6750.     ;
  6751.     pushm    w[@@SegSS],d[@@SegMem],w[@@EntryDS]
  6752.     pushm    d[@@ExpMem],d[@@EntryEIP],w[@@SegCS],d[@@EntryESP]
  6753.     pushm    d[@@SegMem],d[@@RelocMem],d[@@ProgBase],d[@@Segs],w[@@PSP]
  6754.     pushm    d[@@AutoOffset],d[@@Command],w[@@Command+4],d[@@Flags]
  6755.     pushm    d[@@Name],w[@@Name+4],w[@@Environment],d[@@SystemFlags]
  6756.     pushm    d[@@ModLink],d[@@ImpMem],d[@@ImpCnt],d[@@3PStart]
  6757.     ;
  6758.     mov    d[@@Name],edx
  6759.     mov    w[@@Name+4],ax
  6760.     mov    d[@@Flags],ebx
  6761.     mov    d[@@Command],esi
  6762.     mov    w[@@Command+4],es
  6763.     mov    w[@@Environment],cx
  6764.     ;
  6765.     mov    w[@@PSP],0
  6766.     mov    w[@@Handle],0
  6767.     mov    d[@@SegMem],0
  6768.     mov    d[@@RelocMem],0
  6769.     mov    d[@@AutoOffset],0
  6770.     mov    d[@@ExpMem],0
  6771.     mov    d[@@ModLink],0
  6772.     mov    d[@@ImpMem],0
  6773. ;
  6774. ;Try and open the file.
  6775. ;
  6776.     push    ds
  6777.     lds    edx,f[@@Name]
  6778.     mov    ax,3d00h        ;open, read only.
  6779.     int    21h
  6780.     pop    ds
  6781.     jc    @@no_file_error
  6782.     mov    w[@@Handle],ax    ;store the handle.
  6783. ;
  6784. ;Check for just a 3P file with no extender.
  6785. ;
  6786. @@Look3P:    mov    bx,w[@@Handle]
  6787.     mov    edx,offset apiNewHeader    ;somewhere to put the info.
  6788.     mov    ecx,size NewHeaderStruc    ;size of it.
  6789.     mov    ah,3fh
  6790.     int    21h
  6791.     jc    @@file_error
  6792.     cmp    ax,size NewHeaderStruc    ;did we read right amount?
  6793.     jnz    @@file_error
  6794.     ;
  6795.     cmp    w[apiNewHeader],'ZM'
  6796.     jnz    @@CheckNew
  6797.     ;
  6798.     ;Move back to EXE details.
  6799.     ;
  6800.     mov    bx,w[@@Handle]
  6801.     mov    dx,-(size NewHeaderStruc)
  6802.     mov    cx,-1
  6803.     mov    ax,4201h
  6804.     int    21h        ;move back to start of the header.
  6805.     ;
  6806.     mov    bx,w[@@Handle]
  6807.     mov    edx,offset apiExeSignature ;somewhere to put the info.
  6808.     mov    ecx,1bh        ;size of it.
  6809.     mov    ah,3fh
  6810.     int    21h
  6811.     jc    @@file_error
  6812.     cmp    ax,1bh        ;did we read right amount?
  6813.     jnz    @@file_error
  6814.     ;
  6815.     mov    ax,w[apiExeLength+2]    ;get length in 512 byte blocks
  6816.  
  6817. ; MED 01/17/96
  6818.     cmp    WORD PTR [apiExeLength],0
  6819.     je    medexe3        ; not rounded if no modulo
  6820.  
  6821.     dec    ax        ;lose 1 cos its rounded up
  6822.  
  6823. medexe3:
  6824.     add    ax,ax        ;mult by 2
  6825.     mov    dh,0
  6826.     mov    dl,ah
  6827.     mov    ah,al
  6828.     mov    al,dh        ;mult by 256=*512
  6829.     add    ax,w[apiExeLength]    ;add length mod 512
  6830.     adc    dx,0        ;add any carry to dx
  6831.     mov    cx,ax
  6832.     xchg    cx,dx        ;swap round for DOS.
  6833.     mov    ax,4200h        ;set absolute position.
  6834.     int    21h
  6835.     jmp    @@Look3P
  6836.     ;
  6837. @@CheckNew:    cmp    w[apiNewHeader],'P3'    ;ID ok?
  6838.     jnz    @@file_error
  6839. ;
  6840. ;Check if this is the right module.
  6841. ;
  6842.     cmp    ExecMCount,0
  6843.     jz    @@emc0
  6844.     dec    ExecMCount
  6845.     mov    edx,d[apiNewHeader+NewSize]
  6846.     sub    edx,size NewHeaderStruc
  6847.     mov    cx,dx
  6848.     shr    edx,16
  6849.     xchg    cx,dx
  6850.     mov    ax,4201h
  6851.     int    21h
  6852.     jmp    @@Look3P
  6853. ;
  6854. ;Get file offset and store it.
  6855. ;
  6856. @@emc0:    mov    bx,w[@@Handle]
  6857.     xor    cx,cx
  6858.     xor    dx,dx
  6859.     mov    ax,4201h
  6860.     int    21h
  6861.     shl    edx,16
  6862.     mov    dx,ax
  6863.     mov    d[@@3PStart],edx
  6864. ;
  6865. ;Close the file again.
  6866. ;
  6867.     mov    bx,w[@@Handle]
  6868.     mov    ah,3eh
  6869.     int    21h
  6870.     mov    w[@@Handle],0
  6871. ;
  6872. ;Create a new PSP.
  6873. ;
  6874.     push    ds
  6875.     mov    ebx,d[@@Flags]
  6876.     mov    cx,w[@@Environment]
  6877.     les    esi,f[@@command]
  6878.     lds    edx,f[@@name]
  6879.     call    CreatePSP
  6880.     pop    ds
  6881.     mov    w[@@PSP],bx
  6882.     jc    @@mem_error
  6883. ;
  6884. ;Open the input file again.
  6885. ;
  6886.     push    ds
  6887.     lds    edx,f[@@Name]
  6888.     mov    ax,3d00h        ;open, read only.
  6889.     int    21h
  6890.     pop    ds
  6891.     jc    @@file_error
  6892.     mov    w[@@Handle],ax    ;store the handle.
  6893. ;
  6894. ;Move past 3P header again.
  6895. ;
  6896.     mov    edx,d[@@3PStart]
  6897.     mov    cx,dx
  6898.     shr    edx,16
  6899.     xchg    dx,cx
  6900.     mov    ax,4200h
  6901.     mov    bx,w[@@Handle]
  6902.     int    21h
  6903. ;
  6904. ;Grab flags.
  6905. ;
  6906.     mov    esi,offset apiNewHeader
  6907.     mov    eax,NewFlags[esi]
  6908.     mov    d[@@SystemFlags],eax
  6909.     test    b[@@SystemFlags+3],128    ;compressed?
  6910.     jz    @@noret
  6911.     cmp    d[@@Flags],1        ;debug load?
  6912.     jnz    @@noret
  6913.     jmp    @@file_error
  6914. ;
  6915. ;Setup auto stack stuff if its needed.
  6916. ;
  6917. @@noret:    mov    esi,offset apiNewHeader
  6918.     cmp    NewEntryESP[esi],0    ;Need an automatic stack?
  6919.     jnz    @@NotAutoESP
  6920.     mov    eax,NewAutoStack[esi]    ;Get auto stack size.
  6921.     or    eax,eax
  6922.     jnz    @@GotAutoSize
  6923.     mov    eax,1024
  6924. @@GotAutoSize:    mov    NewEntryESP[esi],eax    ;Setup ESP value.
  6925.     mov    ebx,NewAlloc[esi]
  6926.     add    NewAlloc[esi],eax    ;update memory size needed.
  6927.     mov    d[@@AutoOffset],ebx    ;store it for later.
  6928. ;
  6929. ;Get EXPORT memory.
  6930. ;
  6931. @@NotAutoESP:    mov    esi,offset apiNewHeader
  6932.     mov    ecx,NewExports[esi]
  6933.     or    ecx,ecx
  6934.     jz    @@NoExports0
  6935.     sys    GetMemLinear32
  6936.     jc    @@mem_error
  6937.     mov    d[@@ExpMem],esi
  6938. ;
  6939. ;Get IMPORT module link table memory.
  6940. ;
  6941. @@NoExports0:    mov    esi,offset apiNewHeader
  6942.     mov    ecx,NewImportModCnt[esi]
  6943.     or    ecx,ecx
  6944.     jz    @@NoImports0
  6945.     shl    ecx,2        ;dword per entry.
  6946.     add    ecx,4        ;allow for count dword.
  6947.     sys    GetMemLinear32
  6948.     jc    @@mem_error
  6949.     mov    d[@@ModLink],esi
  6950.     push    es
  6951.     mov    es,apiDSeg
  6952.     assume es:_cwMain
  6953.     mov    es,RealSegment
  6954.     assume es:nothing
  6955.     mov    es:d[esi],0        ;clear entry count for now.
  6956.     mov    es,w[@@PSP]
  6957.     mov    es:d[EPSP_Imports],esi
  6958.     pop    es
  6959. ;
  6960. ;Get program main memory.
  6961. ;
  6962. @@NoImports0:    mov    esi,offset apiNewHeader
  6963.     mov    ecx,NewAlloc[esi]    ;get memory size required.
  6964.     sys    GetMemLinear32    ;Get segment/selector.
  6965.     jc    @@mem_error        ;Not enough memory.
  6966.     mov    d[@@ProgBase],esi
  6967. ;
  6968. ;Get segment definition memory, selectors and details.
  6969. ;
  6970.     mov    esi,offset apiNewHeader
  6971.     movzx    ecx,NewSegments[esi]    ;get number of segments.
  6972.     cmp    d[@@AutoOffset],0    ;need auto SS?
  6973.     jz    @@NoAutoSeg
  6974.     inc    cx        ;one more for the stack.
  6975. @@NoAutoSeg:    push    cx
  6976.     shl    ecx,3        ;8 bytes per entry.
  6977.     sys    GetMemLinear32
  6978.     pop    cx
  6979.     jc    @@mem_error
  6980.     mov    d[@@SegMem],esi
  6981.     sys    GetSels
  6982.     jc    @@mem_error
  6983.     mov    w[@@Segs],bx        ;store base selector.
  6984.     mov    w[@@Segs+2],cx    ;store number of selectors.
  6985. ;
  6986. ;Update programs memory and selector details in PSP and variables.
  6987. ;
  6988.     push    es
  6989.     mov    es,w[@@PSP]
  6990.     mov    ax,w[@@Segs]        ;get base selector.
  6991.     mov    es:w[EPSP_SegBase],ax
  6992.     mov    ax,w[@@Segs+2]    ;get number of selectors.
  6993.     shl    ax,3
  6994.     mov    es:w[EPSP_SegSize],ax
  6995.     mov    eax,d[@@ProgBase]    ;get memory address.
  6996.     mov    es:d[EPSP_MemBase],eax
  6997.     mov    es:d[EPSP_NearBase],eax
  6998.     mov    edi,offset apiNewHeader
  6999.     mov    eax,NewAlloc[edi]    ;get memory size.
  7000.     mov    es:d[EPSP_MemSize],eax
  7001.     pop    es
  7002. ;
  7003. ;Read segment definitions.
  7004. ;
  7005.     test    b[@@SystemFlags+3],128    ;compressed?
  7006.     jz    @@ncp0
  7007.     mov    bx,w[@@Handle]
  7008.     push    es
  7009.     mov    es,apiDSeg
  7010.     assume es:_cwMain
  7011.     mov    es,es:RealSegment
  7012.     assume es:nothing
  7013.     mov    edi,d[@@SegMem]
  7014.     sys    cwcLoad
  7015.     pop    es
  7016.     or    ax,ax
  7017.     jnz    @@file_error
  7018.     jmp    @@ncp1
  7019.     ;
  7020. @@ncp0:    mov    esi,offset apiNewHeader
  7021.     movzx    ecx,NewSegments[esi]    ;get number of segments.
  7022.     shl    ecx,3        ;8 bytes per entry.
  7023.     mov    bx,w[@@Handle]
  7024.     mov    edx,d[@@SegMem]
  7025.     push    ecx
  7026.     push    ds
  7027.     mov    ds,apiDSeg
  7028.     assume ds:_cwMain
  7029.     mov    ds,RealSegment
  7030.     call    ReadFile
  7031.     assume ds:_apiCode
  7032.     pop    ds
  7033.     pop    ecx
  7034.     jc    @@file_error
  7035.     cmp    eax,ecx
  7036.     jnz    @@file_error
  7037. ;
  7038. ;Setup a segment definition for auto-stack if needed.
  7039. ;
  7040. @@ncp1:    cmp    d[@@AutoOffset],0
  7041.     jz    @@NoAutoMake
  7042.     mov    esi,offset apiNewHeader
  7043.     movzx    edi,NewSegments[esi]    ;get number of segments.
  7044.     mov    NewEntrySS[esi],di    ;store SS number.
  7045.     shl    edi,3        ;8 bytes per entry.
  7046.     add    edi,d[@@SegMem]    ;offset to space for new entry.
  7047.     inc    NewSegments[esi]    ;update number of segments.
  7048.     mov    eax,d[@@AutoOffset]
  7049.     mov    es,apiDSeg
  7050.     assume es:_cwMain
  7051.     mov    es,es:RealSegment
  7052.     assume es:nothing
  7053.     mov    es:[edi],eax        ;setup base.
  7054.     mov    eax,NewEntryESP[esi]    ;get limit.
  7055.     cmp    eax,100000h
  7056.     jc    @@NoAutoGBit
  7057.     shr    eax,12
  7058.     or    eax,1 shl 20        ;set G bit.
  7059. @@NoAutoGBit:    or    eax,2 shl 21        ;set class 'stack'
  7060.     mov    es:[edi+4],eax    ;setup limit entry.
  7061. ;
  7062. ;Get relocation table memory.
  7063. ;
  7064. @@NoAutoMake:    mov    esi,offset apiNewHeader
  7065.     mov    ecx,NewRelocs[esi]    ;get number of relocation entries.
  7066.     or    ecx,ecx
  7067.     jz    @@NoRelocsMem
  7068.     shl    ecx,2        ;4 bytes per entry.
  7069.     sys    GetMemLinear32
  7070.     jc    @@mem_error
  7071.     mov    d[@@RelocMem],esi
  7072. ;
  7073. ;Read relocation entries.
  7074. ;
  7075.     test    b[@@SystemFlags+3],128    ;compressed?
  7076.     jz    @@ncp2
  7077.     mov    bx,w[@@Handle]
  7078.     push    es
  7079.     mov    es,apiDSeg
  7080.     assume es:_cwMain
  7081.     mov    es,es:RealSegment
  7082.     assume es:nothing
  7083.     mov    edi,d[@@RelocMem]
  7084.     sys    cwcLoad
  7085.     pop    es
  7086.     or    ax,ax
  7087.     jnz    @@file_error
  7088.     jmp    @@NoRelocsMem
  7089.     ;
  7090. @@ncp2:    mov    esi,offset apiNewHeader
  7091.     mov    ecx,NewRelocs[esi]    ;get number of relocation entries.
  7092.     shl    ecx,2        ;4 bytes per entry.
  7093.     mov    bx,w[@@Handle]
  7094.     mov    edx,d[@@RelocMem]
  7095.     pushm    ecx,ds
  7096.     mov    ds,apiDSeg
  7097.     assume ds:_cwMain
  7098.     mov    ds,RealSegment
  7099.     call    ReadFile
  7100.     assume ds:_apiCode
  7101.     popm    ecx,ds
  7102.     jc    @@file_error
  7103.     cmp    eax,ecx        ;did we get enough?
  7104.     jnz    @@file_error
  7105. ;
  7106. ;Read export table.
  7107. ;
  7108. @@NoRelocsMem:    mov    esi,offset apiNewHeader
  7109.     mov    ecx,NewExports[esi]    ;get length of export table.
  7110.     or    ecx,ecx
  7111.     jz    @@NoExpMem
  7112.     ;
  7113.     test    b[@@SystemFlags+3],128    ;compressed?
  7114.     jz    @@ncp3
  7115.     mov    bx,w[@@Handle]
  7116.     push    es
  7117.     mov    es,apiDSeg
  7118.     assume es:_cwMain
  7119.     mov    es,es:RealSegment
  7120.     assume es:nothing
  7121.     mov    edi,d[@@ExpMem]
  7122.     sys    cwcLoad
  7123.     pop    es
  7124.     or    ax,ax
  7125.     jnz    @@file_error
  7126.     jmp    @@NoExpMem
  7127.     ;
  7128. @@ncp3:    mov    bx,w[@@Handle]
  7129.     mov    edx,d[@@ExpMem]
  7130.     pushm    ecx,ds
  7131.     mov    ds,apiDSeg
  7132.     assume ds:_cwMain
  7133.     mov    ds,RealSegment
  7134.     call    ReadFile
  7135.     assume ds:_apiCode
  7136.     popm    ecx,ds
  7137.     jc    @@file_error
  7138.     cmp    eax,ecx        ;did we get enough?
  7139.     jnz    @@file_error
  7140. ;
  7141. ;Get IMPORT memory.
  7142. ;
  7143. @@NoExpMem:    mov    esi,offset apiNewHeader
  7144.     mov    ecx,NewImports[esi]    ;get size of IMPORT table.
  7145.     or    ecx,ecx
  7146.     jz    @@NoImpMem1
  7147.     shl    ecx,2        ;4 bytes per entry.
  7148.     sys    GetMemLinear32
  7149.     jc    @@mem_error
  7150.     mov    d[@@ImpMem],esi
  7151. ;
  7152. ;Read IMPORT entries.
  7153. ;
  7154.     test    b[@@SystemFlags+3],128    ;compressed?
  7155.     jz    @@ncp20
  7156.     mov    bx,w[@@Handle]
  7157.     push    es
  7158.     mov    es,apiDSeg
  7159.     assume es:_cwMain
  7160.     mov    es,es:RealSegment
  7161.     assume es:nothing
  7162.     mov    edi,d[@@ImpMem]
  7163.     sys    cwcLoad
  7164.     pop    es
  7165.     or    ax,ax
  7166.     jnz    @@file_error
  7167.     jmp    @@NoImpMem1
  7168.     ;
  7169. @@ncp20:    mov    esi,offset apiNewHeader
  7170.     mov    ecx,NewImports[esi]    ;get size of IMPORT table.
  7171.     mov    bx,w[@@Handle]
  7172.     mov    edx,d[@@ImpMem]
  7173.     pushm    ecx,ds
  7174.     mov    ds,apiDSeg
  7175.     assume ds:_cwMain
  7176.     mov    ds,RealSegment
  7177.     call    ReadFile
  7178.     assume ds:_apiCode
  7179.     popm    ecx,ds
  7180.     jc    @@file_error
  7181.     cmp    eax,ecx        ;did we get enough?
  7182.     jnz    @@file_error
  7183. ;
  7184. ;Read exe image.
  7185. ;
  7186. @@NoImpMem1:    mov    esi,offset apiNewHeader
  7187.     test    NewFlags[esi],1 shl 31    ;compressed?
  7188.     jz    @@NotComp
  7189.     mov    bx,w[@@Handle]
  7190.     push    es
  7191.     mov    es,apiDSeg
  7192.     assume es:_cwMain
  7193.     mov    es,es:RealSegment
  7194.     assume es:nothing
  7195.     mov    edi,d[@@ProgBase]
  7196.     sys    cwcLoad
  7197.     pop    es
  7198.     or    ax,ax
  7199.     jnz    @@file_error
  7200.     jmp    @@ImageLoaded
  7201.     ;
  7202. @@NotComp:    test    NewFlags[esi],1 shl 30
  7203.     jz    @@LoadAll
  7204.  
  7205.     jmp    @@LoadVMM
  7206.  
  7207. @@LoadAll:    mov    edx,d[@@ProgBase]
  7208.     mov    ecx,NewLength[esi]    ;get image length.
  7209.     mov    bx,w[@@Handle]
  7210.     pushm    ecx,ds
  7211.     mov    ds,apiDSeg
  7212.     assume ds:_cwMain
  7213.     mov    ds,RealSegment
  7214.     call    ReadFile        ;read the file.
  7215.     assume ds:_apiCode
  7216.     popm    ecx,ds
  7217.     jc    @@file_error        ;problems problems.
  7218.     cmp    eax,ecx        ;did we get right amount?
  7219.     jnz    @@file_error
  7220.     jmp    @@ImageLoaded
  7221. ;
  7222. ;Break the file read up into 8K chunks that suit the relocations.
  7223. ;
  7224. @@LoadVMM:    mov    eax,offset apiNewHeader
  7225.     mov    eax,NewRelocs[eax]    ;get number of relocation entries.
  7226.     mov    d[@@SL_RelocLeft],eax
  7227.     mov    eax,d[@@RelocMem]
  7228.     mov    d[@@SL_RelocPnt],eax
  7229.     mov    eax,offset apiNewHeader
  7230.     mov    eax,NewLength[eax]
  7231.     mov    d[@@SL_LoadLeft],eax
  7232.     mov    eax,d[@@ProgBase]
  7233.     mov    d[@@SL_LoadPnt],eax
  7234.     mov    d[@@EntryEIP],0
  7235.     ;
  7236. @@sl0:    ;Anything left to load?
  7237.     ;
  7238.     cmp    d[@@SL_LoadLeft],0
  7239.     jz    @@ImageLoaded
  7240.     mov    es,apiDSeg
  7241.     assume es:_cwMain
  7242.     mov    es,es:RealSegment
  7243.     assume es:nothing
  7244.     ;
  7245.     ;Work out how much we should load.
  7246.     ;
  7247.     mov    ecx,d[@@SL_LoadLeft]
  7248.     cmp    d[@@SL_RelocLeft],0
  7249.     jz    @@sl3
  7250.     mov    esi,d[@@SL_RelocPnt]
  7251.     mov    eax,es:[esi]        ;get fixup address.
  7252.     and    eax,0FFFFFFFh
  7253.     add    eax,4        ;allow for cross page fixup.
  7254.     add    eax,8191
  7255.     and    eax,not 8191        ;get terminal offset.
  7256.     mov    ebx,d[@@SL_LoadPnt]
  7257.     sub    ebx,d[@@ProgBase]
  7258.     sub    eax,ebx        ;get relative offset.
  7259.     cmp    eax,ecx
  7260.     jnc    @@sl1
  7261.     mov    ecx,eax
  7262.     ;
  7263.     ;Load next program chunk.
  7264.     ;
  7265. @@sl1:
  7266.     or    ecx,ecx
  7267.     jnz    @@sl3
  7268.  
  7269.     mov    eax,d[@@EntryEIP]
  7270.     or    bx,-1
  7271.     mov    es,bx
  7272.  
  7273. @@sl3:
  7274.  
  7275.     mov    edx,d[@@SL_LoadPnt]
  7276.     mov    bx,w[@@Handle]
  7277.     pushm    ecx,ds
  7278.     mov    ds,apiDSeg
  7279.     assume ds:_cwMain
  7280.     mov    ds,RealSegment
  7281.     call    ReadFile        ;read the file.
  7282.     assume ds:_apiCode
  7283.     popm    ecx,ds
  7284.     jc    @@file_error        ;problems problems.
  7285.     cmp    eax,ecx        ;did we get right amount?
  7286.     jnz    @@file_error
  7287.     ;
  7288.     ;Update variables.
  7289.     ;
  7290.     add    d[@@SL_LoadPnt],ecx
  7291.     sub    d[@@SL_LoadLeft],ecx
  7292.     ;
  7293.     ;Process all fixups in range of what we loaded.
  7294.     ;
  7295.     mov    esi,d[@@SL_RelocPnt]
  7296.     mov    ecx,d[@@SL_RelocLeft]
  7297.     mov    fs,w[@@PSP]
  7298.     ;
  7299.     mov    bx,w[@@Segs]
  7300.     mov    edi,fs:d[EPSP_MemBase]
  7301.     add    edi,fs:d[EPSP_MemSize]
  7302.     mov    dx,fs:w[EPSP_SegSize]
  7303.     shr    dx,3
  7304. @@SL_RelocLoop: or ecx,ecx
  7305.     jz    @@SL_DoneRelocs
  7306.     mov    ebp,es:[esi]        ;get linear offset.
  7307.     mov    eax,ebp
  7308.     and    ebp,0FFFFFFFh    ;Lose relocation type.
  7309.     shr    eax,28        ;Get relocation type.
  7310.     add    ebp,d[@@ProgBase]    ;get linear address.
  7311.     cmp    ebp,edi
  7312.     jnc    @@file_error2
  7313.     or    al,al
  7314.     jz    @@SL_Seg16
  7315.     dec    al
  7316.     jz    @@SL_Offset32
  7317.     jmp    @@file_error2
  7318.     ;
  7319. @@SL_Offset32:    mov    eax,ebp
  7320.     add    eax,4-1
  7321.     cmp    eax,d[@@SL_LoadPnt]    ;beyond what we loaded?
  7322.     jnc    @@SL_DoneRelocs
  7323.     mov    eax,es:[ebp]        ;Get offset.
  7324.     add    eax,d[@@ProgBase]
  7325.     cmp    eax,edi        ;Beyond program?
  7326.     jnc    @@file_error2
  7327.     mov    eax,d[@@ProgBase]
  7328.     add    es:d[ebp],eax    ;Do the relocation.
  7329.     jmp    @@SL_NextReloc
  7330.     ;
  7331. @@SL_Seg16:    mov    eax,ebp
  7332.     add    eax,2-1
  7333.     cmp    eax,d[@@SL_LoadPnt]    ;beyond what we loaded?
  7334.     jnc    @@SL_DoneRelocs
  7335.     mov    ax,es:[ebp]        ;get selector number.
  7336.     cmp    ax,dx
  7337.     jnc    @@file_error2
  7338.     shl    ax,3        ;*8 for selector value.
  7339.     add    ax,bx        ;add base selector.
  7340.     mov    es:[ebp],ax        ;set segment selector.
  7341.     ;
  7342. @@SL_NextReloc:
  7343.     add    esi,4        ;next relocation entry.
  7344.     inc    d[@@EntryEIP]
  7345.     dec    ecx
  7346.     jnz    @@SL_RelocLoop
  7347.     ;
  7348. @@SL_DoneRelocs:
  7349.     mov    d[@@SL_RelocPnt],esi
  7350.     mov    d[@@SL_RelocLeft],ecx
  7351.     mov    esi,offset apiNewHeader
  7352.     mov    NewRelocs[esi],ecx
  7353.     jmp    @@sl0
  7354. ;
  7355. ;Close the file now we're done with it.
  7356. ;
  7357. @@ImageLoaded:    pushm    ds,ds
  7358.     popm    es,fs
  7359.     ;
  7360.     mov    bx,w[@@Handle]    ;grab handle again,
  7361.     mov    w[@@Handle],0
  7362.     mov    ah,3eh        ;and close it.
  7363.     int    21h
  7364. ;
  7365. ;Process relocations.
  7366. ;
  7367.     mov    esi,offset apiNewHeader
  7368.     mov    ecx,NewRelocs[esi]    ;get number of relocation entries.
  7369.     or    ecx,ecx
  7370.     jz    @@DoneReloc
  7371.     mov    esi,d[@@RelocMem]
  7372.     mov    es,apiDSeg
  7373.     assume es:_cwMain
  7374.     mov    es,es:RealSegment
  7375.     assume es:nothing
  7376.     mov    fs,w[@@PSP]
  7377.     ;
  7378.     mov    d[@@EntryEIP],0
  7379.     mov    bx,w[@@Segs]
  7380.     mov    edi,fs:d[EPSP_MemBase]
  7381.     add    edi,fs:d[EPSP_MemSize]
  7382.     mov    dx,fs:w[EPSP_SegSize]
  7383.     shr    dx,3
  7384. @@RelocLoop:    mov    ebp,es:[esi]        ;get linear offset.
  7385.     mov    eax,ebp
  7386.     and    ebp,0FFFFFFFh    ;Lose relocation type.
  7387.     shr    eax,28        ;Get relocation type.
  7388.     add    ebp,d[@@ProgBase]    ;get linear address.
  7389.     cmp    ebp,edi
  7390.     jnc    @@file_error2
  7391.     or    al,al
  7392.     jz    @@Seg16
  7393.     dec    al
  7394.     jz    @@Offset32
  7395.     jmp    @@file_error2
  7396.     ;
  7397. @@Offset32:    mov    eax,es:[ebp]        ;Get offset.
  7398.     add    eax,d[@@ProgBase]
  7399.     cmp    eax,edi        ;Beyond program?
  7400.     jnc    @@file_error2
  7401.     mov    eax,d[@@ProgBase]
  7402.     add    es:d[ebp],eax    ;Do the relocation.
  7403.     jmp    @@NextReloc
  7404.     ;
  7405. @@Seg16:    mov    ax,es:[ebp]        ;get selector number.
  7406.     cmp    ax,dx
  7407.     jnc    @@file_error2
  7408.     shl    ax,3        ;*8 for selector value.
  7409.     add    ax,bx        ;add base selector.
  7410.     mov    es:[ebp],ax        ;set segment selector.
  7411.     ;
  7412. @@NextReloc:    add    esi,4        ;next relocation entry.
  7413.     inc    d[@@EntryEIP]
  7414.     dec    ecx
  7415.     jnz    @@RelocLoop
  7416.     pushm    ds,ds
  7417.     popm    es,fs
  7418. ;
  7419. ;Set selector details.
  7420. ;
  7421. @@DoneReloc:    mov    esi,offset apiNewHeader
  7422.     movzx    ecx,NewSegments[esi]    ;get number of segments.
  7423.     mov    esi,d[@@SegMem]
  7424.     mov    es,apiDSeg
  7425.     assume es:_cwMain
  7426.     mov    es,es:RealSegment
  7427.     assume es:nothing
  7428.     mov    bx,w[@@Segs]        ;base selector.
  7429. @@SegLoop:    pushm    ebx,ecx,esi
  7430.     ;
  7431.     mov    eax,es:[esi+4]    ;Get limit.
  7432.     mov    ecx,eax
  7433.     and    ecx,0fffffh        ;mask to 20 bits.
  7434.     test    eax,1 shl 20        ;G bit set?
  7435.     jz    @@NoGBit
  7436.     shl    ecx,12
  7437.     or    ecx,4095
  7438. @@NoGBit:    or    ecx,ecx
  7439.     jz    @@NoDecLim
  7440.     cmp    ecx,-1
  7441.     jz    @@NoDecLim
  7442.     dec    ecx
  7443. @@NoDecLim:    mov    edx,es:[esi]        ;get base.
  7444.     ;
  7445.     test    eax,1 shl 27        ;FLAT segment?
  7446.     jz    @@NotFLATSeg
  7447.     ;
  7448.     push    fs
  7449.     mov    fs,w[@@PSP]
  7450.     mov    fs:d[EPSP_NearBase],0    ;Make sure NEAR functions work.
  7451.     pop    fs
  7452.     ;
  7453.     add    edx,d[@@ProgBase]
  7454.     or    ecx,-1        ;Update the limit.
  7455.     xor    edx,edx
  7456.     jmp    @@DoSegSet
  7457.     ;
  7458. @@NotFLATSeg:    add    edx,d[@@ProgBase]    ;offset within real memory.
  7459.     ;
  7460. @@DoSegSet:    sys    SetSelDet32
  7461.     mov    cx,w[@@SystemFlags]    ;use default setting.
  7462.     shr    cx,14
  7463.     xor    cl,1
  7464.     or    cl,b[@@SystemFlags+2]
  7465.     and    cl,1
  7466.     call    _DSizeSelector
  7467.     ;
  7468.     mov    eax,es:[esi+4]    ;Get class.
  7469.     shr    eax,21        ;move type into useful place.
  7470.     and    eax,0fh        ;isolate type.
  7471.     or    eax,eax
  7472.     jz    @@CodeSeg
  7473.     jmp    @@SegDone
  7474.     ;
  7475. @@CodeSeg:    mov    eax,es:[esi+4]    ;Get type bits.
  7476.     mov    cx,0        ;Set 16 bit seg.
  7477.     test    eax,1 shl 25
  7478.     jnz    @@Default
  7479.     mov    cx,1
  7480.     test    eax,1 shl 26        ;32 bit seg?
  7481.     jnz    @@Default
  7482.     mov    cx,w[@@SystemFlags]    ;use default setting.
  7483.     shr    cx,14
  7484.     and    cx,1        ;get code size
  7485.     xor    cx,1        ;flip it for selector function.
  7486. @@Default:    sys    CodeSel
  7487.     ;
  7488. @@SegDone:    popm    ebx,ecx,esi
  7489.     add    esi,8        ;next definition.
  7490.     add    ebx,8        ;next selector.
  7491.     dec    ecx
  7492.     jnz    @@SegLoop
  7493. ;
  7494. ;Update export table values.
  7495. ;
  7496.     cmp    d[@@ExpMem],0
  7497.     jz    @@exp9
  7498.     push    es
  7499.     mov    es,w[@@PSP]
  7500.     mov    esi,d[@@ExpMem]
  7501.     mov    edi,d[@@SegMem]
  7502.     mov    es:d[EPSP_Exports],esi
  7503.     mov    dx,es:[EPSP_SegBase]
  7504.     mov    es,apiDSeg
  7505.     assume es:_cwMain
  7506.     mov    es,es:RealSegment
  7507.     assume es:nothing
  7508.     mov    ecx,es:[esi]
  7509.     mov    ebp,esi
  7510.     add    esi,4
  7511.     ;
  7512.     ;Do module name entry.
  7513.     ;
  7514.     add    es:[esi],ebp        ;turn offset into an address.
  7515.     add    esi,4
  7516.     ;
  7517.     ;Do all other entries.
  7518.     ;
  7519. @@exp0:    add    es:[esi],ebp        ;turn offset into an address.
  7520.     mov    ebx,es:[esi]        ;get address of export entry.
  7521.     movzx    eax,es:w[ebx+4]    ;get segment def.
  7522.     add    es:w[ebx+4],dx    ;update seg
  7523.     shl    eax,3
  7524.     add    eax,edi        ;point into seg defs.
  7525.     test    es:d[eax+4],1 shl 27    ;FLAT seg?
  7526.     jz    @@exp1
  7527.     mov    eax,d[@@ProgBase]
  7528.     add    es:d[ebx],eax    ;update to reflect FLAT
  7529. @@exp1:    add    esi,4
  7530.     dec    ecx
  7531.     jnz    @@exp0
  7532.     pop    es
  7533. @@exp9:    ;
  7534. ;
  7535. ;Setup entry regs.
  7536. ;
  7537.     mov    esi,offset apiNewHeader
  7538.     ;
  7539.     mov    ebx,NewEntryEIP[esi]    ;get entry address.
  7540.     movzx    eax,NewEntryCS[esi]
  7541.     shl    eax,3
  7542.     add    ax,w[@@Segs]
  7543.     mov    w[@@SegCS],ax
  7544.     sub    ax,w[@@Segs]
  7545.     add    eax,d[@@SegMem]    ;point to this segments entry.
  7546.     test    es:d[eax+4],1 shl 27    ;FLAT segment?
  7547.     jz    @@NotFLATEIP
  7548.     add    ebx,es:[eax]        ;include segments offset within image.
  7549.     add    ebx,d[@@ProgBase]
  7550. @@NotFLATEIP:    mov    d[@@EntryEIP],ebx
  7551.     ;
  7552.     mov    ebx,NewEntryESP[esi]
  7553.     movzx    eax,NewEntrySS[esi]
  7554.     shl    eax,3
  7555.     add    ax,w[@@Segs]
  7556.     mov    w[@@SegSS],ax
  7557.     sub    ax,w[@@Segs]
  7558.     add    eax,d[@@SegMem]    ;point to this segments entry.
  7559.     test    es:d[eax+4],1 shl 27    ;FLAT segment?
  7560.     jz    @@NotFLATESP
  7561.     add    ebx,es:[eax]        ;include segments offset within image.
  7562.     add    ebx,d[@@ProgBase]
  7563. @@NotFLATESP:    mov    d[@@EntryESP],ebx
  7564.     ;
  7565.     push    es
  7566.     mov    es,w[@@PSP]
  7567.     mov    ax,es
  7568.     pop    es
  7569.     cmp    NewAutoDS[esi],0
  7570.     jz    @@NotAUTODS
  7571.     mov    ax,NewAutoDS[esi]
  7572.     dec    ax
  7573.     shl    ax,3
  7574.     add    ax,w[@@Segs]
  7575. @@NotAUTODS:    mov    w[@@EntryDS],ax
  7576. ;
  7577. ;Convert import module names to pointers to export tables.
  7578. ;
  7579.     cmp    d[@@ImpMem],0    ;any imports?
  7580.     jz    @@imp9
  7581.     mov    d[@@ImpCnt],0    ;Clear the counter.
  7582.     mov    es,apiDSeg
  7583.     assume es:_cwMain
  7584.     mov    es,es:RealSegment
  7585.     assume es:nothing
  7586. @@imp0:    mov    esi,d[@@ImpMem]
  7587.     add    esi,es:d[esi]    ;move to module name list.
  7588.     mov    eax,d[@@ImpCnt]
  7589.     cmp    eax,es:d[esi]    ;Done all modules?
  7590.     jnc    @@imp6
  7591.     add    esi,es:[esi+4+eax*4]    ;Point to this module name.
  7592.     ;
  7593.     ;Try and find the module.
  7594.     ;
  7595.     call    FindModule
  7596.     jnc    @@got_module
  7597.     ;
  7598.     ;Put module's name into command line error message.
  7599.     ;
  7600.     ;ES:ESI is the name string.
  7601.     ;
  7602.     push    ds
  7603.     push    ax
  7604.     mov    ds,apiDSeg
  7605.     assume ds:_cwMain
  7606.     cmp    ax,1
  7607.     jnz    @@egm1
  7608.     mov    edi,offset ErrorM10_T
  7609.     movzx    ecx,es:b[esi]
  7610.     inc    esi
  7611.     mov    b[edi],'"'
  7612.     inc    edi
  7613. @@egm0:    mov    al,es:[esi]
  7614.     mov    [edi],al
  7615.     inc    esi
  7616.     inc    edi
  7617.     dec    ecx
  7618.     jnz    @@egm0
  7619.     mov    b[edi+0],'"'
  7620.     mov    b[edi+1],13
  7621.     mov    b[edi+2],10
  7622.     mov    b[edi+3],"$"
  7623. @@egm1:    pop    ax
  7624.     assume ds:_apiCode
  7625.     pop    ds
  7626.     stc
  7627.     jmp    @@error
  7628.     ;
  7629. @@got_module:    ;Update the module link table and usage count.
  7630.     ;
  7631.     mov    esi,d[@@ModLink]
  7632.     inc    es:d[esi]        ;update count.
  7633.     mov    eax,d[@@ImpCnt]
  7634.     mov    es:[esi+4+eax*4],edi    ;store EPSP link pointer.
  7635.     ;
  7636.     ;Move onto next module name.
  7637.     ;
  7638.     inc    d[@@ImpCnt]
  7639.     jmp    @@imp0
  7640. ;
  7641. ;Now it's time to work through the relocations performing the fixups.
  7642. ;
  7643. @@imp6:    mov    esi,d[@@ImpMem]
  7644.     add    esi,es:d[esi+8]    ;move to fixup list.
  7645.     mov    eax,es:[esi]        ;get number of entries.
  7646.     or    eax,eax
  7647.     jz    @@imp9
  7648.     mov    d[@@ImpCnt],eax
  7649.     add    esi,4
  7650. @@imp7:    xor    eax,eax
  7651.     mov    al,es:[esi]
  7652.     mov    d[@@ImpType],eax
  7653.     mov    eax,es:[esi+1]
  7654.     mov    d[@@ImpFlags],eax
  7655.     add    esi,1+4
  7656.     ;
  7657.     ;Point to the right modules export list.
  7658.     ;
  7659.     mov    ecx,d[@@ImpFlags]    ;get flags
  7660.     shr    ecx,30
  7661.     xor    eax,eax
  7662. @@imp8:    shl    eax,8
  7663.     mov    al,es:[esi]
  7664.     inc    esi
  7665.     dec    ecx
  7666.     jnz    @@imp8
  7667.     mov    edi,d[@@ModLink]
  7668.     mov    edi,es:[edi+4+eax*4]
  7669.     mov    edi,es:EPSP_Exports[edi]
  7670.     ;
  7671.     ;Point to the import name string.
  7672.     ;
  7673.     mov    ecx,d[@@ImpFlags]
  7674.     shr    ecx,28
  7675.     and    ecx,3
  7676.     xor    eax,eax
  7677. @@imp10:    shl    eax,8
  7678.     mov    al,es:[esi]
  7679.     inc    esi
  7680.     dec    ecx
  7681.     jnz    @@imp10
  7682.     ;
  7683.     ;Ordinal or string import?
  7684.     ;
  7685.     test    d[@@ImpType],128    ;ordinal?
  7686.     jz    @@imp14
  7687.     cmp    es:[edi],eax        ;check number of entries.
  7688.     jc    @@file_error
  7689.     mov    edi,es:[edi+4+eax*4]
  7690.     jmp    @@imp11
  7691.     ;
  7692. @@imp14:    mov    ebp,d[@@ImpMem]
  7693.     add    ebp,es:[ebp+4]    ;point to name list.
  7694.     add    ebp,es:[ebp+4+eax*4]    ;point to name string.
  7695.     ;
  7696.     ;Try and find name string in export list.
  7697.     ;
  7698.     call    FindFunction
  7699.     jc    @@file_error
  7700.     ;
  7701. @@imp11:    ;Found the right entry, now do the fixup.
  7702.     ;
  7703.     mov    ebx,d[@@ImpFlags]
  7704.     and    ebx,0FFFFFFFh
  7705.     add    ebx,d[@@ProgBase]
  7706.     mov    edx,es:[edi]
  7707.     xor    ecx,ecx
  7708.     mov    cx,es:[edi+4]
  7709.     mov    eax,d[@@ImpType]
  7710.     ;
  7711.     ;Check if this is self relative.
  7712.     ;
  7713.     test    eax,64
  7714.     jz    @@imp15
  7715.     and    eax,63
  7716.     mov    edx,ebx        ;must be flat.
  7717.     cmp    eax,1
  7718.     jz    @@imp18
  7719.     mov    edx,d[@@ImpFlags]
  7720.     and    edx,0FFFFFFFh
  7721. @@imp18:    add    edx,2
  7722.     test    eax,1
  7723.     jz    @@imp16
  7724.     add    edx,2
  7725. @@imp16:    sub    edx,es:[edi]
  7726.     neg    edx
  7727. @@imp15:    and    eax,63
  7728.     or    eax,eax
  7729.     jz    @@imp_offset16
  7730.     dec    eax
  7731.     jz    @@imp_offset32
  7732.     dec    eax
  7733.     jz    @@imp_pointer16
  7734.     dec    eax
  7735.     jz    @@imp_pointer32
  7736.     dec    eax
  7737.     jz    @@imp_base
  7738.     jmp    @@file_error
  7739.     ;
  7740.     ;Do a 16-bit offset fixup.
  7741.     ;
  7742. @@imp_offset16: mov    es:[ebx],dx
  7743.     jmp    @@imp17
  7744.     ;
  7745.     ;Do a 32-bit offset fixup.
  7746.     ;
  7747. @@imp_offset32: mov    es:[ebx],edx
  7748.     jmp    @@imp17
  7749.     ;
  7750.     ;Do a 16-bit pointer fixup.
  7751.     ;
  7752. @@imp_pointer16: mov    es:[ebx],dx
  7753.     mov    es:[ebx+2],cx
  7754.     jmp    @@imp17
  7755.     ;
  7756.     ;Do a 32-bit pointer fixup.
  7757.     ;
  7758. @@imp_pointer32: mov    es:[ebx],edx
  7759.     mov    es:[ebx+4],cx
  7760.     jmp    @@imp17
  7761.     ;
  7762.     ;Do a base fixup.
  7763.     ;
  7764. @@imp_base:    mov    es:[ebx],cx
  7765.     ;
  7766. @@imp17:    dec    d[@@ImpCnt]
  7767.     jnz    @@imp7
  7768. @@imp9:    ;
  7769. ;
  7770. ;Lose relocation memory.
  7771. ;
  7772.     mov    esi,d[@@RelocMem]
  7773.     sys    RelMemLinear32    ;release relocation list memory.
  7774.     mov    d[@@RelocMem],0
  7775. ;
  7776. ;Lose import memory.
  7777. ;
  7778.     mov    esi,d[@@ImpMem]    ;release IMPORT memory.
  7779.     or    esi,esi
  7780.     jz    @@NoRelImp9
  7781.     sys    RelMemLinear32
  7782.     mov    d[@@ImpMem],0
  7783. ;
  7784. ;Lose segment definitions.
  7785. ;
  7786. @@NoRelImp9:    cmp    d[@@Flags],1
  7787.     jz    @@NoSegMemRel
  7788.     mov    esi,d[@@SegMem]
  7789.     sys    RelMemLinear32    ;release segment memory.
  7790.     mov    d[@@SegMem],0
  7791. ;
  7792. ;Check if this is an exec or just a load.
  7793. ;
  7794. @@NoSegMemRel:    cmp    d[@@Flags],0
  7795.     jz    @@Exec
  7796. ;
  7797. ;Switch back to parents PSP if this is a debug load.
  7798. ;
  7799.     cmp    d[@@Flags],2
  7800.     jz    @@NoPSwitch2
  7801.     push    fs
  7802.     mov    fs,w[@@PSP]
  7803.     mov    bx,fs:w[EPSP_Parent]
  7804.     pop    fs
  7805.     mov    ah,50h
  7806.     int    21h
  7807.     mov    ebp,d[@@SegMem]
  7808. ;
  7809. ;Return program details to caller.
  7810. ;
  7811. @@NoPSwitch2:    mov    edx,d[@@EntryEIP]
  7812.     mov    cx,w[@@SegCS]
  7813.     mov    eax,d[@@EntryESP]
  7814.     mov    bx,w[@@SegSS]
  7815.     mov    si,w[@@PSP]
  7816.     mov    di,w[@@EntryDS]
  7817.     clc
  7818.     jmp    @@exit
  7819. ;
  7820. ;Run it.
  7821. ;
  7822. @@Exec:    mov    eax,d[@@Flags]
  7823.     mov    ebx,d[@@EntryEIP]
  7824.     mov    cx,w[@@SegCS]
  7825.     mov    edx,d[@@EntryESP]
  7826.     mov    si,w[@@SegSS]
  7827.     mov    di,w[@@PSP]
  7828.     mov    bp,w[@@EntryDS]
  7829.     call    ExecModule
  7830.     clc
  7831. ;
  7832. ;Shut down anything still hanging around.
  7833. ;
  7834. @@error:    pushf
  7835.     push    ax
  7836. ;
  7837. ;Make sure file is closed.
  7838. ;
  7839.     pushf
  7840.     xor    bx,bx
  7841.     xchg    bx,w[@@Handle]
  7842.     or    bx,bx
  7843.     jz    @@NoClose
  7844.     mov    ah,3eh
  7845.     int    21h
  7846. ;
  7847. ;Make sure all work spaces are released.
  7848. ;
  7849. @@NoClose:    mov    esi,d[@@RelocMem]
  7850.     or    esi,esi
  7851.     jz    @@NoRelRel
  7852.     sys    RelMemLinear32    ;release relocation list memory.
  7853.     mov    d[@@RelocMem],0
  7854. @@NoRelRel:    mov    esi,d[@@SegMem]
  7855.     or    esi,esi
  7856.     jz    @@NoSegRel
  7857.     sys    RelMemLinear32    ;release segment memory.
  7858.     mov    d[@@SegMem],0
  7859. @@NoSegRel:    mov    esi,d[@@ImpMem]
  7860.     or    esi,esi
  7861.     jz    @@NoImpRel
  7862.     sys    RelMemLinear32
  7863. ;
  7864. ;Restore previous state.
  7865. ;
  7866. @@NoImpRel:    popf
  7867.     jnc    @@RelPSP
  7868.     cmp    w[@@PSP],0
  7869.     jz    @@NoRelRes
  7870. ;
  7871. ;Restore vectors & DPMI state.
  7872. ;
  7873. @@RelPSP:    pushm    ds,ds,ds
  7874.     popm    es,fs,gs
  7875.     mov    eax,d[@@Flags]
  7876.     mov    bx,w[@@PSP]
  7877.     call    DeletePSP
  7878. ;
  7879. ;Return to caller.
  7880. ;
  7881. @@NoRelRes:    pop    ax
  7882.     popf
  7883.     ;
  7884. @@exit:    popm    d[@@ModLink],d[@@ImpMem],d[@@ImpCnt],d[@@3PStart]
  7885.     popm    d[@@Name],w[@@Name+4],w[@@Environment],d[@@SystemFlags]
  7886.     popm    d[@@AutoOffset],d[@@Command],w[@@Command+4],d[@@Flags]
  7887.     popm    d[@@SegMem],d[@@RelocMem],d[@@ProgBase],d[@@Segs],w[@@PSP]
  7888.     popm    d[@@ExpMem],d[@@EntryEIP],w[@@SegCS],d[@@EntryESP]
  7889.     popm    w[@@SegSS],d[@@SegMem],w[@@EntryDS]
  7890.     ;
  7891.     popm    ds,es,fs,gs
  7892.     ret
  7893. ;
  7894. ;Not enough memory error.
  7895. ;
  7896. @@mem_error:    mov    ax,3
  7897.     stc
  7898.     jmp    @@error
  7899. ;
  7900. ;Couldn't find the file.
  7901. ;
  7902. @@no_file_error: mov    ax,1
  7903.     stc
  7904.     jmp    @@error
  7905. ;
  7906. ;Not a 3P file.
  7907. ;
  7908. @@file_error:    mov    ax,2
  7909.     stc
  7910.     jmp    @@error
  7911. ;
  7912. ;Corrupt file.
  7913. ;
  7914. @@file_error2:    mov    eax,d[@@EntryEIP]    ;Get the relocation number.
  7915.     push    ds
  7916.     assume ds:nothing
  7917.     mov    ds,cs:apiDSeg
  7918.     assume ds:_cwMain
  7919.     mov    b[ErrorM11_0+0]," "
  7920.     mov    b[ErrorM11_0+1]," "
  7921.     mov    b[ErrorM11_0+2]," "
  7922.     mov    ecx,8
  7923.     mov    edi,offset ErrorM11_1
  7924.     call    Bin2HexA
  7925.     assume ds:_apiCode
  7926.     pop    ds
  7927.     mov    ax,2
  7928.     stc
  7929.     jmp    @@error
  7930. ;
  7931. @@Name:    ;
  7932.     df 0,0
  7933. @@Environment:    ;
  7934.     dw 0
  7935. @@SystemFlags:    ;
  7936.     dd ?
  7937. @@AutoOffset:    ;
  7938.     dd ?
  7939. @@Command:    ;
  7940.     df ?,0
  7941. @@Flags:    ;
  7942.     dd 0
  7943. @@ErrorCode:    ;
  7944.     dw 0        ;error number.
  7945. @@Handle:    ;
  7946.     dw 0        ;file handle.
  7947. @@EntryEIP:    ;
  7948.     dd 0
  7949. @@SegCS:    ;
  7950.     dw 0
  7951. @@EntryESP:    ;
  7952.     dd 0
  7953. @@SegSS:    ;
  7954.     dw 0
  7955. @@SegMem:    ;
  7956.     dd 0
  7957. @@RelocMem:    ;
  7958.     dd 0
  7959. @@ProgBase:    ;
  7960.     dd 0
  7961. @@Segs:    ;
  7962.     dd 0
  7963. @@PSP:    ;
  7964.     dw 0
  7965. @@EntryDS:    ;
  7966.     dw 0
  7967. @@ExpMem:    ;
  7968.     dd 0
  7969. @@ModLink:    ;
  7970.     dd 0
  7971. @@ImpMem:    ;
  7972.     dd 0
  7973. @@ImpCnt:    ;
  7974.     dd 0
  7975. @@ImpFlags:    ;
  7976.     dd 0
  7977. @@ImpType:    ;
  7978.     dd 0
  7979. @@3PStart:    ;
  7980.     dd 0
  7981. @@SL_RelocPnt:    ;
  7982.     dd 0
  7983. @@SL_RelocLeft: ;
  7984.     dd 0
  7985. @@SL_LoadPnt:    ;
  7986.     dd 0
  7987. @@SL_LoadLeft:    ;
  7988.     dd 0
  7989. Load3P    endp
  7990.  
  7991.  
  7992. ;-------------------------------------------------------------------------
  7993. ;
  7994. ;Execute module.
  7995. ;
  7996. ;On Entry:
  7997. ;
  7998. ;EAX    - Flags.
  7999. ;EBX    - Entry EIP
  8000. ;CX    - Entry CS
  8001. ;EDX    - Entry ESP
  8002. ;SI    - Entry SS
  8003. ;DI    - Entry ES
  8004. ;BP    - Entry DS
  8005. ;
  8006. ExecModule    proc    near
  8007.     pushm    ds,es
  8008.     assume ds:nothing
  8009.     mov    ds,cs:apiDDSeg
  8010.     assume ds:_apiCode
  8011.     pushm    d[@@Flags],d[@@EntryEIP],w[@@EntryCS],d[@@EntryESP]
  8012.     pushm    w[@@EntrySS],w[@@EntryES],w[@@EntryDS],w[@@PSP]
  8013.     ;
  8014.     mov    d[@@Flags],eax
  8015.     mov    d[@@EntryEIP],ebx
  8016.     mov    w[@@EntryCS],cx
  8017.     mov    d[@@EntryESP],edx
  8018.     mov    w[@@EntrySS],si
  8019.     mov    w[@@EntryES],di
  8020.     mov    w[@@EntryDS],bp
  8021.     mov    w[@@PSP],di
  8022. ;
  8023.     push    es
  8024.     mov    es,di
  8025.     mov    es:d[EPSP_Links],8000000h
  8026.     pop    es
  8027. ;
  8028. ;Patch Int 21h for function 4ch.
  8029. ;
  8030.     push    w[@@OldInt21h+6]
  8031.     mov    w[@@OldInt21h+6],0
  8032.     mov    eax,d[@@OldInt21h]
  8033.     or    ax,w[@@OldInt21h+4]
  8034.     or    eax,eax        ;Already patched?
  8035.     jnz    @@NoPatch21h
  8036.     ;
  8037.     mov    w[@@OldInt21h+6],-1
  8038.     mov    bl,21h
  8039.     sys    GetVect
  8040.     test    apiSystemFlags,1    ;16/32 bit?
  8041.     jz    @@Use32Bit100
  8042.     mov    w[@@OldInt21h+2],cx
  8043.     mov    w[@@OldInt21h],dx
  8044.     jmp    @@Use16Bit100
  8045. @@Use32Bit100:    mov    w[@@OldInt21h+4],cx
  8046.     mov    d[@@OldInt21h],edx
  8047. @@Use16Bit100:    mov    bl,21h
  8048.     mov    cx,cs
  8049.     mov    edx,offset @@Int21Patch
  8050.     sys    SetVect        ;put us in the running.
  8051. ;
  8052. ;Patch exception termination handler address.
  8053. ;
  8054. @@NoPatch21h:    mov    es,apiDSeg
  8055.     assume es:_cwMain
  8056.     push    es:d[TerminationHandler]
  8057.     push    es:d[TerminationHandler+4]
  8058.     mov    es:w[TerminationHandler+4],cs
  8059.     mov    es:d[TerminationHandler],offset @@KillIt
  8060.     assume es:nothing
  8061.     mov    es,w[@@PSP]
  8062.     mov    es:d[EPSP_SSESP],esp
  8063.     mov    es:w[EPSP_SSESP+4],ss
  8064.     lss    esp,f[@@EntryESP]    ;fetch new stack address.
  8065.     xor    eax,eax
  8066.     mov    ebx,eax
  8067.     mov    ecx,eax
  8068.     mov    edx,eax
  8069.     mov    esi,eax
  8070.     mov    edi,eax
  8071.     mov    ebp,eax
  8072.     mov    fs,ax
  8073.     mov    gs,ax
  8074.     mov    ds,cs:w[@@EntryDS]
  8075.     sti
  8076.     assume ds:nothing
  8077.     jmp    cs:f[@@EntryEIP]    ;pass control to program.
  8078.     ;
  8079. @@Int21Patch:    cmp    ah,4ch        ;terminate?
  8080.     jz    @@CheckKillIt
  8081.     cmp    ah,31h        ;TSR?
  8082.     jnz    @@OldVect
  8083. ;
  8084. ;Clean things up and exit.
  8085. ;
  8086.     mov    ax,cs:apiDSeg
  8087.     mov    ds,ax
  8088.     assume ds:_cwMain
  8089.     mov    ax,TSRSize
  8090.     assume ds:nothing
  8091.     mov    edi,offset Int21Buffer
  8092.     push    ds
  8093.     pop    es
  8094.     mov    Real_EAX[edi],3100h
  8095.     mov    Real_EDX[edi],eax
  8096.     mov    bl,21h
  8097.     sys    IntXX
  8098.     jmp    @@KillIt        ;just incase!
  8099.     ;
  8100. @@OldVect:    test    cs:apiSystemFlags,1    ;16/32?
  8101.     jz    @@Use32Bit101
  8102.     db 66h
  8103.     jmp    cs:f[@@OldInt21h]    ;pass control to old handler.
  8104. @@Use32Bit101:    jmp    cs:f[@@OldInt21h]
  8105.     ;
  8106. @@CheckKillIt:    push    ds
  8107.     mov    ds,cs:apiDSeg
  8108.     assume ds:_cwMain
  8109.     cmp    Int21hExecCount,0
  8110.     assume ds:nothing
  8111.     pop    ds
  8112.     jnz    @@OldVect
  8113. ;
  8114. ;Clean things up and return to caller.
  8115. ;
  8116. @@KillIt:    mov    ds,cs:apiDDSeg    ;make our data addressable.
  8117.     assume ds:_apiCode
  8118.     mov    w[@@errorcode],ax
  8119.     mov    es,w[@@PSP]
  8120.     lss    esp,es:f[EPSP_SSESP]
  8121.     mov    es,apiDSeg
  8122.     assume es:_cwMain
  8123.     pop    es:d[TerminationHandler+4]
  8124.     pop    es:d[TerminationHandler]
  8125.     assume es:nothing
  8126.     pushm    ds,ds,ds
  8127.     popm    es,fs,gs
  8128.     sti            ;turn interupts back on.
  8129.     ;
  8130.     cmp    w[@@OldInt21h+6],0
  8131.     jz    @@NoRel21h
  8132.     test    apiSystemFlags,1    ;16/32?
  8133.     jz    @@Use32Bit102
  8134.     mov    cx,w[@@OldInt21h+2]
  8135.     movzx    edx,w[@@OldInt21h]
  8136.     jmp    @@Use16Bit102
  8137. @@Use32Bit102:    mov    cx,w[@@OldInt21h+4]
  8138.     mov    edx,d[@@OldInt21h]
  8139. @@Use16Bit102:    mov    bl,21h
  8140.     sys    SetVect        ;restore old handler.
  8141. @@NoRel21h:    pop    w[@@OldInt21h+6]
  8142. ;
  8143. ;Get mouse event target state.
  8144. ;
  8145.     push    ds
  8146.     assume ds:nothing
  8147.     mov    ds,cs:apiDSeg
  8148.     assume ds:_cwMain
  8149.     mov    ds,w[Int33hExtension+20]    ;Get mouse data segment.
  8150.     assume ds:_Int33h
  8151.     xor    eax,eax
  8152.     xor    ebx,ebx
  8153.     cmp    Int33hUserOK,0
  8154.     jz    @@meventnodum
  8155.     test    cs:apiSystemFlags,1
  8156.     jz    @@mevent32
  8157.     movzx    eax,w[Int33hUserCode]
  8158.     movzx    ebx,w[Int33hUserCode+2]
  8159.     jmp    @@mevent16
  8160. @@mevent32:    mov    eax,d[Int33hUserCode]
  8161.     movzx    ebx,w[Int33hUserCode+4]
  8162. @@mevent16:    cmp    bx,Int33hCSeg
  8163.     jnz    @@meventnodum
  8164.     cmp    eax,offset Int33hDummy
  8165.     jnz    @@meventnodum
  8166.     xor    eax,eax
  8167.     xor    ebx,ebx
  8168. @@meventnodum:    mov    ds,Int33hDSeg
  8169.     assume ds:_cwMain
  8170.     mov    MouseETarget,eax
  8171.     mov    MouseETarget+4,ebx
  8172.     pop    ds
  8173.     assume ds:_apiCode
  8174.     ;
  8175. ;    mov    ax,0        ;reset mouse if present.
  8176. ;    int    33h
  8177.     mov    ax,w[@@errorcode]
  8178.     ;
  8179.     popm    w[@@EntrySS],w[@@EntryES],w[@@EntryDS],w[@@PSP]
  8180.     popm    d[@@Flags],d[@@EntryEIP],w[@@EntryCS],d[@@EntryESP]
  8181.     popm    ds,es
  8182.     ret
  8183. ;
  8184. @@OldInt21h:    ;
  8185.     df 0,0
  8186. @@errorcode:    ;
  8187.     dw 0
  8188. @@Flags:    ;
  8189.     dd 0
  8190. @@EntryEIP:    ;
  8191.     dd 0
  8192. @@EntryCS:    ;
  8193.     dw 0
  8194. @@EntryESP:    ;
  8195.     dd 0
  8196. @@EntrySS:    ;
  8197.     dw 0
  8198. @@EntryES:    ;
  8199.     dw 0
  8200. @@EntryDS:    ;
  8201.     dw 0
  8202. @@PSP:    ;
  8203.     dw 0
  8204. ExecModule    endp
  8205.  
  8206.  
  8207. ;-------------------------------------------------------------------------
  8208. ;
  8209. ;Convert number into ASCII Hex version.
  8210. ;
  8211. ;On Entry:-
  8212. ;
  8213. ;EAX    - Number to convert.
  8214. ;CX    - Digits to do.
  8215. ;DS:EDI    - Buffer to put string in.
  8216. ;
  8217. Bin2HexA    proc    near
  8218.     pushm    eax,ebx,ecx,edx,edi
  8219.     movzx    ecx,cx
  8220.     mov    ebx,offset HexTableA
  8221.     add    edi,ecx
  8222.     dec    edi
  8223.     mov    edx,eax
  8224. @@0:    mov    al,dl
  8225.     shr    edx,4
  8226.     and    al,15
  8227.     xlat    cs:[ebx]
  8228.     mov    [edi],al
  8229.     dec    edi
  8230.     dec    ecx
  8231.     jnz    @@0
  8232.     popm    eax,ebx,ecx,edx,edi
  8233.     push    ecx
  8234.     movzx    ecx,cx
  8235.     add    edi,ecx
  8236.     pop    ecx
  8237.     ret
  8238. HexTableA    db '0123456789ABCDEF'
  8239. Bin2HexA    endp
  8240.  
  8241.  
  8242. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  8243. LosefileHandles proc near
  8244.  
  8245.     if    0
  8246.     pushm    ds,es,fs
  8247.     assume ds:nothing
  8248.     mov    ds,cs:apiDSeg
  8249.     assume ds:_cwMain
  8250.     mov    fs,PSPSegment
  8251.     cmp    fs:w[PSP_HandlePtr+2],0
  8252.     jz    @@donehandles
  8253.     les    di,fs:d[PSP_HandlePtr]
  8254.     mov    cx,fs:w[PSP_Handles]
  8255.  
  8256.     if    0
  8257. @@RelHandles:    cmp    es:b[di],255
  8258.     jz    @@NoRelHandle
  8259.     movzx    bx,es:b[di]
  8260.     mov    ah,3eh
  8261.     int    21h
  8262. @@NoRelHandle:    inc    di
  8263.     dec    cx
  8264.     jnz    @@RelHandles
  8265.     endif
  8266.  
  8267.     mov    ax,fs
  8268.     mov    bx,es
  8269.     cmp    ax,bx
  8270.     jz    @@donehandles
  8271.     sys    RelMem
  8272.  
  8273.     if    0
  8274. ;
  8275. ;Reduce real mode handle count.
  8276. ;
  8277.     mov    edi,offset Int21Buffer
  8278.     mov    ax,TotalHandles    ;get current count.
  8279.     sub    ax,fs:w[PSP_Handles]
  8280.     or    ax,1        ;force bit 0 for DOS bug.
  8281.     mov    [edi].Real_EAX,6700h
  8282.     mov    [edi].Real_EBX,eax
  8283.     mov    bl,21h
  8284.     push    ds
  8285.     pop    es
  8286.     sys    IntXX
  8287.     sub    TotalHandles,20    ;update total handle count.
  8288.     endif
  8289.  
  8290. @@donehandles:
  8291.  
  8292.     popm    ds,es,fs
  8293.     endif
  8294.  
  8295.     ret
  8296.     assume ds:_apiCode
  8297. LosefileHandles endp
  8298.  
  8299.  
  8300. ;-------------------------------------------------------------------------
  8301. ;
  8302. ;Read some data from a file.
  8303. ;
  8304. ;On Entry:
  8305. ;
  8306. ;DS:EDX    - Address to read to.
  8307. ;ECX    - length to read.
  8308. ;EBX    - file handle.
  8309. ;
  8310. ;On Exit:
  8311. ;
  8312. ;EAX    - bytes read.
  8313. ;
  8314. ReadFile    proc    near
  8315.     call    DPMICopyCheck
  8316.     pushm    ecx,edx,esi
  8317.     xor    esi,esi        ;reset length read.
  8318. @@0:    pushm    ebx,ecx,edx,esi
  8319.     cmp    ecx,65535        ;size of chunks to load.
  8320.     jc    @@1
  8321.     mov    ecx,65535        ;as close to 64k as can get.
  8322. @@1:    mov    ah,3fh
  8323.     int    21h        ;read from the file.
  8324.     popm    ebx,ecx,edx,esi
  8325.     jc    @@2        ;DOS error so exit NOW.
  8326.     movzx    eax,ax        ;get length read.
  8327.     add    esi,eax        ;update length read counter.
  8328.     add    edx,eax        ;move memory pointer.
  8329.     sub    ecx,eax        ;update length counter.
  8330.     jz    @@2        ;read as much as was wanted.
  8331.     or    eax,eax        ;did we read anything?
  8332.     jnz    @@0
  8333. @@2:    mov    eax,esi
  8334.     popm    ecx,edx,esi
  8335.     ret
  8336. ReadFile    endp
  8337.  
  8338.  
  8339. ;-------------------------------------------------------------------------
  8340. ;
  8341. ;Patch exceptions to do register dump and terminate.
  8342. ;
  8343. PatchExc    proc    near
  8344.     push    ds
  8345.     assume ds:nothing
  8346.     mov    ds,cs:apiDDSeg
  8347.     assume ds:_apiCode
  8348. ;
  8349. ;Patch some interrupts.
  8350. ;
  8351.     mov    bl,23h
  8352.     sys    GetVect
  8353.     test    apiSystemFlags,1
  8354.     jz    @@iUse32
  8355.     mov    w[OldInt23],dx
  8356.     mov    w[OldInt23+2],cx
  8357.     jmp    @@iDone3216
  8358. @@iUse32:    mov    d[OldInt23],edx
  8359.     mov    w[OldInt23+4],cx
  8360. @@iDone3216:    mov    edx,offset Int23Handler
  8361.     mov    cx,cs
  8362.     mov    bl,23h
  8363.     sys    SetVect
  8364.     ;
  8365.     mov    bl,24h
  8366.     sys    GetVect
  8367.     test    apiSystemFlags,1
  8368.     jz    @@i24Use32
  8369.     mov    w[OldInt24],dx
  8370.     mov    w[OldInt24+2],cx
  8371.     jmp    @@i24Done3216
  8372. @@i24Use32:    mov    d[OldInt24],edx
  8373.     mov    w[OldInt24+4],cx
  8374. @@i24Done3216:    mov    edx,offset Int24Handler
  8375.     mov    cx,cs
  8376.     mov    bl,24h
  8377.     sys    SetVect
  8378. ;
  8379. ;Patch 1Bh vector.
  8380. ;
  8381.     ;
  8382.     ;Get a call back.
  8383.     ;
  8384.     pushm    ds,es,ds
  8385.     pop    es
  8386.     mov    esi,offset CtrlBrkEvent
  8387.     mov    edi,offset CtrlBrkEventTab
  8388.     push    cs
  8389.     pop    ds
  8390.     sys    GetCallBack
  8391.     popm    ds,es
  8392.     jc    @@0
  8393.  
  8394.     ;
  8395.     ;Get current protected mode 1Bh vector.
  8396.     ;
  8397.     pushm    cx,dx
  8398.     mov    bl,1bh
  8399.     sys    GetVect
  8400.     test    apiSystemFlags,1
  8401.     jz    @@1
  8402.     movzx    edx,dx
  8403. @@1:    mov    d[OldInt1BhP],edx
  8404.     mov    w[OldInt1BhP+4],cx
  8405.     ;
  8406.     ;Install our own handler.
  8407.     ;
  8408.     mov    edx,offset Int1bHandler
  8409.     mov    cx,cs
  8410.     mov    bl,1bh
  8411.     sys    SetVect
  8412.     popm    cx,dx
  8413.  
  8414.     ;
  8415.     ;Get current real mode 1Bh vector.
  8416.     ;
  8417.     pushm    cx,dx
  8418.     mov    al,1bh
  8419.     sys    GetRVect
  8420.     mov    w[OldInt1bh],dx
  8421.     mov    w[OldInt1bh+2],cx
  8422.     popm    cx,dx
  8423.     mov    w[Int1bhcall],dx
  8424.     mov    w[Int1bhcall+2],cx
  8425.     ;
  8426.     ;Install call-back.
  8427.     ;
  8428.     mov    bl,1bh
  8429.     sys    SetRVect
  8430.  
  8431.  
  8432. @@0:    mov    ds,apiDSeg
  8433.     assume ds:_cwMain
  8434.     or    apiExcepPatched,-1
  8435.     assume ds:_apiCode
  8436.     ;
  8437.     pop    ds
  8438.     db 66h
  8439.     retf
  8440. PatchExc    endp
  8441.  
  8442.  
  8443. ;-------------------------------------------------------------------------
  8444. ;
  8445. ;Remove exception patchs.
  8446. ;
  8447. UnPatchExc    proc    near
  8448.     push    ds
  8449.     assume ds:nothing
  8450.     mov    ds,cs:apiDDSeg
  8451.     assume ds:_apiCode
  8452. ;
  8453. ;Release real mode hardware interupt vectors and call back entries.
  8454. ;
  8455.     cmp    d[OldInt1bh],0
  8456.     jz    @@no1b
  8457.     mov    dx,w[OldInt1bh]
  8458.     mov    cx,w[OldInt1bh+2]
  8459.     mov    bl,1bh
  8460.     sys    SetRVect
  8461.     mov    cx,w[Int1bhcall+2]
  8462.     mov    dx,w[Int1bhcall]
  8463.     sys    RelCallBack
  8464.     mov    edx,d[OldInt1bhP]
  8465.     mov    cx,w[OldInt1bhP+4]
  8466.     mov    bl,1bh
  8467.     sys    SetVect
  8468. ;
  8469. @@no1b:    cmp    d[OldInt23],0
  8470.     jz    @@i0
  8471.     test    apiSystemFlags,1
  8472.     jz    @@iUse32
  8473.     mov    dx,w[OldInt23]
  8474.     mov    cx,w[OldInt23+2]
  8475.     jmp    @@iDone3216
  8476. @@iUse32:    mov    edx,d[OldInt23]
  8477.     mov    cx,w[OldInt23+4]
  8478. @@iDone3216:    mov    bl,23h
  8479.     sys    SetVect
  8480. @@i0:    ;
  8481.     cmp    d[OldInt24],0
  8482.     jz    @@i1
  8483.     test    apiSystemFlags,1
  8484.     jz    @@i24Use32
  8485.     mov    dx,w[OldInt24]
  8486.     mov    cx,w[OldInt24+2]
  8487.     jmp    @@i24Done3216
  8488. @@i24Use32:    mov    edx,d[OldInt24]
  8489.     mov    cx,w[OldInt24+4]
  8490. @@i24Done3216:    mov    bl,24h
  8491.     sys    SetVect
  8492. @@i1:    ;
  8493.     pop    ds
  8494.     db 66h
  8495.     retf
  8496. UnPatchExc    endp
  8497.  
  8498.  
  8499. ;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
  8500. CtrlBrkEvent    proc    far
  8501.     push    ax
  8502.     push    ds
  8503.     mov    ds,cs:apiDSeg
  8504.     assume ds:_cwMain
  8505.     test    SystemFlags,1
  8506.     assume ds:_apiCode
  8507.     pop    ds
  8508.     jz    @@start32
  8509.     ;
  8510.     mov    ax,[si]        ;get stacked offset.
  8511.     mov    es:Real_IP[di],ax
  8512.     mov    ax,2[si]
  8513.     mov    es:Real_CS[di],ax
  8514.     mov    ax,4[si]
  8515.     mov    es:Real_Flags[di],ax
  8516.     add    es:Real_SP[di],6
  8517.     jmp    @@start0
  8518.     ;
  8519. @@start32:
  8520. ;    mov    ax,[esi]        ;get stacked offset.
  8521.     mov    ax,[si]        ;get stacked offset. MED 01/24/96
  8522.  
  8523.     mov    es:Real_IP[edi],ax
  8524. ;    mov    ax,2[esi]
  8525.     mov    ax,2[si]     ; MED 01/24/96
  8526.  
  8527.     mov    es:Real_CS[edi],ax
  8528. ;    mov    ax,4[esi]
  8529.     mov    ax,4[si]    ; MED 01/24/96
  8530.  
  8531.     mov    es:Real_Flags[edi],ax
  8532.     add    es:Real_SP[edi],6
  8533.     ;
  8534. @@start0:    pop    ax
  8535.     ;
  8536.     ;Give protected mode handler a shout.
  8537.     ;
  8538.     int    1bh
  8539.     ;
  8540.     ;Go back to caller.
  8541.     ;
  8542.     assume ds:nothing
  8543.     test    cs:apiSystemFlags,1
  8544.     assume ds:_apiCode
  8545.     jz    @@Use32Bit2
  8546.     iret
  8547. @@Use32Bit2:    ;
  8548.     iretd
  8549. ;
  8550. OldInt1bh    dd 0
  8551. Int1bhcall    dd 0
  8552. CtrlBrkEventTab db size RealRegsStruc dup (0)
  8553. CtrlBrkEvent    endp
  8554.  
  8555.  
  8556. ;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
  8557. ;
  8558. ;Base handler for protected mode int 1bh's.
  8559. ;
  8560. Int1bHandler    proc    far
  8561.     push    es
  8562.     pushad
  8563.     assume ds:nothing
  8564.     ;
  8565.     ;Need to chain to origional real mode handler.
  8566.     ;
  8567.     mov    es,cs:apiDDSeg
  8568.     mov    edi,offset Int1bRegs
  8569.     mov    eax,cs:d[OldInt1bh]
  8570.     mov    es:Real_IP[edi],ax
  8571.     shr    eax,16
  8572.     mov    es:Real_CS[edi],ax
  8573.     mov    es:Real_SS[edi],0
  8574.     mov    es:Real_SP[edi],0
  8575.     mov    ax,0302h
  8576.     xor    ecx,ecx
  8577.     xor    ebx,ebx
  8578.     int    31h
  8579.     ;
  8580.     ;Return to caller.
  8581.     ;
  8582.     popad
  8583.     pop    es
  8584.     test    cs:apiSystemFlags,1
  8585.     jz    @@0
  8586.     iret
  8587. @@0:    iretd
  8588.     assume ds:_apiCode
  8589. ;
  8590. OldInt1BhP    df 0
  8591. Int1bRegs    db size RealRegsStruc dup (0)
  8592. Int1bHandler    endp
  8593.  
  8594.  
  8595. ;-------------------------------------------------------------------------
  8596. ;
  8597. ;Handle a ctrl-break key press by terminating this application cleanly.
  8598. ;
  8599. Int23Handler    proc    near
  8600.     assume ds:nothing
  8601.     mov    ds,cs:apiDSeg
  8602.     assume ds:_cwMain
  8603.     pushm    ds,ds,ds
  8604.     popm    es,fs,gs
  8605.     sti
  8606.     jmp    f[TerminationHandler]
  8607.     assume ds:_apiCode
  8608. OldInt23    df 0
  8609. Int23Handler    endp
  8610.  
  8611.  
  8612. ;-------------------------------------------------------------------------
  8613. Int24Handler    proc    near
  8614.     pushm    ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  8615.     assume ds:nothing
  8616.     mov    ds,cs:apiDDSeg
  8617.     assume ds:_apiCode
  8618.     pushm    ds,ds,ds
  8619.     popm    es,fs,gs
  8620.     ;
  8621. @@0:    mov    edx,offset CriticalPrompt
  8622.     mov    ah,9
  8623.     int    21h
  8624.     mov    ah,1
  8625.     int    21h
  8626.     mov    edi,offset CriticalKeys
  8627.     mov    ecx,8
  8628.     cld
  8629.     push    ds
  8630.     pop    es
  8631.     repne    scasb
  8632.     jnz    @@0
  8633.     movzx    eax,b[edi+7]
  8634.     cmp    eax,2
  8635.     jz    @@Terminate
  8636.     popm    ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  8637.     assume ds:nothing
  8638.     test    cs:apiSystemFlags,1
  8639.     assume ds:_apiCode
  8640.     jz    @@Use32_2
  8641.     iret
  8642. @@Use32_2:    ;
  8643.     iretd
  8644.     ;
  8645. @@Terminate:    assume ds:nothing
  8646.     mov    ds,cs:apiDSeg
  8647.     assume ds:_cwMain
  8648.     pushm    ds,ds,ds
  8649.     popm    es,fs,gs
  8650.     sti
  8651.     jmp    f[TerminationHandler]
  8652.     assume ds:_apiCode
  8653. ;
  8654. OldInt24    df 0
  8655. CriticalPrompt    db 13,10,'Critical Error: Abort, Retry, Ignore, Fail? $'
  8656. CriticalKeys    db 'aArRiIfF'
  8657. CriticalCodes    db 2,2,1,1,0,0,3,3
  8658. Int24Handler    endp
  8659.  
  8660.  
  8661. ; remembered to defang this ancient artifact, MED, 11/01/99
  8662. ;-------------------------------------------------------------------------
  8663. DPMICopyCheck    proc    near
  8664. COMMENT !
  8665.     pushf
  8666.     pushm    ax,ds,si
  8667.     assume ds:nothing
  8668.     mov    ds,cs:apiDSeg
  8669.     assume ds:_cwMain
  8670.     lea    si,Copyright
  8671.     add    si,CopyCount
  8672.     cmp    b[si],0
  8673.     jnz    @@0
  8674.     sub    si,CopyCount
  8675.     mov    CopyCount,0
  8676. @@0:    inc    CopyCount
  8677.     mov    al,b[CopyCheck+si]
  8678.     cmp    al,255
  8679.     jz    @@1
  8680.     add    al,44
  8681.     cmp    al,b[si]
  8682.     jz    @@1
  8683.     sub    DPMIStackOff,32
  8684.     ;
  8685. @@1:    popm    ax,ds,si
  8686.     popf
  8687.     assume ds:_apiCode
  8688. END COMMENT !
  8689.     ret
  8690. DPMICopyCheck    endp
  8691.  
  8692.  
  8693. ;-------------------------------------------------------------------------
  8694. Borda    proc    near
  8695.     pushm    ax,dx
  8696.     mov    ah,al
  8697.     mov    dx,3dah
  8698.     in    al,dx
  8699.     mov    dl,0c0h
  8700.     mov    al,11h
  8701.     out    dx,al
  8702.     mov    al,ah
  8703.     out    dx,al
  8704.     mov    al,20h
  8705.     out    dx,al
  8706.     popm    ax,dx
  8707.     ret
  8708. Borda    endp
  8709.  
  8710.  
  8711. ;-------------------------------------------------------------------------
  8712. ;
  8713. apiSystemFlags    dw 0,0
  8714. DescriptorBuffer db 8 dup (?)
  8715. apiDSeg    dw ?
  8716. apiDDSeg    dw ?
  8717. ;
  8718. apiNewHeader    NewHeaderStruc <>    ;make space for a header.
  8719. ;
  8720. apiExeSignature    db ?    ;00 Identifier text.
  8721.     db ?    ;01 /
  8722. apiExeLength    dw ?    ;02 Length of file MOD 512
  8723.     dw ?    ;04 Length of file in 512 byte blocks.
  8724. apiExeRelocNum    dw ?    ;06 Number of relocation items.
  8725. apiExeHeaderSize    dw ?    ;08 Length of header in 16 byte paragraphs.
  8726. apiExeMinAlloc    dw ?    ;0A Minimum number of para's needed above program.
  8727. apiExeMaxAlloc    dw ?    ;0C Maximum number of para's needed above program.
  8728. apiExeStackSeg    dw ?    ;0E Segment displacement of stack module.
  8729. apiExeEntrySP    dw ?    ;10 value for SP at entry.
  8730. apiExeCheckSum    dw ?    ;12 Check sum...
  8731. apiExeEntryIP    dw ?    ;14 Contents of IP at entry.
  8732. apiExeEntryCS    dw ?    ;16 Segment displacement of CS at entry.
  8733. apiExeRelocFirst    dw ?    ;18 First relocation item offset.
  8734. apiExeOverlayNum    db ?    ;1A Overlay number.
  8735. ;
  8736. LastResource    dd 0,0
  8737. ;
  8738. PatchTable    dd 16 dup (0)
  8739. ;
  8740.     include loadle\loadle.asm
  8741.     include decode_c.asm
  8742.  
  8743. mcbLastChunk    dd 0
  8744.  
  8745. ExecMCount    dd 0
  8746.  
  8747. ;
  8748. ;Export table for base PSP. EXPORT's internal functions.
  8749. ;
  8750. apiEXPORT_cwMainCode equ 0
  8751. apiEXPORT_cwMainData equ 1
  8752. apiEXPORT_apiCode equ 2
  8753. apiEXPORT_apiData equ 3
  8754.  
  8755.  
  8756. apiExports    dd 10
  8757. ;
  8758.     dd apiExportName
  8759. ;
  8760.     dd apiExport01
  8761.     dd apiExport02
  8762.     dd apiExport03
  8763.     dd apiExport04
  8764.     dd apiExport05
  8765.     dd apiExport06
  8766.     dd apiExport07
  8767.     dd apiExport08
  8768.     dd apiExport09
  8769.     dd apiExport10
  8770. ;
  8771. apiExportName    db 15,"CAUSEWAY_KERNAL"
  8772. ;
  8773. apiExport01    dd __cwAPI_CreatePSP
  8774.     dw apiEXPORT_apiCode
  8775.     db 17,"__CWAPI_CREATEPSP"
  8776. ;
  8777. apiExport02    dd __cwAPI_DeletePSP
  8778.     dw apiEXPORT_apiCode
  8779.     db 17,"__CWAPI_DELETEPSP"
  8780. ;
  8781. apiExport03    dd __cwAPI_ExecModule
  8782.     dw apiEXPORT_apiCode
  8783.     db 18,"__CWAPI_EXECMODULE"
  8784. ;
  8785. apiExport04    dd __cwAPI_DSizeSelector
  8786.     dw apiEXPORT_apiCode
  8787.     db 21,"__CWAPI_DSIZESELECTOR"
  8788. ;
  8789. apiExport05    dd __cwAPI_FindModule
  8790.     dw apiEXPORT_apiCode
  8791.     db 18,"__CWAPI_FINDMODULE"
  8792. ;
  8793. apiExport06    dd __cwAPI_UnFindModule
  8794.     dw apiEXPORT_apiCode
  8795.     db 20,"__CWAPI_UNFINDMODULE"
  8796. ;
  8797. apiExport07    dd __cwAPI_FindFunction
  8798.     dw apiEXPORT_apiCode
  8799.     db 20,"__CWAPI_FINDFUNCTION"
  8800. ;
  8801. apiExport08    dd __cwAPI_GetMemLinear32
  8802.     dw apiEXPORT_apiCode
  8803.     db 22,"__CWAPI_GETMEMLINEAR32"
  8804. ;
  8805. apiExport09    dd __cwAPI_ResMemLinear32
  8806.     dw apiEXPORT_apiCode
  8807.     db 22,"__CWAPI_RESMEMLINEAR32"
  8808. ;
  8809. apiExport10    dd __cwAPI_RelMemLinear32
  8810.     dw apiEXPORT_apiCode
  8811.     db 22,"__CWAPI_RELMEMLINEAR32"
  8812.  
  8813. __cwAPI_CreatePSP proc far
  8814.     call    CreatePSP
  8815.     ret
  8816. __cwAPI_CreatePSP endp
  8817.  
  8818. __cwAPI_DeletePSP proc far
  8819.     call    DeletePSP
  8820.     ret
  8821. __cwAPI_DeletePSP endp
  8822.  
  8823. __cwAPI_ExecModule proc far
  8824.     call    ExecModule
  8825.     ret
  8826. __cwAPI_ExecModule endp
  8827.  
  8828. __cwAPI_DSizeSelector proc far
  8829.     call    _DSizeSelector
  8830.     ret
  8831. __cwAPI_DSizeSelector endp
  8832.  
  8833. __cwAPI_FindModule proc far
  8834.     call    FindModule
  8835.     ret
  8836. __cwAPI_FindModule endp
  8837.  
  8838. __cwAPI_UnFindModule proc far
  8839.     call    UnFindModule
  8840.     ret
  8841. __cwAPI_UnFindModule endp
  8842.  
  8843. __cwAPI_FindFunction proc far
  8844.     call    FindFunction
  8845.     ret
  8846. __cwAPI_FindFunction endp
  8847.  
  8848. __cwAPI_GetMemLinear32 proc far
  8849.     call    mcbGetMemLinear32
  8850.     ret
  8851. __cwAPI_GetMemLinear32 endp
  8852.  
  8853. __cwAPI_ResMemLinear32 proc far
  8854.     call    mcbResMemLinear32
  8855.     ret
  8856. __cwAPI_ResMemLinear32 endp
  8857.  
  8858. __cwAPI_RelMemLinear32 proc far
  8859.     call    mcbRelMemLinear32
  8860.     ret
  8861. __cwAPI_RelMemLinear32 endp
  8862.  
  8863.  
  8864.     db 4 dup (?)
  8865. _apiCodeEnd    label byte
  8866. _apiCode    ends
  8867.  
  8868.     .286
  8869.  
  8870.