www.pudn.com > SJF2443.zip > POKEIO.C


/********************************************************************* 
 
  This code fragment illustrates the unsuccessful attempt to directly 
modify the IOPM base address.  This code would appear in a kernel 
mode device driver.  Refer to the GIVEIO.C listing for a complete 
device driver example. 
 
*********************************************************************/ 
 
/* 
 *  Make sure our structure is packed properly, on byte boundary, not 
 * on the default doubleword boundary. 
 */ 
#pragma pack(push,1) 
 
/* 
 *  Structure of a GDT (global descriptor table) entry.  From 
 * processor manual. 
 */ 
typedef struct { 
	unsigned limit : 16; 
	unsigned baselo : 16; 
	unsigned basemid : 8; 
	unsigned type : 4; 
	unsigned system : 1; 
	unsigned dpl : 2; 
	unsigned present : 1; 
	unsigned limithi : 4; 
	unsigned available : 1; 
	unsigned zero : 1; 
	unsigned size : 1; 
	unsigned granularity : 1; 
	unsigned basehi : 8; 
} GDTENT; 
 
/* 
 *  Structure of the 48 bits of the GDT register that are stored 
 * by the SGDT instruction. 
 */ 
typedef struct { 
	unsigned short  limit; 
	GDTENT  *base; 
} GDTREG; 
 
#pragma pack(pop) 
 
/* 
 *  This code demonstrates the brute force approach to modifying 
 * the IOPM base.  The IOPM base is stored as a two byte integer 
 * at offset 0x66 within the TSS, as documented in the processor 
 * manual.  In Windows NT, the IOPM is stored within the TSS 
 * starting at offset 0x88, and going for 0x2004 bytes.  This is 
 * not documented anywhere, and was determined by inspection. 
 * The code here puts some 0's into the IOPM so that we 
 * can try to access some I/O ports, then modifies the IOPM base 
 * address. 
 * 
 *  This code is unsuccessful because NT overwrites the IOPM 
 * base on each process switch. 
 */ 
void GiveIO() 
{ 
	GDTREG gdtreg; 
	GDTENT *g; 
	short TaskSeg; 
	char *TSSbase; 
	int i; 
 
	_asm str TaskSeg;                                       // get the TSS selector 
	_asm sgdt gdtreg;                                       // get the GDT address 
 
	g = gdtreg.base + (TaskSeg >> 3);       // get the TSS descriptor 
 
										// get the TSS address 
	TSSbase = (PVOID)(g->baselo | (g->basemid << 16)  
		       | (g->basehi << 24)); 
 
	for(i=0; i < 16; ++i)                           // poke some 0's into the 
		TSSbase[0x88 + i] = 0;                  //   IOPM 
 
										// set IOPM base to 0x88 
	*((USHORT *)(TSSbase + 0x66)) = 0x88; 
}