home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l430 / 1.ddi / CHAP5.ZIP / HANDLES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-08  |  8.5 KB  |  266 lines

  1. /* 
  2. HANDLES.C -- KERNEL-related handles
  3. from "Undocumented Windows" by Schulman et al. (Addison-Wesley, 1992)
  4. Chapter 5: KERNEL
  5. Copyright (c) Andrew Schulman and Matt Pietrek 1992
  6. */
  7.  
  8. #include <dos.h>
  9. #include "windows.h"
  10. #include "handles.h"
  11.  
  12. extern DWORD FAR PASCAL GetSelectorBase(WORD wSel);
  13. extern DWORD FAR PASCAL GetSelectorLimit(WORD wSel);
  14. extern WORD FAR PASCAL SetSelectorBase(WORD wSel, DWORD dwBase);
  15. extern WORD FAR PASCAL SetSelectorLimit(WORD wSel, DWORD dwLimit);
  16.  
  17. /* Convert a handle to a selector, just the way TOOLHELP 
  18.    does.  See WINMOD.C for explanation */
  19. WORD HandleToSel(HANDLE h)
  20. {
  21.     static WORD wVers = 0;
  22.     if (! wVers)    // one-time initialization
  23.         wVers = (WORD) GetVersion();
  24.     if (wVers == 3) // 3.0: handles = selectors+1
  25.         return ((h & 2) == 2) ? h-1 : h;
  26.     else            // 3.1++: handles = selectors-1
  27.         return (h | 1);
  28. }
  29.  
  30. /* Turn hInstance into hTask:  walk the task list (see sample
  31. code in the entries for GetCurrentTask() and the Task Database),
  32. searching for a TDB whose WORD at offset 1Ch matches the hInstance,
  33. i.e., where HINSTANCE_FROM_HTASK(hTask) == hInstance */
  34. WORD hTask_from_hInstance(WORD hInstance)
  35. {
  36.     DWORD (FAR PASCAL *GetCurrentTaskD)(void) = GetCurrentTask;
  37.     DWORD dwTask = GetCurrentTaskD();
  38.     HANDLE hTask = HIWORD(dwTask);      // get base of linked list
  39.     for (;;)
  40.     {
  41.         if (HINSTANCE_FROM_HTASK(hTask) == hInstance)
  42.             return hTask;
  43.         
  44.         /* Get the handle of the next task from offset 0 in the Task DB */
  45.         if ((hTask = *((WORD far *) MK_FP(hTask, 0))) == 0)
  46.             break;
  47.     }
  48.     /* still here -- didn't find it */
  49.     return 0;
  50. }
  51.  
  52. /* Turn PDB (PSP) into hTask:  this is for the truly masochistic.  Use
  53. GetSelectorBase() to obtain the linear address of the PSP.  Subtract
  54. 100h, and create a new selector with the resulting base address.  This
  55. new selector points at the TDB, and the hTask can be found at offset
  56. 0Ch.  It would be wise to "sanity check" by making sure that the WORD
  57. at offset 0FAh is 'TD' */
  58. HANDLE hTask_from_PSP(WORD wPSP)
  59. {
  60.     WORD hTask, hMyTask, wDS;
  61.     _asm mov wDS, ds
  62.     hMyTask = AllocSelector(wDS);   // use DS as model
  63.     SetSelectorBase(hMyTask, GetSelectorBase(wPSP) - 0x100);
  64.     SetSelectorLimit(hMyTask, 0x100);
  65.     if (*((WORD far *) MK_FP(hMyTask, 0xFA)) != 0x4454) // 'TD'
  66.     {
  67.         FreeSelector(hMyTask);
  68.         return 0;   // no 'TD' signature: something wrong
  69.     }
  70.     hTask = *((WORD far *) MK_FP(hMyTask, 0x0c));   // the canonical hTask
  71.     if (*((WORD far *) MK_FP(hTask, 0xFA)) != 0x4454)   // 'TD'
  72.         hTask = 0;  // no 'TD' signature: something wrong
  73.     FreeSelector(hMyTask);
  74.     return hTask;
  75. }
  76.  
  77. /* Turn hModule into hInstance: a module can have more than one
  78. instance, unless if it's a DLL.  Use offset 0Eh in the Module Table,
  79. i.e., *((WORD far *) MK_FP(hModule, 0x0e)), to obtain the logical
  80. segment number (1, 2, etc.) of the DGROUP for the module.  Then, look
  81. up the actual DGROUP selector in the segment portion of the module
  82. table.  Treat this DGROUP as the hInstance.  If the module is for a 
  83. task rather than a DLL, the hInstance is for the most recent task
  84. that's still using the module table, and is not correct for the
  85. other invocations of the program. 
  86.     But a much simpler way is to get the hInstance returned from
  87. LoadLibrary().  This is used in hInstance_from_hModule. */
  88. /*    That's what it says in the book.  Unfortunately, it just doesn't
  89. seem totally reliable, so back to the long version: */
  90. #if 1
  91. typedef struct {
  92.     unsigned short ns_sector;
  93.     unsigned short ns_cbseg;
  94.     unsigned short ns_flags;
  95.     unsigned short ns_minalloc;
  96.     unsigned short ns_seg;      // in-memory version only!!!
  97.     } SEG; 
  98.  
  99. // fields in Module Table
  100. #define DGROUP(lpNEhdr)     *((WORD far *) &lpNEhdr[0x0e])
  101. #define SEGTAB(lpNEhdr)     *((WORD far *) &lpNEhdr[0x22])
  102. #define CSEG(lpNEhdr)       *((WORD far *) &lpNEhdr[0x1c])
  103.  
  104. WORD hInstance_from_hModule(WORD hModHand) 
  105. {
  106.     BYTE far *nehdr;
  107.     SEG far *segtab;
  108.     WORD dgroup;
  109.     
  110.     if (! IsValidModuleHandle(hModHand))
  111.         return 0;
  112.  
  113.     if (! IsModuleDLL(hModHand))
  114.         /* DGROUP may not be unique! */ ;
  115.     
  116.     nehdr  = MK_FP(hModHand, 0);
  117.     segtab = MK_FP(hModHand, SEGTAB(nehdr));
  118.     dgroup = DGROUP(nehdr);
  119.     
  120.     if (dgroup > CSEG(nehdr))
  121.         return 0;   // something wrong
  122.     else
  123.         return segtab[dgroup-1].ns_seg;
  124. }
  125. #else
  126. WORD hInstance_from_hModule(WORD hModule)
  127. {
  128.     char buf[128];
  129.     WORD hInstance;
  130.     GetModuleFileName(hModule, buf, 128);
  131.     /* remember, module is already loaded */
  132.     if ((hInstance = LoadLibrary(buf)) > 32)   // ref++
  133.     {
  134.         FreeLibrary(hInstance);                   // ref--
  135.         return HIWORD(GlobalLock(hInstance));
  136.     }
  137.     else
  138.         return 0;
  139. }
  140. #endif
  141.  
  142. #define NEMAGIC     0x454E          /* new EXE magic id:  'NE'  */
  143. #define NEFLAGS_OFS 0x0c            /* offset of flags in NE header */
  144. #define DLL_FLAG    0x8000          /* is module a DLL? */
  145.  
  146. /* Is handle for a DLL rather than for a task?  Use the flags at
  147.    offset 0Ch in the Module Database */
  148. BOOL IsModuleDLL(HANDLE hModule)
  149. {
  150.     if (*((WORD far *) MK_FP(hModule, 0)) != NEMAGIC)
  151.         return FALSE;   // it's not even a module, much less a DLL
  152.     else
  153.         return (*((WORD far *) MK_FP(hModule, NEFLAGS_OFS)) & DLL_FLAG);
  154. }
  155.  
  156. /* C interface to protected-mode instructions; must compile 
  157.    with 286 instructions (Borland -2, Microsoft -G2) */
  158.  
  159. /* Verify for Reading (VERR) instruction */
  160. BOOL verr(WORD wSel)
  161. {
  162.     if (! wSel) return 0;   /* workaround 386 bug: Hummel, p.584 */
  163.     _asm verr word ptr wSel
  164.     _asm je short ok
  165.     return 0;   // not valid for reading
  166. ok: return 1;   // is valid for reading
  167. }
  168.  
  169. /* Verify for Writing (VERW) instruction */
  170. BOOL verw(WORD wSel)
  171. {
  172.     if (! wSel) return 0;   /* workaround 386 bug: Hummel, p.585 */
  173.     _asm verw word ptr wSel
  174.     _asm je short ok
  175.     return 0;   // not valid for writing
  176. ok: return 1;   // is valid for writing
  177. }
  178.  
  179. /* C interface to protected-mode Load Access Rights (LAR) instruction */
  180. WORD lar(WORD wSel)
  181. {
  182.     if (! wSel) return 0;   /* workaround 386 bug: Hummel, p.448 */
  183.     _asm lar ax, wSel
  184.     _asm jnz error
  185.     _asm shr ax, 8
  186.     _asm jmp short no_error; // value in AX
  187. error:
  188.     return 0;
  189. no_error: ;
  190. }
  191.  
  192. /* C interface to LSL (Load Segment Limit) instruction */
  193. WORD lsl(WORD wSel)
  194. {
  195.     if (! wSel) return 0;   /* workaround 386 bug: Hummel, p.471 */
  196.     _asm lsl ax, wSel
  197.     _asm jnz error
  198.     _asm jmp short non_error; // value in AX
  199. error:
  200.     return 0;
  201. no_error: ;
  202. }
  203.  
  204. /* Are we using the 16-bit or 32-bit KERNEL?  
  205.    Returns 16 for KRNL286, 32 for KRNL386, 0 for real mode */
  206. int Kernel1632(void)
  207. {
  208.     LONG lFlags = GetWinFlags();
  209.     if (GetVersion() == 0x0003) // Windows 3.0: mode-dependent
  210.     {
  211.         if (lFlags & WF_STANDARD)       return 16;
  212.         else if (lFlags & WF_ENHANCED)  return 32;
  213.         else /* yuk! real mode! */      return 0;
  214.     }
  215.     else    // Windows 3.1+: processor-dependent
  216.         return (lFlags & WF_CPU286) ? 16 : 32;
  217. }
  218.  
  219. #define LHMAGIC     0x484C          /* 'LH' signature for Local Heap */
  220. #define NEMAGIC     0x454E          /* new EXE magic id:  'NE'  */
  221. #define PSPMAGIC    0x20CD          /* INT 20h instruction */
  222. #define TDBMAGIC    0x4454          /* 'TD' signature for Task */
  223.  
  224. /* Does the far pointer point to a valid local heap info struct? */
  225. BOOL IsValidLocalHeap(BYTE far *fp)
  226. {
  227.     WORD wMagicOffset = (Kernel1632() == 16) ? 0x22 : 0x28;
  228.     return (*((WORD far *) &fp[wMagicOffset]) == LHMAGIC);
  229. }
  230.  
  231. /* Is this handle for a Module Database? */
  232. BOOL IsValidModuleHandle(HANDLE h)
  233. {
  234.     WORD far *fp;
  235.     // assert(IsValidModuleHandle(GetCurrentModule()));
  236.     if (! verr(h))
  237.         return 0;
  238.     fp = MK_FP(h, 0);
  239.     return (*fp == NEMAGIC);    // make sure starts with 'NE' signature
  240. }
  241.  
  242. /* Is this handle for a DOS Program Segment Prefix (PSP; alias PDB)? */
  243. BOOL IsValidPSP(HANDLE h)
  244. {
  245.     WORD far *fp;
  246.     // assert(IsValidPSP(GetCurrentPDB()));
  247.     if (! verr(h))
  248.         return 0;
  249.     fp = MK_FP(h, 0);
  250.     return (*fp == PSPMAGIC);   // make sure starts with INT 20h instruction
  251. }
  252.  
  253. /* Is this handle for a Task Database?  3.1 has documented 
  254.    IsTask(), but it's not in 3.0, so do our own */
  255. BOOL IsValidTask(HANDLE h)
  256. {
  257.     WORD far *fp;
  258.     // assert(IsValidTask(GetCurrentTask()));
  259.     if (! verr(h))
  260.         return FALSE;
  261.     if (GetSelectorLimit(h) < 0xFC)
  262.         return FALSE;
  263.     fp = MK_FP(h, 0xFA);
  264.     return (*fp == TDBMAGIC);
  265. }
  266.