home *** CD-ROM | disk | FTP | other *** search
- /**
- *
- * Name pcremove -- Remove resident program
- *
- * Synopsis ercode = pcremove(psp_seg);
- *
- * int ercode Error code from MMFREE: 0 if okay,
- * nonzero if error.
- * unsigned psp_seg Segment of Program Segment Prefix
- * of resident program.
- *
- * Description This function removes from memory a program that has
- * previously terminated and stayed resident via PCRESEXT.
- *
- * WARNING: Any interrupt vectors or chained interrupt
- * service that invoke any portion of the resident program
- * MUST be re-vectored or otherwise disabled BEFORE the
- * program is removed. Serious problems may result
- * otherwise.
- *
- * Method This function works by following the chain of DOS memory
- * control blocks via get_memctrl(). The chain of control
- * blocks are located at increasing memory addresses, so we
- * begin searching at psp_seg, its environment segment, or
- * the calling program's PSP or environment, whichever has
- * the lowest address. For each control block that belongs
- * to psp_seg, we free the associated memory block via DOS
- * function 0x49. Any associated memory blocks residing at
- * lower addresses than our starting point will remain
- * reserved.
- *
- * Version 3.00 (C)Copyright Blaise Computing Inc. 1986,1987
- *
- * Version 3.02 March 31, 1987
- * Rewrote to trace DOS memory control block chain to find
- * more memory blocks belonging to the removed program.
- *
- **/
-
- #include <bisr.h>
- #include <bmemory.h>
-
- typedef struct /* MEMCTRL: DOS memory control block */
- { /* structure. */
- /* */
- char _dummy; /* Dummy to force word alignment of */
- /* unsigned members, so no waste */
- /* space appears within structure. */
- /* */
- /* Actual 16-byte copy of control block */
- /* starts here: */
- /* */
- char ident; /* Identifying signature. */
- unsigned owner_psp; /* Segment address of owner process's */
- /* PSP. */
- unsigned size; /* Size of memory block in paragraphs. */
- char _reserved[11];
- } MEMCTRL;
-
- static int get_memctrl(unsigned,MEMCTRL *,unsigned *); /* Internal */
-
- #define PSP_ENV_OFFSET 0x2c /* Offset of environment within */
- /* PSP */
-
- int pcremove(psp_seg)
- unsigned psp_seg;
- {
- unsigned env_seg; /* Segment of resident program's */
- /* environment */
- unsigned my_env_seg; /* Segment of this program's environment*/
-
- ADS env_ads; /* Address of env_seg */
- ADS my_env_ads; /* Address of my_env_seg */
- ADS psp_ads; /* Address of resident program's PSP or */
- /* this program's PSP. */
-
- unsigned memblock,nextblock;
- int result;
- MEMCTRL ctlblock;
-
- psp_ads.s = psp_seg; /* Fetch segment of resident */
- psp_ads.r = PSP_ENV_OFFSET; /* program's environment. */
- utabsptr((char *) &env_seg,&env_ads);
- utslmove(&psp_ads,&env_ads,sizeof(env_seg));
-
- psp_ads.s = utpspseg; /* Fetch segment of caller's */
- /* environment. */
- utabsptr((char *) &my_env_seg,&my_env_ads);
- utslmove(&psp_ads,&my_env_ads,sizeof(my_env_seg));
-
- result = 9; /* In case first block address */
- /* is bad, return 9 (Invalid */
- /* memory block). */
-
- /* Begin memory block search as low in memory as possible: */
- /* at PSP or environment of this program or of resident program. */
-
- for (memblock = min(env_seg,min(my_env_seg,min(utpspseg,psp_seg)));
- memblock != 0;
- memblock = nextblock)
- {
- if ( 9 != get_memctrl(memblock,&ctlblock,&nextblock)
- /* If block okay */
- && ctlblock.owner_psp == psp_seg) /* and belongs to */
- { /* psp_seg, */
- result = mmfree(memblock); /* then free the block. */
- if (result != 0)
- break; /* Quit if error. */
- }
- }
-
- return result;
- }
-
- /**
- *
- * Name get_memctrl -- Retrieve a DOS memory control block
- *
- * Synopsis ercode = get_memctrl(memblk,pctrlblk,pnextblk);
- *
- * int ercode 0 if memblk is a legitimate DOS
- * memory block, but not the last;
- * 9 if memblk is not a legitimate
- * DOS memory block;
- * 18 if memblk is the last memory block.
- * unsigned memblk Segment address of DOS memory block
- * as allocated by DOS function 0x48.
- * MEMCTRL *pctrlblk Address of structure in which to
- * return copy of memory control block
- * associated with memblk.
- * unsigned *pnextblk
- * Segment of next memory block,
- * or 0 if memblk is invalid or if
- * there is no next block.
- *
- * Description This function fetches a copy of the control block
- * associated with a DOS memory block and returns the
- * segment address of the next memory block.
- *
- * The control block is a 16-byte data structure located
- * exactly 16 bytes (one paragraph) before the memory block
- * (i.e., at segment (memblk-1), offset 0). Its leading
- * byte should be 'M' or 'Z'; a 'Z' indicates the final
- * block in the chain.
- *
- * This function fails if memblk is not a
- * currently-allocated DOS memory block. In that case 9 is
- * returned as the value of the function.
- **/
-
- static int get_memctrl(memblk,pctrlblk,pnextblk)
- unsigned memblk;
- MEMCTRL *pctrlblk;
- unsigned *pnextblk;
- {
- register int result;
- ADS mem_ads; /* Address of actual control */
- /* block. */
- ADS blk_ads; /* Address of caller's copy of */
- /* control block. */
-
- utabsptr(&pctrlblk->ident,&blk_ads);
- mem_ads.s = memblk - 1;
- mem_ads.r = 0;
- utslmove(&mem_ads,&blk_ads,16); /* Fetch 16 bytes. */
-
- switch (pctrlblk->ident)
- {
- case 'M': /* Valid memory block, not the */
- result = 0; /* last. */
- *pnextblk = memblk + pctrlblk->size + 1;
- break;
-
- case 'Z': /* Last memory block in the */
- result = 18; /* chain. */
- *pnextblk = 0;
- break;
-
- default: /* Invalid memory block. */
- result = 9;
- *pnextblk = 0;
- break;
- }
- return result;
- }