home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l440 / 2.ddi / CHAP6 / MSTENVP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-27  |  4.6 KB  |  186 lines

  1. /* 
  2. MSTENVP.C 
  3. test bed for different methods of finding the master environment
  4.  
  5. cl -qc mstenvp.c
  6. */
  7.  
  8. #include <stdlib.h>
  9. #include <dos.h>
  10.  
  11. typedef unsigned char BYTE;
  12. typedef unsigned short WORD;
  13. typedef unsigned long ULONG;
  14. typedef void far *FP;
  15.  
  16. #ifndef MK_FP
  17. #define MK_FP(seg,ofs)  ((FP)(((ULONG)(seg) << 16) | (ofs)))
  18. #endif
  19.  
  20. #ifdef __TURBOC__
  21. #define ASM asm
  22. #else
  23. #define ASM _asm
  24. #endif
  25.  
  26. /**********************************************************************/
  27.  
  28. #pragma pack(1)
  29.  
  30. typedef struct {
  31.     BYTE type;          /* 'M'=in chain; 'Z'=at end */
  32.     WORD owner;         /* PSP of the owner */
  33.     WORD size;          /* in 16-byte paragraphs */
  34.     BYTE unused[3];
  35.     BYTE dos4[8];
  36.     } MCB;
  37.  
  38. MCB far *get_mcb(void)
  39. {
  40.     ASM mov ah, 52h
  41.     ASM int 21h
  42.     ASM mov dx, es:[bx-2]
  43.     ASM xor ax, ax
  44.     /* in both Microsoft C and Turbo C, far* returned in DX:AX */
  45. }
  46.  
  47. #define MCB_FM_SEG(seg)     ((seg) - 1)
  48. #define IS_PSP(mcb)         (FP_SEG(mcb) + 1 == (mcb)->owner)
  49. #define ENV_FM_PSP(psp_seg) (*((WORD far *) MK_FP(psp_seg, 0x2c)))
  50. #define PARENT(psp_seg)     (*((WORD far *) MK_FP(psp_seg, 0x16)))
  51.  
  52. char far *env(MCB far *mcb)
  53. {
  54.     char far *e;
  55.     unsigned env_mcb;
  56.     unsigned env_owner;
  57.     
  58.     if (! IS_PSP(mcb))
  59.         return (char far *) 0;
  60.     
  61.     e = MK_FP(ENV_FM_PSP(mcb->owner), 0);
  62.     env_mcb = MCB_FM_SEG(FP_SEG(e));
  63.     env_owner = ((MCB far *) MK_FP(env_mcb, 0))->owner;
  64.     return (env_owner == mcb->owner) ? e : (char far *) 0;
  65. }
  66.  
  67. typedef enum { FALSE, TRUE } BOOL;
  68. typedef BOOL (*WALKFUNC)(MCB far *mcb);
  69.  
  70. /*
  71.     General-purpose MCB walker.
  72.     The second parameter to walk() is a function that expects an 
  73.     MCB pointer, and that returns TRUE to indicate that walk()
  74.     should keep going, and FALSE to indicate that walk() should
  75.     stop.
  76. */
  77. BOOL walk(MCB far *mcb, WALKFUNC walker)
  78. {
  79.     for (;;)
  80.         switch (mcb->type)
  81.         {
  82.             case 'M':
  83.                 if (! walker(mcb))
  84.                     return FALSE;
  85.                 mcb = MK_FP(FP_SEG(mcb) + mcb->size + 1, 0);
  86.                 break;
  87.             case 'Z':
  88.                 return walker(mcb);
  89.                 break;
  90.             default:
  91.                 return FALSE;   /* error in MCB chain! */
  92.         }
  93. }
  94.  
  95. /**********************************************************************/
  96.     
  97. /* using the GETVECT 2Eh technique (ENVPKG.ASM) */
  98. void far *mstenvp1(void)
  99. {
  100.     ASM mov ax, 352eh       /* get INT 2Eh vector */
  101.     ASM int 21h
  102.     ASM mov dx, es:[002Ch]  /* environment segment */
  103.     ASM xor ax, ax          /* return far ptr in DX:AX */
  104. }
  105.  
  106. /**********************************************************************/
  107.  
  108. /* walk MCB chain, looking for very first environment */
  109. void far *env2 = (void far *) 0;
  110.  
  111. BOOL walk2(MCB far *mcb)
  112. {
  113.     if (env2 = env(mcb))
  114.     {
  115.         unsigned psp = FP_SEG(mcb)+1;
  116.         return (PARENT(psp) == psp) ? FALSE /*found it!*/ : TRUE;
  117.     }
  118.     else
  119.         return TRUE;    /* keep going */
  120. }
  121.  
  122. void far *mstenvp2(void)
  123. {
  124.     walk(get_mcb(), walk2);
  125.     return env2;
  126. }
  127.  
  128. /**********************************************************************/
  129.  
  130. /* walk MCB chain, looking for very LAST env addr > PSP addr */
  131. void far *env3 = (void far *) 0;
  132.  
  133. #define NORMALIZE(fp)   (FP_SEG(fp) + (FP_OFF(fp) >> 4))
  134.  
  135. BOOL walk3(MCB far *mcb)
  136. {
  137.     void far *fp;
  138.     /* if env seg at greater address than PSP, then
  139.        candidate for master env -- we'll take last */
  140.     if (fp = env(mcb))
  141.         if (NORMALIZE(fp) > (FP_SEG(mcb)+1))
  142.             env3 = fp;
  143.     return TRUE;
  144. }
  145.  
  146. void far *mstenvp3(void)
  147. {
  148.     walk(get_mcb(), walk3);
  149.     return env3;
  150. }
  151.  
  152. /**********************************************************************/
  153.  
  154. /* walk MCB chain, looking for very first environment belonging
  155.    to PSP which is its own parent */
  156. void far *env4 = (void far *) 0;
  157.  
  158. #define PARENT(psp_seg)     (*((WORD far *) MK_FP(psp_seg, 0x16)))
  159.  
  160. BOOL walk4(MCB far *mcb)
  161. {
  162.     if (env4 = env(mcb))
  163.     {
  164.         unsigned psp = FP_SEG(mcb) + 1;
  165.         return (PARENT(psp) == psp) ? FALSE /*found it!*/ : TRUE;
  166.     }
  167.     else
  168.         return TRUE;    /* keep going */
  169. }
  170.  
  171. void far *mstenvp4(void)
  172. {
  173.     walk(get_mcb(), walk4);
  174.     return env4;
  175. }
  176.  
  177. /**********************************************************************/
  178.  
  179. main()
  180. {
  181.     printf("GETVECT 2Eh method; mstenvp1   = %Fp\n", mstenvp1()); 
  182.     printf("WALK MCB method; mstenvp2      = %Fp\n", mstenvp2());
  183.     printf("WALK MCB/LAST method; mstenvp3 = %Fp\n", mstenvp3());
  184.     printf("WALK MCB/OWN PARENT; mstenvp4  = %Fp\n", mstenvp4());
  185. }
  186.