home *** CD-ROM | disk | FTP | other *** search
- /*
- MSTENVP.C
- test bed for different methods of finding the master environment
-
- cl -qc mstenvp.c
- */
-
- #include <stdlib.h>
- #include <dos.h>
-
- typedef unsigned char BYTE;
- typedef unsigned short WORD;
- typedef unsigned long ULONG;
- typedef void far *FP;
-
- #ifndef MK_FP
- #define MK_FP(seg,ofs) ((FP)(((ULONG)(seg) << 16) | (ofs)))
- #endif
-
- #ifdef __TURBOC__
- #define ASM asm
- #else
- #define ASM _asm
- #endif
-
- /**********************************************************************/
-
- #pragma pack(1)
-
- typedef struct {
- BYTE type; /* 'M'=in chain; 'Z'=at end */
- WORD owner; /* PSP of the owner */
- WORD size; /* in 16-byte paragraphs */
- BYTE unused[3];
- BYTE dos4[8];
- } MCB;
-
- MCB far *get_mcb(void)
- {
- ASM mov ah, 52h
- ASM int 21h
- ASM mov dx, es:[bx-2]
- ASM xor ax, ax
- /* in both Microsoft C and Turbo C, far* returned in DX:AX */
- }
-
- #define MCB_FM_SEG(seg) ((seg) - 1)
- #define IS_PSP(mcb) (FP_SEG(mcb) + 1 == (mcb)->owner)
- #define ENV_FM_PSP(psp_seg) (*((WORD far *) MK_FP(psp_seg, 0x2c)))
- #define PARENT(psp_seg) (*((WORD far *) MK_FP(psp_seg, 0x16)))
-
- char far *env(MCB far *mcb)
- {
- char far *e;
- unsigned env_mcb;
- unsigned env_owner;
-
- if (! IS_PSP(mcb))
- return (char far *) 0;
-
- e = MK_FP(ENV_FM_PSP(mcb->owner), 0);
- env_mcb = MCB_FM_SEG(FP_SEG(e));
- env_owner = ((MCB far *) MK_FP(env_mcb, 0))->owner;
- return (env_owner == mcb->owner) ? e : (char far *) 0;
- }
-
- typedef enum { FALSE, TRUE } BOOL;
- typedef BOOL (*WALKFUNC)(MCB far *mcb);
-
- /*
- General-purpose MCB walker.
- The second parameter to walk() is a function that expects an
- MCB pointer, and that returns TRUE to indicate that walk()
- should keep going, and FALSE to indicate that walk() should
- stop.
- */
- BOOL walk(MCB far *mcb, WALKFUNC walker)
- {
- for (;;)
- switch (mcb->type)
- {
- case 'M':
- if (! walker(mcb))
- return FALSE;
- mcb = MK_FP(FP_SEG(mcb) + mcb->size + 1, 0);
- break;
- case 'Z':
- return walker(mcb);
- break;
- default:
- return FALSE; /* error in MCB chain! */
- }
- }
-
- /**********************************************************************/
-
- /* using the GETVECT 2Eh technique (ENVPKG.ASM) */
- void far *mstenvp1(void)
- {
- ASM mov ax, 352eh /* get INT 2Eh vector */
- ASM int 21h
- ASM mov dx, es:[002Ch] /* environment segment */
- ASM xor ax, ax /* return far ptr in DX:AX */
- }
-
- /**********************************************************************/
-
- /* walk MCB chain, looking for very first environment */
- void far *env2 = (void far *) 0;
-
- BOOL walk2(MCB far *mcb)
- {
- if (env2 = env(mcb))
- {
- unsigned psp = FP_SEG(mcb)+1;
- return (PARENT(psp) == psp) ? FALSE /*found it!*/ : TRUE;
- }
- else
- return TRUE; /* keep going */
- }
-
- void far *mstenvp2(void)
- {
- walk(get_mcb(), walk2);
- return env2;
- }
-
- /**********************************************************************/
-
- /* walk MCB chain, looking for very LAST env addr > PSP addr */
- void far *env3 = (void far *) 0;
-
- #define NORMALIZE(fp) (FP_SEG(fp) + (FP_OFF(fp) >> 4))
-
- BOOL walk3(MCB far *mcb)
- {
- void far *fp;
- /* if env seg at greater address than PSP, then
- candidate for master env -- we'll take last */
- if (fp = env(mcb))
- if (NORMALIZE(fp) > (FP_SEG(mcb)+1))
- env3 = fp;
- return TRUE;
- }
-
- void far *mstenvp3(void)
- {
- walk(get_mcb(), walk3);
- return env3;
- }
-
- /**********************************************************************/
-
- /* walk MCB chain, looking for very first environment belonging
- to PSP which is its own parent */
- void far *env4 = (void far *) 0;
-
- #define PARENT(psp_seg) (*((WORD far *) MK_FP(psp_seg, 0x16)))
-
- BOOL walk4(MCB far *mcb)
- {
- if (env4 = env(mcb))
- {
- unsigned psp = FP_SEG(mcb) + 1;
- return (PARENT(psp) == psp) ? FALSE /*found it!*/ : TRUE;
- }
- else
- return TRUE; /* keep going */
- }
-
- void far *mstenvp4(void)
- {
- walk(get_mcb(), walk4);
- return env4;
- }
-
- /**********************************************************************/
-
- main()
- {
- printf("GETVECT 2Eh method; mstenvp1 = %Fp\n", mstenvp1());
- printf("WALK MCB method; mstenvp2 = %Fp\n", mstenvp2());
- printf("WALK MCB/LAST method; mstenvp3 = %Fp\n", mstenvp3());
- printf("WALK MCB/OWN PARENT; mstenvp4 = %Fp\n", mstenvp4());
- }
-