?? mstenvp.c
字號:
/*
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());
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -