home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c005 / 4.ddi / C / PCREMOVE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-13  |  6.3 KB  |  186 lines

  1. /**
  2. *
  3. * Name        pcremove -- Remove resident program
  4. *
  5. * Synopsis    ercode = pcremove(psp_seg);
  6. *
  7. *        int     ercode   Error code from MMFREE:  0 if okay,
  8. *                  nonzero if error.
  9. *        unsigned psp_seg  Segment of Program Segment Prefix
  10. *                  of resident program.
  11. *
  12. * Description    This function removes from memory a program that has
  13. *        previously terminated and stayed resident via PCRESEXT.
  14. *
  15. *        WARNING:  Any interrupt vectors or chained interrupt
  16. *        service that invoke any portion of the resident program
  17. *        MUST be re-vectored or otherwise disabled BEFORE the
  18. *        program is removed.  Serious problems may result
  19. *        otherwise.
  20. *
  21. * Method    This function works by following the chain of DOS memory
  22. *        control blocks via get_memctrl().  The chain of control
  23. *        blocks are located at increasing memory addresses, so we
  24. *        begin searching at psp_seg, its environment segment, or
  25. *        the calling program's PSP or environment, whichever has
  26. *        the lowest address.  For each control block that belongs
  27. *        to psp_seg, we free the associated memory block via DOS
  28. *        function 0x49.    Any associated memory blocks residing at
  29. *        lower addresses than our starting point will remain
  30. *        reserved.
  31. *
  32. * Version    3.00 (C)Copyright Blaise Computing Inc.  1986,1987
  33. *
  34. * Version    3.02 March 31, 1987
  35. *        Rewrote to trace DOS memory control block chain to find
  36. *            more memory blocks belonging to the removed program.
  37. *
  38. **/
  39.  
  40. #include <bisr.h>
  41. #include <bmemory.h>
  42.  
  43. typedef struct              /* MEMCTRL:  DOS memory control block   */
  44. {                  /*   structure.                  */
  45.                   /*                      */
  46.     char     _dummy;          /* Dummy to force word alignment of     */
  47.                   /*   unsigned members, so no waste      */
  48.                   /*   space appears within structure.    */
  49.                   /*                      */
  50.                   /* Actual 16-byte copy of control block */
  51.                   /* starts here:                  */
  52.                   /*                      */
  53.     char     ident;          /* Identifying signature.           */
  54.     unsigned owner_psp;       /* Segment address of owner process's   */
  55.                   /*   PSP.                   */
  56.     unsigned size;          /* Size of memory block in paragraphs.  */
  57.     char     _reserved[11];
  58. } MEMCTRL;
  59.  
  60. static int get_memctrl(unsigned,MEMCTRL *,unsigned *);      /* Internal */
  61.  
  62. #define  PSP_ENV_OFFSET  0x2c          /* Offset of environment within */
  63.                       /* PSP                  */
  64.  
  65. int pcremove(psp_seg)
  66. unsigned psp_seg;
  67. {
  68.     unsigned env_seg;          /* Segment of resident program's        */
  69.                   /* environment                  */
  70.     unsigned my_env_seg;      /* Segment of this program's environment*/
  71.  
  72.     ADS      env_ads;          /* Address of env_seg              */
  73.     ADS      my_env_ads;      /* Address of my_env_seg              */
  74.     ADS      psp_ads;          /* Address of resident program's PSP or */
  75.                   /* this program's PSP.                  */
  76.  
  77.     unsigned memblock,nextblock;
  78.     int      result;
  79.     MEMCTRL  ctlblock;
  80.  
  81.     psp_ads.s = psp_seg;          /* Fetch segment of resident    */
  82.     psp_ads.r = PSP_ENV_OFFSET;       /* program's environment.       */
  83.     utabsptr((char *) &env_seg,&env_ads);
  84.     utslmove(&psp_ads,&env_ads,sizeof(env_seg));
  85.  
  86.     psp_ads.s = utpspseg;          /* Fetch segment of caller's    */
  87.                       /* environment.              */
  88.     utabsptr((char *) &my_env_seg,&my_env_ads);
  89.     utslmove(&psp_ads,&my_env_ads,sizeof(my_env_seg));
  90.  
  91.     result = 9;               /* In case first block address  */
  92.                       /* is bad, return 9 (Invalid    */
  93.                       /* memory block).           */
  94.  
  95.     /* Begin memory block search as low in memory as possible:          */
  96.     /* at PSP or environment of this program or of resident program.  */
  97.  
  98.     for (memblock  = min(env_seg,min(my_env_seg,min(utpspseg,psp_seg)));
  99.      memblock != 0;
  100.      memblock  = nextblock)
  101.     {
  102.     if (   9 != get_memctrl(memblock,&ctlblock,&nextblock)
  103.                           /* If block okay    */
  104.         && ctlblock.owner_psp == psp_seg)      /* and belongs to   */
  105.     {                      /*   psp_seg,       */
  106.         result = mmfree(memblock);        /* then free the block.   */
  107.         if (result != 0)
  108.         break;                /* Quit if error.          */
  109.     }
  110.     }
  111.  
  112.     return result;
  113. }
  114.  
  115. /**
  116. *
  117. * Name        get_memctrl -- Retrieve a DOS memory control block
  118. *
  119. * Synopsis    ercode = get_memctrl(memblk,pctrlblk,pnextblk);
  120. *
  121. *        int ercode      0  if memblk is a legitimate DOS
  122. *                     memory block, but not the last;
  123. *                  9 if memblk is not a legitimate
  124. *                     DOS memory block;
  125. *                  18 if memblk is the last memory block.
  126. *        unsigned memblk   Segment address of DOS memory block
  127. *                  as allocated by DOS function 0x48.
  128. *        MEMCTRL *pctrlblk Address of structure in which to
  129. *                  return copy of memory control block
  130. *                  associated with memblk.
  131. *        unsigned *pnextblk
  132. *                  Segment of next memory block,
  133. *                  or 0 if memblk is invalid or if
  134. *                  there is no next block.
  135. *
  136. * Description    This function fetches a copy of the control block
  137. *        associated with a DOS memory block and returns the
  138. *        segment address of the next memory block.
  139. *
  140. *        The control block is a 16-byte data structure located
  141. *        exactly 16 bytes (one paragraph) before the memory block
  142. *        (i.e., at segment (memblk-1), offset 0).  Its leading
  143. *        byte should be 'M' or 'Z'; a 'Z' indicates the final
  144. *        block in the chain.
  145. *
  146. *        This function fails if memblk is not a
  147. *        currently-allocated DOS memory block.  In that case 9 is
  148. *        returned as the value of the function.
  149. **/
  150.  
  151. static int get_memctrl(memblk,pctrlblk,pnextblk)
  152. unsigned memblk;
  153. MEMCTRL  *pctrlblk;
  154. unsigned *pnextblk;
  155. {
  156.     register int result;
  157.     ADS      mem_ads;          /* Address of actual control    */
  158.                       /* block.               */
  159.     ADS      blk_ads;          /* Address of caller's copy of  */
  160.                       /* control block.           */
  161.  
  162.     utabsptr(&pctrlblk->ident,&blk_ads);
  163.     mem_ads.s = memblk - 1;
  164.     mem_ads.r = 0;
  165.     utslmove(&mem_ads,&blk_ads,16);          /* Fetch 16 bytes.  */
  166.  
  167.     switch (pctrlblk->ident)
  168.     {
  169.     case 'M':                     /* Valid memory block, not the  */
  170.         result    = 0;          /*   last.              */
  171.         *pnextblk = memblk + pctrlblk->size + 1;
  172.         break;
  173.  
  174.     case 'Z':                     /* Last memory block in the     */
  175.         result    = 18;          /* chain.               */
  176.         *pnextblk = 0;
  177.         break;
  178.  
  179.     default:              /* Invalid memory block.          */
  180.         result    = 9;
  181.         *pnextblk = 0;
  182.         break;
  183.     }
  184.     return result;
  185. }
  186.