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    mov    es,[PspAd  21h
  284.  
  285. ifdef DO_SAMPLE_COtrailing del SampleDosCommaopymov     bx,offoter
  286.       e   bove co
  287.  
  288.         ; Chec               r     bh,bh     mov    bx,si        jmp  para     mov     bl,[e   ;aopynt    NA
  289. VEN
  290.  
  291. COMMAND_B,O    jzVEN
  292.  
  293. COMMAND_Brs modified
  294.     ;g
  295. ommerve   ; PresemmandGiven],COandGi    ; BX now containventions
  296.     ;       NA
  297.     ;   Registcl
  298.  
  299.      No cmp        stse
  300.  
  301.         deleCommand
  302.    tion of our stackrs modif
  303. ifdef DO_SAExtraMlsComma   aommanE  ret   ; Preserves thelStrinr are convrine neMMAND
  304. sffoter
  305. Comma+4],cxe thnving delimies thelSE  ret   ; Prese    ; BD   AL upPh, 
  306.         re inN   
  307.  
  308.    
  309.         re inN     ComspecSeg      e proper way to caE  ret   ; Preserv.
  310.     Orig_SS dw ?
  311.    is exe   ret
  312.     e      e   ,OS candGi,a+4]rv.
  313.     Oeacomp inD.COM comCOMMAND.COM lizes all variables and data sax:]
  314.  -     jz:
  315.   n
  316. ;  les and data sd
  317.  -o    jz:
  318. ce D      OS command which is surroundedn at end of routine.
  319.     ;
  320.     ;   Input
  321.     ;       None
  322.     ;   Output
  323.     ;       Nonee  cep   sthe location of the cD   AL upPh,  [ComspecSeg], of the ce inN   
  324.  
  325. ] paragraphs used
  326.    ce inN   ]k]
  327.     ;   Calling co  proc P  Calling conventions
  328.     ;       NA
  329.     ;   Registers modifise
  330.         f free lank  mt    eove cox+4],cx   ; LoadDIR C:    ; BX no,
  331.     ;   uto  Registerstions
  332.     ;       NA
  333. s transfere   ; BX now contains paragraphs used
  334.    dCOMMAND.COM ransfere   ; BX now contaikkF     NABUFFER_LENGTH          r     bh,bhched, return p   CronmtFound:
  335.          call  o  Paraailio not copye.
  336. ment folliriabp     @@Exit
  337.  
  338.     ote andu
  339.  lerve
  340.    a %gment is still zero.COMMAND.COM ransfereit
  341.  
  342.     F4],oveult
  343.  
  344. ifdef DOmov   
  345.  
  346.         ; Checcl,c  @@CheckEnvironmentEnd AExtr is a quowhichlow
  347.         mov     jmp  cES:DI]    ; EnvironmentEnd AEx lock is a group of null terminated strings.
  348.     ; A string beginning with zero signals the end of the eviroment block.
  349.  
  350.     proc SearchEnvironment
  351.     ;   This routine searches for a variable in the environment block.
  352.     ;
  353.     ;   Input
  354.     ;       DS:SI - Points to a string like "NAME=" which is to be
  355.     ;               found in the environment. It should be an ASCIIZ string.
  356.     ;   Output
  357.     ;       If the variable is found,
  358.     ;           AL    -  0
  359.     ;           ES:DI -  Points to string after the = sign in the environment.
  360.     ;       If the variable is not found,
  361.     ;           AL is nonzero.
  362.     ;   Registers modified
  363.     ;       all
  364.  
  365.         cld       ;Set direction for scanning to increment
  366.  
  367.         ; Set ES:DI to environment block
  368.         push   ds
  369.         mov    ax,@data   ; Reset to our datasegment since the "NAME="
  370.                           ; might be in another segment.
  371.         mov    ds,ax
  372.         mov    es,[PspAddress]
  373.         mov    es,[es:psp.EnvironmentBlock]
  374.         xor    di,di
  375.         pop    ds
  376.     @@CheckEnvironmentEnd:
  377.         mov    bx,si               ;initialize BX pointer to name to find
  378.         mov    al,[byte es:di]
  379.         or     al,al
  380.         je     @@MatchFailed       ;jump if end is found
  381.  
  382.     @@CheckNextByte:
  383.  
  384.         mov    al,[bx]                  ;get character to match.
  385.  
  386.         or     al,al                    ;if end of name we are done!
  387.         jz     @@MatchCompleted         ;  (AL will be zero)
  388.  
  389.         cmp    al,[byte es:di]          ;compare to char in environment block
  390.         jne    @@FindNextString         ;jump if match failed
  391.         inc    bx
  392.         inc    di
  393.         jmp    @@CheckNextByte
  394.  
  395.     @@FindNextString:
  396.         xor    al,al                    ;scan forward in Environment Block
  397.         mov    cx,0FFFFh                ;for zero byte.
  398.         repnz  scasb
  399.         jmp    @@CheckEnvironmentEnd    ;go compare next string
  400.  
  401.     @@MatchFailed:
  402.         inc    al                       ;return al<>0 as failure flag
  403.  
  404.     @@MatchCompleted:                   ;all matched, return ES:DI pointing
  405.                                         ; to parameter. al = 0
  406.         ret
  407.     endp SearchEnvironment
  408.  
  409.  
  410. ifdef DO_SAMPLE_COMMAND
  411.     ; Show a sample of the proper way to call COMMAND.COM
  412.     dataseg
  413.     SampleCommand db 9,'/C DIR C:',13
  414.     codeseg
  415.     proc SampleDosCommand
  416.     ;   This routine calls COMMAND.COM to do the DIR command.
  417.     ;
  418.         mov     cx,seg SampleCommand
  419.         mov     dx,offset SampleCommand
  420.         call    DoDosCommand
  421.         ret
  422.     endp SampleDosCommand
  423. endif
  424.  
  425.     proc DoDosCommand
  426.     ;   This procedure executes the command string pointed at by DX:CX
  427.     ;   by giving it to COMMAND.COM.
  428.     ;   This routine is not reentrant because of local code segment
  429.     ;   data storage at end of routine.
  430.     ;
  431.     ;   Input
  432.     ;       None
  433.     ;   Output
  434.     ;       None
  435.     ;   Calling conventions
  436.     ;       NA
  437.     ;   Registers modified
  438.     ;       all
  439.  
  440.         push    ds
  441.         mov     ax,seg ParamBlock
  442.         mov     es,ax
  443.         mov     bx,offset ParamBlock
  444.  
  445.         mov     [word es:bx+4],cx   ; Load the location of the command tail
  446.         mov     [word es:bx+2],dx   ;   for the command.
  447.  
  448.         mov     [Orig_SS],SS
  449.         mov     [Orig_SP],SP
  450.  
  451.         mov     ax,[ComSpecSeg]
  452.         or      ax,ax
  453.         jz      @@Skip       ; Skip over EXEC if our segment is still zero.
  454.                              ; That means that no Comspec was found.
  455.  
  456.         mov     dx,[ComspecOfs]
  457.         mov     ds,ax
  458.         
  459.         mov     ax,4b00h
  460.         int     21h
  461.     @@Skip:
  462.         mov     ss,[Orig_SS]
  463.         mov     sp,[Orig_SP]
  464.         pop     ds
  465.         ret
  466.  
  467.     ; Preserves the location of our stack.
  468.     Orig_SS dw ?
  469.     Orig_SP dw ?
  470.     endp DoDosCommand
  471.  
  472.     proc ParseDosCommand
  473.     ;   This procedure initializes all variables and data structures
  474.     ;   used for executing the DOS command.
  475.     ;
  476.     ;   Input
  477.     ;       ES:DI - Points to DOS command which is surrounded by quotes.
  478.     ;               It is a pascal style string
  479.     ;   Output
  480.     ;       Carry set if a command has already been specified
  481.     ;   Calling conventions
  482.     ;       NA
  483.     ;   Registers modified
  484.     ;       all
  485.  
  486.         cmp     [DosCommandGiven],COMMAND_GIVEN
  487.         jne     @@FirstUse
  488.         stc     ; An error because a command was already specified
  489.         jmp     @@Exit
  490.  
  491.     @@FirstUse:
  492.         push    es di           ; Preserve pointer to DOS command
  493.         ; We need to find COMMAND.COM before we can know that we can
  494.         ; do a DOS command.
  495.          mov    si,offset ComspecTag     ;DS:SI string to match
  496.          call   SearchEnvironment        ;go search environment
  497.          or     al,al
  498.          jne    ComspecNotFound
  499.  
  500.          mov    [ComspecSeg],es          ; If it was found, ES:DI is stored.
  501.          mov    [ComspecOfs],di
  502.          jz     FreeExtraMemory
  503.  
  504.     ComspecNotFound:
  505.          call   WritePascalString,ds,offset NoComspecMssg
  506.  
  507.     FreeExtraMemory:
  508.         ; We need to give up extra memory.
  509.         mov     bx,zzzzzseg     ; Location of first segment of free memory
  510.         mov     ax,[PspAddress] ; PSP segment
  511.         sub     bx,ax           ; BX now contains paragraphs used
  512.                                 ;   by this program.
  513.         mov     es,ax
  514.         mov     ah,4ah
  515.         int     21h
  516.  
  517. ifdef DO_SAMPLE_COMMAND
  518.         call    SampleDosCommand
  519. endif
  520.         pop     di es           ; Restore pointer to DOS command
  521.  
  522.         ; Check if the final character is a quote and
  523.         ;   remove it if it is.
  524.         xor     bh,bh           ; Get length of string in BX
  525.         mov     bl,[es:di]
  526.  
  527.         mov     al,[es:di+bx]   ; Load last character of string
  528.         call    IsDelimiter
  529.         jnc     RemoveLeadingQuote
  530.  
  531.     RemoveTrailingQuote:
  532.         dec     ntBlocES:DI]    ; Remove the trailing delimiter
  533.       e   
  534.          kkkkkkkkkkFEC if oul   M 
  535.      ; Res6locES:f string  extra memory.
  536.      EC if oul   M 
  537. ment follow
  538.         mov     bl,[edi]   C stnt    mov    es,[PspAd  21h
  539.  
  540. ifdef DO_SA