home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland Pascal with Objects 7.0 / WHEREIS.ZIP / IEXECDOS.ASM < prev    next >
Encoding:
Assembly Source File  |  1992-10-27  |  17.2 KB  |  540 lines

  1.  
  2. ;   FILENAME: IEXECDOS.ASM
  3. ;
  4. ;   Copyright (c) 1990, 1992 by Borland International, Inc.
  5. ;
  6. ;   DESCRIPTION: This module implements the routines that handle calling
  7. ;   DOS to perform a command on each file that is found by WHEREIS.
  8. ;   This module uses ideal mode syntax.
  9. ;
  10. ;   This module looks for the location of COMMAND.COM to enable the
  11. ;   running of the commands. Since many matching files may be found,
  12. ;   and COMMAND.COM is called to execute the given DOS command for each
  13. ;   file that is found, it is best if COMMAND.COM is located in a ramdisk.
  14. ;
  15. ;   ASSEMBLY INSTRUCTIONS: To assemble this module use the following
  16. ;   TASM command line.
  17. ;
  18. ;       TASM /m /dMDL=memorymodel iparam
  19. ;
  20. ;   /m in the above command line allows TASM to resolve jumps and other
  21. ;   operations to their shortest form and get rid of extra NOPs.
  22. ;   'memorymodel' in the above command line may be replaced by TINY, SMALL,
  23. ;   MEDIUM, COMPACT, LARGE or HUGE. If assembling this module to run on
  24. ;   a 286/386 machine, turn on the P286 directive in order to take advantage of
  25. ;   286/386 specific instructions. I.E.
  26. ;
  27. ;       TASM /m /dMDL=memorymodel /jP286 iparam
  28. ;
  29.  
  30. ;DO_SAMPLE_COMMAND equ 1      ; Enable this to execute a sample DIR command
  31. ;                             ;   when the command line is being parsed.
  32.  
  33. jumps
  34.  
  35. %tabsize 4
  36.  
  37. ifndef  MDL
  38.     display "Error: This module requires that you provide a memory model"
  39.     display "       definition on the command line. I.E. /dMDL=SMALL."
  40.     err ; Force a fatal error
  41. else
  42.  
  43.     ideal                           ; Use TASM's Ideal mode
  44. %   model   MDL,pascal              ; Define the memory model
  45.  
  46.     include "dos.inc"
  47.     include "idos.inc"
  48.     include "kbd.inc"
  49.     include "iwhglobl.inc"
  50.     include "imacros.mac"
  51.  
  52.     dataseg
  53. NO_COMMAND_GIVEN equ 0
  54. COMMAND_GIVEN    equ 1
  55.     DosCommandGiven   db NO_COMMAND_GIVEN
  56.  
  57. COMMAND_BUFFER_LENGTH equ 200
  58.     ; Stores the command given on command line
  59.     DosCommandBuffer  db COMMAND_BUFFER_LENGTH dup (?)
  60.  
  61. ; The DOS command in quotes will include some special escape sequences
  62. ; that will cause the name of the file to be inserted in various ways.
  63. ;
  64. ;  %1  - The full path, filename and  extension
  65. ;  %2  - Filename and extension (no path)
  66. ;  %3  - Only the path
  67. ;  %4  - Only the filename before the extension followed by a .
  68. ;  %5  - Only the extension, preceeded by a .
  69.  
  70.     ; This is placed at the start of COMMAND.COM command strings.
  71.     StartOfBuff       db '/C ',0
  72.  
  73.     ; Store the actual command that is executed. Any %x directives in
  74.     ; the above command buffer are converted to their actual values
  75.     ; as the above command is transfered into the following buffer.
  76.     ; 32 extra bytes are an overrun buffer.
  77.     CommandToDo       db COMMAND_BUFFER_LENGTH+32 dup (?)
  78.  
  79.     ; Needed for the call to execute COMMAND.COM
  80.     ParamBlock        dw 7 dup (0)
  81.  
  82.     ComspecTag        db 'COMSPEC=',0
  83.  
  84.     ; Pointer into the environment block for start of COMMAND.COM location
  85.     ComspecSeg        dw 0     ;Not changed from zero if no comspec found.
  86.     ComspecOfs        dw ?
  87.  
  88.     MakePascalString  NoComspecMssg,<"COMSPEC= not found in environment!",13,10>
  89.  
  90.     codeseg
  91.  
  92.     ; The environment block is a group of null terminated strings.
  93.     ; A string beginning with zero signals the end of the eviroment block.
  94.  
  95.     proc SearchEnvironment
  96.     ;   This routine searches for a variable in the environment block.
  97.     ;
  98.     ;   Input
  99.     ;       DS:SI - Points to a string like "NAME=" which is to be
  100.     ;               found in the environment. It should be an ASCIIZ string.
  101.     ;   Output
  102.     ;       If the variable is found,
  103.     ;           AL    -  0
  104.     ;           ES:DI -  Points to string after the = sign in the environment.
  105.     ;       If the variable is not found,
  106.     ;           AL is nonzero.
  107.     ;   Registers modified
  108.     ;       all
  109.  
  110.         cld       ;Set direction for scanning to increment
  111.  
  112.         ; Set ES:DI to environment block
  113.         push   ds
  114.         mov    ax,@data   ; Reset to our datasegment since the "NAME="
  115.                           ; might be in another segment.
  116.         mov    ds,ax
  117.         mov    es,[PspAddress]
  118.         mov    es,[es:psp.EnvironmentBlock]
  119.         xor    di,di
  120.         pop    ds
  121.     @@CheckEnvironmentEnd:
  122.         mov    bx,si               ;initialize BX pointer to name to find
  123.         mov    al,[byte es:di]
  124.         or     al,al
  125.         je     @@MatchFailed       ;jump if end is found
  126.  
  127.     @@CheckNextByte:
  128.  
  129.         mov    al,[bx]                  ;get character to match.
  130.  
  131.         or     al,al                    ;if end of name we are done!
  132.         jz     @@MatchCompleted         ;  (AL will be zero)
  133.  
  134.         cmp    al,[byte es:di]          ;compare to char in environment block
  135.         jne    @@FindNextString         ;jump if match failed
  136.         inc    bx
  137.         inc    di
  138.         jmp    @@CheckNextByte
  139.  
  140.     @@FindNextString:
  141.         xor    al,al                    ;scan forward in Environment Block
  142.         mov    cx,0FFFFh                ;for zero byte.
  143.         repnz  scasb
  144.         jmp    @@CheckEnvironmentEnd    ;go compare next string
  145.  
  146.     @@MatchFailed:
  147.         inc    al                       ;return al<>0 as failure flag
  148.  
  149.     @@MatchCompleted:                   ;all matched, return ES:DI pointing
  150.                                         ; to parameter. al = 0
  151.         ret
  152.     endp SearchEnvironment
  153.  
  154.  
  155. ifdef DO_SAMPLE_COMMAND
  156.     ; Show a sample of the proper way to call COMMAND.COM
  157.     dataseg
  158.     SampleCommand db 9,'/C DIR C:',13
  159.     codeseg
  160.     proc SampleDosCommand
  161.     ;   This routine calls COMMAND.COM to do the DIR command.
  162.     ;
  163.         mov     cx,seg SampleCommand
  164.         mov     dx,offset SampleCommand
  165.         call    DoDosCommand
  166.         ret
  167.     endp SampleDosCommand
  168. endif
  169.  
  170.     proc DoDosCommand
  171.     ;   This procedure executes the command string pointed at by DX:CX
  172.     ;   by giving it to COMMAND.COM.
  173.     ;   This routine is not reentrant because of local code segment
  174.     ;   data storage at end of routine.
  175.     ;
  176.     ;   Input
  177.     ;       None
  178.     ;   Output
  179.     ;       None
  180.     ;   Calling conventions
  181.     ;       NA
  182.     ;   Registers modified
  183.     ;       all
  184.  
  185.         push    ds
  186.         mov     ax,seg ParamBlock
  187.         mov     es,ax
  188.         mov     bx,offset ParamBlock
  189.  
  190.         mov     [word es:bx+4],cx   ; Load the location of the command tail
  191.         mov     [word es:bx+2],dx   ;   for the command.
  192.  
  193.         mov     [Orig_SS],SS
  194.         mov     [Orig_SP],SP
  195.  
  196.         mov     ax,[ComSpecSeg]
  197.         or      ax,ax
  198.         jz      @@Skip       ; Skip over EXEC if our segment is still zero.
  199.                              ; That means that no Comspec was found.
  200.  
  201.         mov     dx,[ComspecOfs]
  202.         mov     ds,ax
  203.         
  204.         mov     ax,4b00h
  205.         int     21h
  206.     @@Skip:
  207.         mov     ss,[Orig_SS]
  208.         mov     sp,[Orig_SP]
  209.         pop     ds
  210.         ret
  211.  
  212.     ; Preserves the location of our stack.
  213.     Orig_SS dw ?
  214.     Orig_SP dw ?
  215.     endp DoDosCommand
  216.  
  217.     proc ParseDosCommand
  218.     ;   This procedure initializes all variables and data structures
  219.     ;   used for executing the DOS command.
  220.     ;
  221.     ;   Input
  222.     ;       ES:DI - Points to DOS command which is surrounded by quotes.
  223.     ;               It is a pascal style string
  224.     ;   Output
  225.     ;       Carry set if a command has already been specified
  226.     ;   Calling conventions
  227.     ;       NA
  228.     ;   Registers modified
  229.     ;       all
  230.  
  231.         cmp     [DosCommandGiven],COMMAND_GIVEN
  232.         jne     @@FirstUse
  233.         stc     ; An error because a command was already specified
  234.         jmp     @@Exit
  235.  
  236.     @@FirstUse:
  237.         push    es di           ; Preserve pointer to DOS command
  238.         ; We need to find COMMAND.COM before we can know that we can
  239.         ; do a DOS command.
  240.          mov    si,offset ComspecTag     ;DS:SI string to match
  241.          call   SearchEnvironment        ;go search environment
  242.          or     al,al
  243.          jne    ComspecNotFound
  244.  
  245.          mov    [ComspecSeg],es          ; If it was found, ES:DI is stored.
  246.          mov    [ComspecOfs],di
  247.          jz     FreeExtraMemory
  248.  
  249.     ComspecNotFound:
  250.          call   WritePascalString,ds,offset NoComspecMssg
  251.  
  252.     FreeExtraMemory:
  253.         ; We need to give up extra memory.
  254.         mov     bx,zzzzzseg     ; Location of first segment of free memory
  255.         mov     ax,[PspAddress] ; PSP segment
  256.         sub     bx,ax           ; BX now contains paragraphs used
  257.                                 ;   by this program.
  258.         mov     es,ax
  259.         mov     ah,4ah
  260.         int     21h
  261.  
  262. ifdef DO_SAMPLE_COMMAND
  263.         call    SampleDosCommand
  264. endif
  265.         pop     di es           ; Restore pointer to DOS command
  266.  
  267.         ; Check if the final character is a quote and
  268.         ;   remove it if it is.
  269.         xor     bh,bh           ; Get length of string in BX
  270.         mov     bl,[es:di]
  271.  
  272.         mov     al,[es:di+bx]   ; Load last character of string
  273.         call    IsDelimiter
  274.         jnc     RemoveLeadingQuote
  275.  
  276.     RemoveTrailingQuote:
  277.         dec     ntBlocES:DI]    ; Remove the trailing delimiter
  278.       e   
  279.          kkkkkkkkkkFEC if oul   M 
  280.      ; Res6locES:f string  extra memory.
  281.      EC if oul   M 
  282. ment follow
  283.         mov     bl,[edi]   C stnt
  284.     mov    es,[PspAd  21h
  285.  
  286. ifdef DO_SAMPLE_COtrailing del SampleDosCommaopymov     bx,offoter
  287.       e   
  288. bove co
  289.  
  290.         ; Chec               r     bh,bh     mov    bx,si        jmp  para     mov     bl,[e   ;aopynt
  291.     NA
  292. VEN
  293.  
  294. COMMAND_B,O    jzVEN
  295.  
  296. COMMAND_Brs modified
  297.     ;g
  298.  
  299. ommerve   ; PresemmandGiven],COandGi    ; BX now containventions
  300.     ;       NA
  301.     ;   Registcl
  302.  
  303.      No cmp        stse
  304.  
  305.         deleCommand
  306.    tion of our stackrs modif
  307. ifdef DO_SAExtraMlsComma   aommanE  ret
  308.    ; Preserves thelStrinr are convrine neMMAND
  309. sffoter
  310. Comma+4],cxe thnving delimies thelSE  ret
  311.    ; Prese    ; BD   AL upPh, 
  312.         re inN   
  313.  
  314.    
  315.         re inN     ComspecSeg      e proper way to caE  ret
  316.    ; Preserv.
  317.     Orig_SS dw ?
  318.    is exe   ret
  319.     e      e   
  320. ,OS candGi,a+4]rv.
  321.     Oeacomp inD.COM comCOMMAND.COM lizes all variables and data sax:]
  322.  -     jz:
  323.   n
  324. ;  les and data sd
  325.  -o    jz:
  326. ce D      OS command which is surroundedn at end of routine.
  327.     ;
  328.     ;   Input
  329.     ;       None
  330.     ;   Output
  331.     ;       Nonee  cep   sthe location of the cD   AL upPh,  [ComspecSeg], of the ce inN   
  332.  
  333. ] paragraphs used
  334.    ce inN   ]k]
  335.  
  336.     ;   Calling co  proc P  Calling conventions
  337.     ;       NA
  338.     ;   Registers modifise
  339.         f free lank  mt    eove cox+4],cx   ; LoadDIR C:    ; BX no,
  340.     ;   uto  Registerstions
  341.     ;       NA
  342. s transfere   ; BX now contains paragraphs used
  343.    dCOMMAND.COM ransfere   ; BX now contaikkF     NA
  344. BUFFER_LENGTH          r     bh,bhched, return p   CronmtFound:
  345.          call  o  Paraailio not copye.
  346. ment folliriabp     @@Exit
  347.  
  348.     ote andu
  349.  lerve
  350.    a %gment is still zero.
  351. COMMAND.COM ransfereit
  352.  
  353.     F4],oveult
  354.  
  355. ifdef DOmov   
  356.  
  357.         ; Checcl,c  @@CheckEnvironmentEnd AExtr is a quowhichlow
  358.         mov     jmp  cES:DI]    ; EnvironmentEnd AEx lock is a group of null terminated strings.
  359.     ; A string beginning with zero signals the end of the eviroment block.
  360.  
  361.     proc SearchEnvironment
  362.     ;   This routine searches for a variable in the environment block.
  363.     ;
  364.     ;   Input
  365.     ;       DS:SI - Points to a string like "NAME=" which is to be
  366.     ;               found in the environment. It should be an ASCIIZ string.
  367.     ;   Output
  368.     ;       If the variable is found,
  369.     ;           AL    -  0
  370.     ;           ES:DI -  Points to string after the = sign in the environment.
  371.     ;       If the variable is not found,
  372.     ;           AL is nonzero.
  373.     ;   Registers modified
  374.     ;       all
  375.  
  376.         cld       ;Set direction for scanning to increment
  377.  
  378.         ; Set ES:DI to environment block
  379.         push   ds
  380.         mov    ax,@data   ; Reset to our datasegment since the "NAME="
  381.                           ; might be in another segment.
  382.         mov    ds,ax
  383.         mov    es,[PspAddress]
  384.         mov    es,[es:psp.EnvironmentBlock]
  385.         xor    di,di
  386.         pop    ds
  387.     @@CheckEnvironmentEnd:
  388.         mov    bx,si               ;initialize BX pointer to name to find
  389.         mov    al,[byte es:di]
  390.         or     al,al
  391.         je     @@MatchFailed       ;jump if end is found
  392.  
  393.     @@CheckNextByte:
  394.  
  395.         mov    al,[bx]                  ;get character to match.
  396.  
  397.         or     al,al                    ;if end of name we are done!
  398.         jz     @@MatchCompleted         ;  (AL will be zero)
  399.  
  400.         cmp    al,[byte es:di]          ;compare to char in environment block
  401.         jne    @@FindNextString         ;jump if match failed
  402.         inc    bx
  403.         inc    di
  404.         jmp    @@CheckNextByte
  405.  
  406.     @@FindNextString:
  407.         xor    al,al                    ;scan forward in Environment Block
  408.         mov    cx,0FFFFh                ;for zero byte.
  409.         repnz  scasb
  410.         jmp    @@CheckEnvironmentEnd    ;go compare next string
  411.  
  412.     @@MatchFailed:
  413.         inc    al                       ;return al<>0 as failure flag
  414.  
  415.     @@MatchCompleted:                   ;all matched, return ES:DI pointing
  416.                                         ; to parameter. al = 0
  417.         ret
  418.     endp SearchEnvironment
  419.  
  420.  
  421. ifdef DO_SAMPLE_COMMAND
  422.     ; Show a sample of the proper way to call COMMAND.COM
  423.     dataseg
  424.     SampleCommand db 9,'/C DIR C:',13
  425.     codeseg
  426.     proc SampleDosCommand
  427.     ;   This routine calls COMMAND.COM to do the DIR command.
  428.     ;
  429.         mov     cx,seg SampleCommand
  430.         mov     dx,offset SampleCommand
  431.         call    DoDosCommand
  432.         ret
  433.     endp SampleDosCommand
  434. endif
  435.  
  436.     proc DoDosCommand
  437.     ;   This procedure executes the command string pointed at by DX:CX
  438.     ;   by giving it to COMMAND.COM.
  439.     ;   This routine is not reentrant because of local code segment
  440.     ;   data storage at end of routine.
  441.     ;
  442.     ;   Input
  443.     ;       None
  444.     ;   Output
  445.     ;       None
  446.     ;   Calling conventions
  447.     ;       NA
  448.     ;   Registers modified
  449.     ;       all
  450.  
  451.         push    ds
  452.         mov     ax,seg ParamBlock
  453.         mov     es,ax
  454.         mov     bx,offset ParamBlock
  455.  
  456.         mov     [word es:bx+4],cx   ; Load the location of the command tail
  457.         mov     [word es:bx+2],dx   ;   for the command.
  458.  
  459.         mov     [Orig_SS],SS
  460.         mov     [Orig_SP],SP
  461.  
  462.         mov     ax,[ComSpecSeg]
  463.         or      ax,ax
  464.         jz      @@Skip       ; Skip over EXEC if our segment is still zero.
  465.                              ; That means that no Comspec was found.
  466.  
  467.         mov     dx,[ComspecOfs]
  468.         mov     ds,ax
  469.         
  470.         mov     ax,4b00h
  471.         int     21h
  472.     @@Skip:
  473.         mov     ss,[Orig_SS]
  474.         mov     sp,[Orig_SP]
  475.         pop     ds
  476.         ret
  477.  
  478.     ; Preserves the location of our stack.
  479.     Orig_SS dw ?
  480.     Orig_SP dw ?
  481.     endp DoDosCommand
  482.  
  483.     proc ParseDosCommand
  484.     ;   This procedure initializes all variables and data structures
  485.     ;   used for executing the DOS command.
  486.     ;
  487.     ;   Input
  488.     ;       ES:DI - Points to DOS command which is surrounded by quotes.
  489.     ;               It is a pascal style string
  490.     ;   Output
  491.     ;       Carry set if a command has already been specified
  492.     ;   Calling conventions
  493.     ;       NA
  494.     ;   Registers modified
  495.     ;       all
  496.  
  497.         cmp     [DosCommandGiven],COMMAND_GIVEN
  498.         jne     @@FirstUse
  499.         stc     ; An error because a command was already specified
  500.         jmp     @@Exit
  501.  
  502.     @@FirstUse:
  503.         push    es di           ; Preserve pointer to DOS command
  504.         ; We need to find COMMAND.COM before we can know that we can
  505.         ; do a DOS command.
  506.          mov    si,offset ComspecTag     ;DS:SI string to match
  507.          call   SearchEnvironment        ;go search environment
  508.          or     al,al
  509.          jne    ComspecNotFound
  510.  
  511.          mov    [ComspecSeg],es          ; If it was found, ES:DI is stored.
  512.          mov    [ComspecOfs],di
  513.          jz     FreeExtraMemory
  514.  
  515.     ComspecNotFound:
  516.          call   WritePascalString,ds,offset NoComspecMssg
  517.  
  518.     FreeExtraMemory:
  519.         ; We need to give up extra memory.
  520.         mov     bx,zzzzzseg     ; Location of first segment of free memory
  521.         mov     ax,[PspAddress] ; PSP segment
  522.         sub     bx,ax           ; BX now contains paragraphs used
  523.                                 ;   by this program.
  524.         mov     es,ax
  525.         mov     ah,4ah
  526.         int     21h
  527.  
  528. ifdef DO_SAMPLE_COMMAND
  529.         call    SampleDosCommand
  530. endif
  531.         pop     di es           ; Restore pointer to DOS command
  532.  
  533.         ; Check if the final character is a quote and
  534.         ;   remove it if it is.
  535.         xor     bh,bh           ; Get length of string in BX
  536.         mov     bl,[es:di]
  537.  
  538.         mov     al,[es:di+bx]   ; Load last character of string
  539.         call    IsDelimiter
  540.         jnc     RemoveLeadingQuote
  541.  
  542.     RemoveTrailingQuote:
  543.         dec     ntBlocES:DI]    ; Remove the trailing delimiter
  544.       e   
  545.          kkkkkkkkkkFEC if oul   M 
  546.      ; Res6locES:f string  extra memory.
  547.      EC if oul   M 
  548. ment follow
  549.         mov     bl,[edi]   C stnt
  550.     mov    es,[PspAd  21h
  551.  
  552. ifdef DO_SA