home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l440 / 2.ddi / CHAP5 / MEM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-26  |  7.6 KB  |  307 lines

  1. /* 
  2. MEM.C -- walks DOS MCB chain(s): detailed version
  3. Andrew Schulman and Jim Kyle, July 1990
  4. */
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. #include <dos.h>
  11.  
  12. typedef enum { FALSE, TRUE } BOOL;
  13. typedef unsigned char BYTE;
  14. typedef unsigned short WORD;
  15. typedef unsigned long ULONG;
  16. typedef void far *FP;
  17.  
  18. #ifndef MK_FP
  19. #define MK_FP(seg,ofs)  ((FP)(((ULONG)(seg) << 16) | (ofs)))
  20. #endif
  21.  
  22. #ifdef __TURBOC__
  23. #define ASM asm
  24. #else
  25. #define ASM _asm
  26. #endif
  27.  
  28. #ifdef __TURBOC__
  29. #define GETVECT(x)      getvect(x)
  30. #else
  31. #define GETVECT(x)      _dos_getvect(x)
  32. #endif
  33.  
  34. #pragma pack(1)
  35.  
  36. typedef struct {
  37.     BYTE type;          /* 'M'=in chain; 'Z'=at end */
  38.     WORD owner;         /* PSP of the owner */
  39.     WORD size;          /* in 16-byte paragraphs */
  40.     BYTE unused[3];
  41.     BYTE dos4[8];
  42.     } MCB;
  43.  
  44. #define MCB_FM_SEG(seg)     ((seg) - 1)
  45. #define IS_PSP(mcb)         (FP_SEG(mcb) + 1 == (mcb)->owner)
  46. #define ENV_FM_PSP(psp_seg) (*((WORD far *) MK_FP(psp_seg, 0x2c)))
  47.  
  48. #ifdef TSR
  49. void fail(char *s) { printf("%s\r\n", s); return; }
  50. #else
  51. void fail(char *s) { puts(s); exit(1); }
  52. #endif
  53.  
  54. BOOL belongs(void far *vec, unsigned start, unsigned size);
  55. void display(MCB far *mcb);
  56. char far *env(MCB far *mcb);
  57. void display_progname(MCB far *mcb);
  58. void display_cmdline(MCB far *mcb);
  59. void display_vectors(MCB far *mcb);
  60. unsigned fstrlen(char far *s);
  61.  
  62. MCB far *get_mcb(void)
  63. {
  64.     ASM mov ah, 52h
  65.     ASM int 21h
  66.     ASM mov dx, es:[bx-2]
  67.     ASM xor ax, ax
  68.     /* in both Microsoft C and Turbo C, far* returned in DX:AX */
  69. }
  70.  
  71. mcb_chk(MCB far *mcb)
  72. {
  73.     for (;;)
  74.         if (mcb->type == 'M')
  75.             mcb = MK_FP(FP_SEG(mcb) + mcb->size + 1, 0);
  76.         else
  77.             return (mcb->type == 'Z');
  78. }
  79.  
  80. void walk(MCB far *mcb)
  81. {
  82. #ifdef TSR  
  83.     printf("Seg     Owner   Size\r\n"); 
  84. #else
  85.     printf("Seg     Owner   Size\n"); 
  86. #endif
  87.     for (;;)
  88.         switch (mcb->type)
  89.         {
  90.             case 'M' : /* Mark : belongs to MCB chain */
  91.                 display(mcb);
  92.                 mcb = MK_FP(FP_SEG(mcb) + mcb->size + 1, 0);
  93.                 break;
  94.             case 'Z' : /* Zbikowski : end of MCB chain */
  95.                 display(mcb);
  96.                 return;
  97.             default :
  98.                 fail("error in MCB chain");
  99.         }
  100. }
  101.  
  102. #ifdef TSR
  103. void application(void)
  104. {
  105.     walk(get_mcb());
  106. }
  107. #else
  108. main(int argc, char *argv[])
  109. {
  110.     if (argc < 2)
  111.         walk(get_mcb());            /* walk "normal" MCB chain */
  112.     else
  113.     {
  114.         unsigned seg;
  115.         sscanf(argv[1], "%04X", &seg);
  116.         walk(MK_FP(seg, 0));       /* walk arbitrary MCB chain */
  117.     }
  118.  
  119.     return 0;
  120. }
  121. #endif
  122.  
  123. void display(MCB far *mcb)
  124. {
  125.     static void far *vect_2e = (void far *) 0;
  126.     unsigned env_seg;
  127.     
  128.     printf("%04X    %04X    %04X (%6lu)   ", 
  129.         FP_SEG(mcb), mcb->owner, mcb->size, (long) mcb->size << 4);
  130.  
  131.     if (IS_PSP(mcb))
  132.     {
  133.         void far *e = env(mcb);     /* MSC wants lvalue */
  134.         if (env_seg = FP_SEG(e)) printf("%04X    ", env_seg);
  135.         else                     printf("        ");
  136.     
  137.         display_progname(mcb);
  138.     }
  139.     
  140.     if (! vect_2e) 
  141.         vect_2e = GETVECT(0x2e);   /* do just once */
  142.     if (! mcb->owner)
  143.         printf("free ");
  144.     /* 0008 is not really a PSP; belongs to CONFIG.SYS */
  145.     else if (mcb->owner == 8)   
  146.         printf("config ");
  147.     /* INT 2Eh belongs to master COMMAND.COM (or other shell) */
  148.     else if (belongs(vect_2e, FP_SEG(mcb), mcb->size))
  149.         printf("%s ", getenv("COMSPEC"));   
  150.  
  151.     /* presence command line is independent of program name */
  152.     if (IS_PSP(mcb))
  153.         display_cmdline(mcb);
  154.     display_vectors(mcb);
  155. #ifdef TSR  
  156.     printf("\r\n");
  157. #else
  158.     printf("\n");
  159. #endif
  160. }
  161.  
  162. char far *env(MCB far *mcb)
  163. {
  164.     char far *e;
  165.     unsigned env_mcb;
  166.     unsigned env_owner;
  167.  
  168.     /*
  169.         if the MCB owner is one more than the MCB segment then
  170.             psp := MCB owner
  171.             env_seg := make_far_pointer(psp, 2Ch)
  172.             e := make_far_pointer(env_seg, 0)
  173.         else
  174.             return NULL
  175.     */
  176.     if (IS_PSP(mcb))
  177.         e = MK_FP(ENV_FM_PSP(mcb->owner), 0);
  178.     else 
  179.         return (char far *) 0;
  180.     
  181.     /* 
  182.        Does this environment really belong to this PSP? An
  183.        environment is just another memory block, so its MCB is
  184.        located in the preceding paragraph. Make sure the env
  185.        MCB's owner is equal to the PSP whose environment this
  186.        supposedly is! Thanks to Rob Adams of Phar Lap Software
  187.        for pointing out the need for this check; this is a 
  188.        good example of the sort of consistency check one must
  189.        do when working with undocumented DOS.
  190.     */
  191.     env_mcb = MCB_FM_SEG(FP_SEG(e));
  192.     env_owner = ((MCB far *) MK_FP(env_mcb, 0))->owner;
  193.     return (env_owner == mcb->owner) ? e : (char far *) 0;
  194. }
  195.  
  196. char far *progname_fm_psp(unsigned psp)
  197. {
  198.     char far *e;
  199.     unsigned len;
  200.  
  201.     /* is there an environment? */
  202.     if (! (e = env(MK_FP(MCB_FM_SEG(psp), 0))))
  203.         return (char far *) 0;
  204.  
  205.     /* program name only available in DOS 3+ */
  206.     if (_osmajor >= 3)
  207.     {
  208.         /* skip past environment variables */
  209.         do e += (len = fstrlen(e)) + 1;
  210.         while (len);
  211.  
  212.         /* 
  213.             e now points to WORD containing number of strings following
  214.             environment; check for reasonable value: signed because
  215.             could be FFFFh; will normally be 1
  216.         */
  217.         if ((*((signed far *) e) >= 1) && (*((signed far *) e) < 10))
  218.         {
  219.             e += sizeof(signed);
  220.             if (isalpha(*e))
  221.                 return e; /* could make canonical with INT 21h AH=60h */
  222.         }
  223.     }
  224.     
  225.     return (char far *) 0;
  226. }
  227.  
  228. void display_progname(MCB far *mcb)
  229. {
  230.     char far *s;
  231.     if (IS_PSP(mcb))
  232.         if (s = progname_fm_psp((FP_SEG(mcb) + 1)))
  233.             printf("%Fs ", s);
  234. }
  235.  
  236. BOOL belongs(void far *vec, unsigned start, unsigned size)
  237. {
  238.     unsigned seg = FP_SEG(vec) + (FP_OFF(vec) >> 4); /* normalize */
  239.     return (seg >= start) && (seg <= (start + size));
  240. }
  241.  
  242. void display_cmdline(MCB far *mcb)
  243. {
  244.     /*
  245.         psp := MCB owner
  246.         cmdline_len := psp[80h]
  247.         cmdline := psp[81h]
  248.         print cmdline (display width := cmdline_len)
  249.     */
  250.     int len = *((BYTE far *) MK_FP(mcb->owner, 0x80));
  251.     char far *cmdline = MK_FP(mcb->owner, 0x81);
  252.     printf("%.*Fs ", len, cmdline);
  253. }
  254.  
  255. void display_vectors(MCB far *mcb)
  256. {
  257. #ifdef TSR
  258.     void far *vec;
  259.     int i;
  260.     int did_one=0;
  261.     
  262.     for (i=0; i<256; i++)
  263.         if ((vec = GETVECT(i)) && 
  264.             belongs(vec, FP_SEG(mcb), mcb->size))
  265.         {
  266.             if (! did_one) { did_one++; printf("["); }
  267.             printf("%02X ", i);
  268.         }
  269.     if (did_one) printf("]");
  270. #else
  271.     static void far **vec = (void far **) 0;
  272.     WORD vec_seg;
  273.     int i;
  274.     int did_one=0;
  275.     
  276.     if (! vec)
  277.     {
  278.         if (! (vec = calloc(256, sizeof(void far *))))
  279.             fail("insufficient memory");
  280.         for (i=0; i<256; i++)
  281.             vec[i] = GETVECT(i);
  282.     }
  283.     
  284.     for (i=0; i<256; i++)
  285.         if (vec[i] && belongs(vec[i], FP_SEG(mcb), mcb->size))
  286.         {
  287.             if (! did_one) { did_one++; printf("["); }
  288.             printf("%02X ", i);
  289.             vec[i] = 0;
  290.         }
  291.     if (did_one) printf("]");
  292. #endif  
  293. }
  294.  
  295. unsigned fstrlen(char far *s)
  296. {
  297. #if defined(_MSC_VER) && (_MSC_VER >= 600)
  298.     return _fstrlen(s);
  299. #else
  300.     unsigned len = 0;
  301.     while (*s++)
  302.         len++;
  303.     return len;
  304. #endif  
  305. }
  306.  
  307.