看到http://bbs.pediy.com/showthread.php?t=83385说如何像dbgview那样的应用程序来接收驱动的dbgprint.........可以拦截int 2d来简单实现....碰巧刚写了点代码...帖上来吧...只是测试的代码..很不稳定....
   下面的代码拦截了int 3/ int 1 int 2d
   本意是设置CPU单补状态来分析异常的执行EIP的...
#include "ntddk.h"
#include <stdio.h>

#define MAKELONG(a, b) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16)) 

#define MAX_IDT_ENTRIES 0xFF
#define NT_INT_TIMER        0x3

unsigned long g_i_count = 0;

///////////////////////////////////////////////////
// IDT structures
///////////////////////////////////////////////////
#pragma pack(1)

// entry in the IDT, this is sometimes called
// an "interrupt gate"
typedef struct
{
  unsigned short LowOffset;
  unsigned short selector;
  unsigned char unused_lo;
  unsigned char segment_type:4;  //0x0E is an interrupt gate
  unsigned char system_segment_flag:1;
  unsigned char DPL:2;         // descriptor privilege level 
  unsigned char P:1;            /* present */
  unsigned short HiOffset;
} IDTENTRY;

/* sidt returns idt in this format */
typedef struct
{
  unsigned short IDTLimit;
  unsigned short LowIDTbase;
  unsigned short HiIDTbase;
} IDTINFO;

#pragma pack()


// naked functions have no prolog/epilog code - they are functionally like the 
// target of a goto statement
typedef struct _KINT_STACK_INFO
{
  ULONG ret_eip;
  ULONG saved_cs;
  ULONG saved_eflags;
  ULONG saved_esp;
  ULONG saved_ss;

  ULONG saved_eax;
  ULONG saved_ebx;
  ULONG saved_ecx;
  ULONG saved_edx;
  ULONG saved_esi;
  ULONG saved_edi;
  ULONG saved_ebp;
  ULONG saved_pid;

}KINT_STACK_INFO;

typedef struct _REG_INFO
{
  ULONG saved_eax;
  ULONG saved_ebx;
  ULONG saved_ecx;
  ULONG saved_edx;
  ULONG saved_esi;
  ULONG saved_edi;
  ULONG saved_ebp;
  ULONG saved_esp;
}REG_INFO;

KINT_STACK_INFO g_kstack_info = {0};

REG_INFO g_reg_info = {0};



#define  MAX_BREAKPOINT 10
//breakpoint_info g_breakpoint_array[MAX_BREAKPOINT] = {0};

typedef struct _breakpoint_info
{
  ULONG cur_breakpoint_count;
  struct _breakpoint_array
  {
    ULONG u_address;
    UCHAR byte_code[4];  // byte_code[0] 原始byte 
  }breakpoint_array[MAX_BREAKPOINT];
}breakpoint_info;
char save_byte[4] = {0};
breakpoint_info g_breakpoint_array = {0};

#define ENABLE_WRITE { \
                    __asm cli \
                      __asm mov eax,cr0 \
            __asm and eax, not 0x10000 \
            __asm mov cr0,eax \
            }

#define DISANBLE_WRITE {  \
                       __asm mov eax,cr0  \
             __asm or eax,0x10000  \
             __asm mov cr0,eax  \
             __asm sti \
             }

BOOLEAN insert_breakpoint(PVOID u_address)
{

  int i = 0, j= -1;
  if(MmIsAddressValid(u_address) == FALSE)
  {
    return FALSE;
  }

  for( i; i<MAX_BREAKPOINT; i++)
  {
    if(g_breakpoint_array.breakpoint_array[i].byte_code[0] == 0)
    {
      j = i;
      break;
    }
  }

  if( j == -1) return FALSE;


  ENABLE_WRITE

   __asm
   {
     mov ebx,u_address
       mov al,0xcc
     mov ah,byte ptr[ebx]
     mov save_byte[0],ah
     mov byte ptr[ebx],al
   }

   g_breakpoint_array.breakpoint_array[j].u_address = (ULONG)u_address;
   g_breakpoint_array.breakpoint_array[j].byte_code[1] = *(UCHAR*)u_address;
     g_breakpoint_array.breakpoint_array[j].byte_code[0] = 1;
   g_breakpoint_array.cur_breakpoint_count++ ;

   DISANBLE_WRITE

   return TRUE;

}

int z = 0;
int tmp_addr;
BOOLEAN b_steping = FALSE;


LIST_ENTRY hbpdata_list;

typedef struct _BP_DATA
{
  KINT_STACK_INFO bp_context;
  LIST_ENTRY ListEntry;
}BP_DATA, *PBP_DATA;

PBP_DATA gp_bpdata = NULL;

NTKERNELAPI ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers,
                  IN ULONG Count,
                  IN ULONG Flags);

PVOID Callers[128];
ULONG nCount =0;
ULONG i;


__declspec(naked) my_interrupt_hook()
{
  
  nCount = RtlWalkFrameChain(Callers,16,0);
  if(nCount>0)
  {
    for(i=0;i<nCount;i++)
    {
      DbgPrint("stack %x",Callers[i]);
    }
  }

  RtlZeroMemory(&g_kstack_info,sizeof(KINT_STACK_INFO));
//  g_pcur_tss = (struct _KTSS*)(*(ULONG*)(0xffdff000+0x40));
//  DbgPrint("--%d\n",PsGetCurrentProcessId());
 
  __asm
  {
   
    pushfd;
  push  eax
  pushad  // EAX,ECX,EDX,EBX,ESP,EBP,ESI和EDI 

  mov g_kstack_info.saved_eax,eax
  mov g_kstack_info.saved_ecx,ecx

  mov g_kstack_info.saved_ebx,ebx

  mov g_kstack_info.saved_edx,edx
  mov g_kstack_info.saved_esi,esi
  mov g_kstack_info.saved_edi,edi
  mov g_kstack_info.saved_ebp,ebp
  mov g_kstack_info.saved_esp,esp

  mov eax,[esp+8+32]
  mov g_kstack_info.ret_eip, eax
  xor eax,eax

  mov eax,[esp+12+32]
  mov g_kstack_info.saved_cs,eax
  xor eax,eax

  mov eax,[esp+16+32]
  mov g_kstack_info.saved_eflags, eax
  xor eax,eax

/*  mov eax,[esp+20+32]
  mov g_kstack_info.saved_esp, eax
  xor eax,eax*/

  mov eax,[esp+24+32]
  mov g_kstack_info.saved_ss,eax
  xor eax,eax

  cmp g_kstack_info.saved_cs,0x1b
  jz __RING3

  mov eax,[esp+8+32]
  dec eax
  mov tmp_addr,eax
  
  }

  
  for(z = 0; z<MAX_BREAKPOINT; z++)
  {
    if((g_breakpoint_array.breakpoint_array[z].byte_code[0] == 1)&&
      g_breakpoint_array.breakpoint_array[z].u_address == tmp_addr)
    {
      //DbgPrint("--%d\n",PsGetCurrentProcessId());
      g_kstack_info.saved_pid = (ULONG)PsGetCurrentProcessId();
      __asm xor eax,eax
      __asm mov eax,tmp_addr
      __asm mov [esp+8+32], eax
      ENABLE_WRITE
        *(UCHAR*)tmp_addr = save_byte[0];
      DISANBLE_WRITE
      g_breakpoint_array.breakpoint_array[z].byte_code[0] = 0;
      g_breakpoint_array.breakpoint_array[z].u_address = 0;
      break;
    }
  }

    gp_bpdata = (PBP_DATA)ExAllocatePool(NonPagedPool,sizeof(BP_DATA));
    if(gp_bpdata != NULL)
    {
      //strcpy(gp_dbdata->db_string,str_addr);
      RtlCopyMemory(&gp_bpdata->bp_context,&g_kstack_info,sizeof(KINT_STACK_INFO));
      InsertTailList(&hbpdata_list,&gp_bpdata->ListEntry);
    }
  DbgPrint("eip 0x%x  cs 0x%x  EFLAGS 0x%x   %x %x\n",g_kstack_info.ret_eip,
                                            g_kstack_info.saved_cs,
                              g_kstack_info.saved_eflags,
                        g_kstack_info.saved_esp,
                        g_kstack_info.saved_ss
                       );
  DbgPrint(" eax= 0x%08x   ",g_kstack_info.saved_eax);

  // set TF


__RING3:

  if(b_steping == TRUE)
  {
    g_kstack_info.saved_eflags|=0x100;
    __asm
    {
      mov eax,g_kstack_info.saved_eflags
      mov [esp+16+32],eax
    }
  }
  __asm
  {
    popad
    pop eax
    popfd;
      iretd;


  }
}

//////////////////////////////////////////////////////////////
ULONG hit_addr = 0;
int tmp_count = 0;
ULONG tmp_mode = 0;
int int1_hit_count = 0;
ULONG jc_addr = 0;
ULONG to_addr = 0;

char* jorc[2]={"call","jmp"};


LIST_ENTRY hcalldata_list;
LIST_ENTRY heipinfo_list;

BOOLEAN call_or_address = FALSE; // false 表示只记录 call信息 否则只是记录EIP
BOOLEAN can_get_callinfo = FALSE; //表示应用程序能拿数据没

// who call/jmp to  
typedef struct __CALL_INFO
{
  ULONG who[150];
  ULONG to[150];
  ULONG used;
  LIST_ENTRY ListEntry;
}CALL_INFO,*PCALL_INFO;

PCALL_INFO gp_callinfo = NULL;

typedef struct __EIP_INFO
{
  ULONG eip_array[1000];
  ULONG used;
  LIST_ENTRY ListEntry;
}EIP_INFO,*PEIP_INFO;

PEIP_INFO gp_eipinfo = NULL;

ULONG tmp_efalgs = 0;
ULONG last_addr = 0;
ULONG not_record_addr = 0;

BOOLEAN no_dip_data = FALSE;
__declspec(naked) my_int_1()
{
  
  
  //DWORD eax,ebx,ecx,edx,
//  KeStallExecutionProcessor(100000);
//  RtlZeroMemory(&g_kstack_info,sizeof(KINT_STACK_INFO));
//  g_pcur_tss = (struct _KTSS*)(*(ULONG*)(0xffdff000+0x40));
//  DbgPrint("--%d\n",PsGetCurrentProcessId());
  __asm
  {
    pushfd;
  push  eax
  pushad  // EAX,ECX,EDX,EBX,ESP,EBP,ESI和EDI 
    
  mov eax,[esp+8+32]
  mov hit_addr, eax
  mov eax,[esp+12+32]
  mov tmp_mode,eax

  }

      __asm mov eax,[esp+16+32]
    __asm and eax,0x100
    __asm mov tmp_efalgs,eax

  if(!tmp_efalgs&0x100)
    goto __RET;

  int1_hit_count++;
  if(call_or_address == FALSE)
  {
    if( gp_callinfo == NULL || gp_callinfo->used == 149) ///////////// 不排除以后做修改
    {
      gp_callinfo = (PCALL_INFO)ExAllocatePool(NonPagedPool,sizeof(CALL_INFO));
      if(gp_callinfo != NULL)
      {
        gp_callinfo->used = 0;
        InsertTailList(&hcalldata_list,&gp_callinfo->ListEntry);
      }else goto __RET;  /////////////////////////////////////////////// ????????????
    }
    if(*(UCHAR*)hit_addr == 0xe8 /* || *(UCHAR*)hit_addr == 0xe9*/)  //// 屏蔽掉好
    {
      jc_addr = *(ULONG*)(hit_addr+1);
      if(jc_addr&0x10000000)
      {
        to_addr=*(ULONG*)((UCHAR*)(hit_addr+1))+(ULONG)hit_addr-0xFFFFFFFB;
      }
      else
      {
        to_addr =*(ULONG*)((UCHAR*)(hit_addr+1))+(ULONG)hit_addr+5;
      }
      
//      DbgPrint("0x%x %s  0x%x %d", hit_addr,jorc[*(UCHAR*)hit_addr-0xe8],to_addr,gp_callinfo->used);
      
      gp_callinfo->who[gp_callinfo->used] = hit_addr;
      gp_callinfo->to[gp_callinfo->used] = to_addr;
      (gp_callinfo->used)++;
    }else if(*(USHORT*)hit_addr == 0x15ff) /////// ?? 0xff15
    {
      to_addr = *(ULONG*)(*(ULONG*)((UCHAR*)(hit_addr+2)));
//      DbgPrint("--0x%x call 0x%x  %d",hit_addr,to_addr,gp_callinfo->used);

        
      gp_callinfo->who[gp_callinfo->used] = hit_addr;
      gp_callinfo->to[gp_callinfo->used] = to_addr;
      (gp_callinfo->used)++;
      
      
    }
    
    //DbgPrint("eip 0x%x ",hit_addr);
    __asm mov eax,[esp+16+32]
    __asm and eax,0x100
    __asm mov tmp_efalgs,eax
    
//     
    if(gp_callinfo->used == 149 || tmp_efalgs ==0)
    {
      //DbgPrint("--%x\n",hit_addr);
      can_get_callinfo = TRUE;
    }
    
  }else  //只记录EIP的...
  {
    can_get_callinfo = TRUE; //////////换方式..满才插入列
    if(gp_eipinfo == NULL || gp_eipinfo->used == 999) ///////////// 不排除以后做修改
    {
      gp_eipinfo = (PEIP_INFO)ExAllocatePool(NonPagedPool,sizeof(EIP_INFO));
      if(gp_eipinfo != NULL)
      {
        //DbgPrint(" ----------------");
        gp_eipinfo->used = 0;
        //InsertTailList(&heipinfo_list,&gp_eipinfo->ListEntry);
      }else 
      {
        DbgPrint(" failed allocate memory");
        goto __RET;  /////////////////////////////////////////////// ????????????
      }
    }
      
      if(hit_addr == last_addr) //// can_get_callinfo == FALSE??
      {
        //not_record_addr = hit_addr; 
        __asm
        {
              mov eax,[esp+16+32]
    and eax,0xfffffeff
    mov [esp+16+32],eax

        }

        DbgPrint("-uuuuuuuuu-%x\n",hit_addr);
        //InsertTailList(&heipinfo_list,&gp_eipinfo->ListEntry);
//        can_get_callinfo = FALSE; ///////////////////////////////////////////

      }
       
  
      {
    gp_eipinfo->eip_array[gp_eipinfo->used] = hit_addr;
    (gp_eipinfo->used)++;
      }
    last_addr = hit_addr;
    
    __asm mov eax,[esp+16+32]
    __asm and eax,0x100
    __asm mov tmp_efalgs,eax    
   
    
    if(gp_eipinfo->used == 999 || tmp_efalgs ==0)
    {
      //DbgPrint("--uuuuuuuuuuuuuuuuu%x\n",hit_addr);
      can_get_callinfo = TRUE;
      InsertTailList(&heipinfo_list,&gp_eipinfo->ListEntry);
      //DbgPrint("--%x\n",hit_addr);
    }

  }

__RET:
   if(tmp_count == int1_hit_count || tmp_mode==0x1b)
   {

     DbgPrint("--uuuuuuuuuuuuuuuuu%x\n",hit_addr);
//     InsertTailList(&heipinfo_list,&gp_eipinfo->ListEntry);
     //如果不要 tmp_count++; 则记录了整个调用的过程直到返回RING3
  __asm
  {
    mov eax,[esp+16+32]
    and eax,0xfffffeff
    mov [esp+16+32],eax
    mov eax,0
    mov dr6,eax
  }
  
  can_get_callinfo = TRUE;
   }

    __asm
  {
    popad
    pop eax
    popfd;
      iretd;


  }
}



char* str_addr = NULL;
ULONG str_len = 0;
ULONG str_max_len = 0;
ULONG is_print = 0;

PKEVENT pKEvent = NULL;
char tmp_dbgprint_string[256]={0};
KIRQL                   oldIrql;
KSPIN_LOCK  StateLock;
    
LARGE_INTEGER timeout;

    
LIST_ENTRY hdbdata_list;

typedef struct _DB_DATA
{
  char db_string[256];
  LIST_ENTRY ListEntry;
} DB_DATA, *PDB_DATA;

PDB_DATA gp_dbdata = NULL;

__declspec(naked) my_int_2d()
{
// timeout.QuadPart = -3*1000*1000*10/1000;
//  KeAcquireSpinLock(&StateLock, &oldIrql);
  __asm
  
  {
    pushfd;
  push  eax
  pushad  // EAX,ECX,EDX,EBX,ESP,EBP,ESI和EDI
  
  mov is_print,eax 
  mov eax,[esp+8+32]
  inc eax
  mov [esp+8+32],eax
  
  mov str_addr,ecx
  mov str_len,edx
  }

  if(str_len >250)
    str_max_len = 250;
  else str_max_len = str_len;
  if(/*pKEvent&& */is_print==1)
  {
    gp_dbdata = (PDB_DATA)ExAllocatePool(NonPagedPool,sizeof(DB_DATA));
    if(gp_dbdata != NULL)
    {
      strcpy(gp_dbdata->db_string,str_addr);
      InsertTailList(&hdbdata_list,&gp_dbdata->ListEntry);
    }
//    strcpy(tmp_dbgprint_string,str_addr);
//    KeSetEvent(pKEvent,IO_NO_INCREMENT, FALSE);
//    KeWaitForSingleObject(pKEvent,Executive,KernelMode,FALSE,&timeout);
//    RtlCopyMemory(tmp_dbgprint_string,str_addr,str_max_len);
  }
  
//  DbgPrint("----hi int 2d %x",xx);
  
    __asm
  {
//    jmp g_old_isr[0x2d]
    popad
    pop eax
    popfd;
      iretd;
  }
//  KeReleaseSpinLock(&StateLock, oldIrql);
}


typedef struct _INTTERUPT_STACK
{    
  ULONG InterruptReturnAddress;    
  ULONG SavedCS;    
  ULONG SavedFlags;    
  ULONG FunctionReturnAddress;    
  ULONG Argument;
}INTTERUPT_STACK;


#define MAX_PROCESSOR 8
ULONG g_old_isr[256]={0};

typedef struct _IDT_ENTRY
{
  ULONG g_old_isr[256];

}IDT_ENTRY,*PIDT_ENTRY;

IDT_ENTRY g_idtentry_array[MAX_PROCESSOR] = {0};

#define MAX_NUM_PROCESSER   8

extern VOID KeSetSystemAffinityThread(KAFFINITY Affinity);
IDTENTRY OldIdtEntry[MAX_NUM_PROCESSER]={ 0 };
IDTINFO idt_info[MAX_NUM_PROCESSER]={ 0 };
////////////////////////////////////////////////////////
VOID AddInterrupt(LONG dwIndex,ULONG vertor, PVOID fake_routine)

  IDTINFO    idt_info;    // this structure is obtained by calling STORE IDT (sidt)
  IDTENTRY*  idt_entries;  // and then this pointer is obtained from idt_info

  int i = 0;

  if(g_idtentry_array[dwIndex].g_old_isr[vertor] !=0)
  {
    return ;
  }
   // load idt_info
  __asm  sidt  idt_info
  idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);

  g_idtentry_array[dwIndex].g_old_isr[vertor] = MAKELONG(idt_entries[vertor].LowOffset,idt_entries[vertor].HiOffset);

  // remember we disable interrupts while we patch the table
  __asm cli
  idt_entries[vertor].LowOffset = (unsigned short)fake_routine;
  idt_entries[vertor].HiOffset = (unsigned short)((unsigned long)fake_routine >> 16);
  __asm sti

  
/*  IDTENTRY* idt_entries;  
  IDTINFO idt_infoTmp;

  __asm sidt idt_infoTmp;

  idt_info[dwIndex]=idt_infoTmp;
  
    idt_entries = (IDTENTRY*) MAKELONG(idt_info[dwIndex].LowIDTbase,idt_info[dwIndex].HiIDTbase);


    if ((idt_entries[vector].LowOffset != 0) || (idt_entries[vector].HiOffset != 0))
    return; 

  memcpy(&OldIdtEntry[dwIndex], &idt_entries[vector], sizeof(IDTENTRY));
  __asm cli
    
    idt_entries[vector].LowOffset = (unsigned short)fake_routine;
    idt_entries[vector].HiOffset = (unsigned short)((unsigned int)fake_routine>>16);
  __asm sti

  return;*/
}


void RemoveInterrupt(LONG dwIndex,ULONG vertor)
{
  IDTINFO    idt_info;    // this structure is obtained by calling STORE IDT (sidt)
  IDTENTRY*  idt_entries;
  if(g_idtentry_array[dwIndex].g_old_isr[vertor] == 0)
  {
    return ;
  }
  
  __asm  sidt  idt_info  
  idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);

  // restore the original interrupt handler
  __asm cli
  idt_entries[vertor].LowOffset = (unsigned short)g_idtentry_array[dwIndex].g_old_isr[vertor];
  idt_entries[vertor].HiOffset = (unsigned short)((unsigned long)g_idtentry_array[dwIndex].g_old_isr[vertor] >> 16);
  __asm sti

  g_idtentry_array[dwIndex].g_old_isr[vertor] = 0; ////////////////////////////////////////////////////////////
/*    IDTENTRY* idt_entries;
    idt_entries = (IDTENTRY*) MAKELONG(idt_info[dwIndex].LowIDTbase,idt_info[dwIndex].HiIDTbase);

  __asm cli
    memcpy(&idt_entries[vector], &OldIdtEntry[dwIndex], sizeof(IDTENTRY));
  __asm sti*/
}


void install_idt_hook(int vertor, PVOID fake_routine)
{
  
/*  KAFFINITY     ActiveProcessors, CurrentAffinity;
  LONG  dwTmp=0;
  ActiveProcessors=KeQueryActiveProcessors(); 
  DbgPrint("KeActiveProcessors=%d",ActiveProcessors);

   for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) 
   {
     if (ActiveProcessors & CurrentAffinity)
     {
       ActiveProcessors &= ~CurrentAffinity;
             KeSetSystemAffinityThread(CurrentAffinity);
         AddInterrupt(dwTmp,vertor,fake_routine);
       dwTmp++;
     }
   }*/
  IDTINFO    idt_info;    // this structure is obtained by calling STORE IDT (sidt)
  IDTENTRY*  idt_entries;  // and then this pointer is obtained from idt_info

  int i = 0;

  if(g_old_isr[vertor] !=0)
  {
    return ;
  }
   // load idt_info
  __asm  sidt  idt_info
  idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);

  g_old_isr[vertor] = MAKELONG(idt_entries[vertor].LowOffset,idt_entries[vertor].HiOffset);

  // remember we disable interrupts while we patch the table
  __asm cli
  idt_entries[vertor].LowOffset = (unsigned short)fake_routine;
  idt_entries[vertor].HiOffset = (unsigned short)((unsigned long)fake_routine >> 16);
  __asm sti

}

void unistall_idt_hook(int vertor)
{
/*  KAFFINITY     ActiveProcessors, CurrentAffinity;
  LONG  dwTmp=0;
  ActiveProcessors=KeQueryActiveProcessors(); 
  DbgPrint("KeActiveProcessors=%d",ActiveProcessors);

  for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) 
  {
    if (ActiveProcessors & CurrentAffinity)
    {
      ActiveProcessors &= ~CurrentAffinity;
            KeSetSystemAffinityThread(CurrentAffinity);
      RemoveInterrupt(dwTmp,vector);  
      dwTmp++;
    }
  }  */
IDTINFO    idt_info;    // this structure is obtained by calling STORE IDT (sidt)
  IDTENTRY*  idt_entries;  // and then this pointer is obtained from idt_info

  if(g_old_isr[vertor] == 0)
  {
    return ;
  }
  // load idt_info
  __asm  sidt  idt_info  
  idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);

  // restore the original interrupt handler
  __asm cli
  idt_entries[vertor].LowOffset = (unsigned short)g_old_isr[vertor];
  idt_entries[vertor].HiOffset = (unsigned short)((unsigned long)g_old_isr[vertor] >> 16);
  __asm sti

  g_old_isr[vertor] = 0; ////////////////////////////////////////////////////////////


}

VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{  
  UNICODE_STRING usDosDeviceName;
  //    DbgPrint("Example_Unload Called \r\n");
  RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\Sys_SKD");
    IoDeleteSymbolicLink(&usDosDeviceName);
  IoDeleteDevice(DriverObject->DeviceObject);
    if(pKEvent)
        ObDereferenceObject(pKEvent); 
//  unistall_idt_hook(NT_INT_TIMER);
  unistall_idt_hook(0x1);
  unistall_idt_hook(0x2d);
  unistall_idt_hook(0x3);
}

NTSTATUS SysCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
  return NtStatus;
}


NTSTATUS SysClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
  return NtStatus;
}

#define IOCTL_GET_DBGPRINT_DATA    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_PASS_USER_EVENT    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_UNPASS_USER_EVENT    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_INSTALL_INT3    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_UNINSTALL_INT3    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_INSTALL_INT1    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_INSERT_BREAKPOINT    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_GET_BREAKPOINT_CONTEXT    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_SET_STEPING   CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_SET_STEPING_COUNT   CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_UNSET_STEPING   CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
#define IOCTL_UNINSTALL_INT1    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x812, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)  

#define IOCTL_GET_CALL_DATA    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x813, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)  
#define IOCTL_SET_GET_EIPINFO    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x814, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)  
#define IOCTL_GET_EIP_DATA   CTL_CODE(FILE_DEVICE_UNKNOWN, 0x815, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define IOCTL_SET_GET_CALLINFO   CTL_CODE(FILE_DEVICE_UNKNOWN, 0x816, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)   





NTSTATUS handle_get_dbdata(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, ULONG* pdwDataWritten)
{
  NTSTATUS NtStatus = STATUS_SUCCESS;
  PCHAR pOutputBuffer = NULL;
  int dwwrite = 0;


  if(Irp->MdlAddress)
    {
        pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
    }

  if(pOutputBuffer)
    {

  
//    DbgPrint("----get data");
//    while(!IsListEmpty(&hdbdata_list))
    if(!IsListEmpty(&hdbdata_list))
    {
      PLIST_ENTRY pEntry;

      
      pEntry = RemoveHeadList(&hdbdata_list);
    gp_dbdata = CONTAINING_RECORD(pEntry,
                              DB_DATA,
                              ListEntry);
    //if(gp_tmp_dbdata)
    //gp_tmp_dbdata = gp_dbdata;
    //KdPrint(("%d\n",pData->number));
    if(pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >strlen(gp_dbdata->db_string))
    strcpy(pOutputBuffer,gp_dbdata->db_string);
    else strcpy(pOutputBuffer,"NULL");
    ExFreePool(gp_dbdata);
    dwwrite = strlen(gp_dbdata->db_string);
//    RemoveHeadList(&hdbdata_list);
//    KeSetEvent(pKEvent,IO_NO_INCREMENT, FALSE);
    //break;
    }    
//    strcpy(pOutputBuffer,tmp_dbgprint_string);
//    RtlZeroMemory(tmp_dbgprint_string,256);
//    DbgPrint("----get data");
//    if(pKEvent)
//    KeSetEvent(pKEvent,IO_NO_INCREMENT, FALSE);
  }

  //*pdwDataWritten == 0 表示失败....否则返回真实的..用户程序需要根据这个返回值判断自己提供的缓冲区是否足够
  *pdwDataWritten = dwwrite;
  return NtStatus;
  
}

NTSTATUS handle_pass_uevent(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, ULONG* pdwDataWritten)
{
  NTSTATUS NtStatus = STATUS_SUCCESS;

     // 需要验证一下.
  HANDLE hUserEvent =  *(HANDLE*)Irp->AssociatedIrp.SystemBuffer;

  NtStatus = ObReferenceObjectByHandle(hUserEvent,EVENT_MODIFY_STATE,*ExEventObjectType,KernelMode,
                                     (PVOID*)&pKEvent, NULL);
  
  if(NtStatus!=STATUS_SUCCESS)
  {
    DbgPrint("pass event wrong\n");
  }
  
  *pdwDataWritten = 0;
  return NtStatus;
}

///////////////////////////
NTSTATUS get_bpcontext(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, ULONG* pdwDataWritten)
{
  NTSTATUS NtStatus = STATUS_SUCCESS;
  PCHAR pOutputBuffer = NULL;
  int dwwrite = 0;


  if(Irp->MdlAddress)
    {
        pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
    }

  if(pOutputBuffer)
    {

    if(!IsListEmpty(&hbpdata_list))
    {
      PLIST_ENTRY pEntry;

      
      pEntry = RemoveHeadList(&hbpdata_list);
    gp_bpdata = CONTAINING_RECORD(pEntry,
                              BP_DATA,
                              ListEntry);

    if(pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KINT_STACK_INFO))
    {
      RtlCopyMemory(pOutputBuffer,&gp_bpdata->bp_context,sizeof(KINT_STACK_INFO));
      dwwrite = sizeof(KINT_STACK_INFO);
    }
    
    else dwwrite = 0;
    ExFreePool(gp_bpdata);
    gp_bpdata = NULL;
    

    }    

  }

  //*pdwDataWritten == 0 表示失败....否则返回真实的..用户程序需要根据这个返回值判断自己提供的缓冲区是否足够
  *pdwDataWritten = dwwrite;
  return NtStatus;
  
}

////////////////////
NTSTATUS get_call_info(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, ULONG* pdwDataWritten)
{
  NTSTATUS NtStatus = STATUS_SUCCESS;
  PCHAR pOutputBuffer = NULL;
  int dwwrite = 0;


  if(Irp->MdlAddress)
    {
        pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
    }

  if(pOutputBuffer)  
    {
    if(!IsListEmpty(&hcalldata_list)&&(can_get_callinfo == TRUE))  // 因为结构被多次用..除非慢满了..否则有数据也不取的..
    {
      PLIST_ENTRY pEntry;
      
      pEntry = RemoveHeadList(&hcalldata_list);
      gp_callinfo = CONTAINING_RECORD(pEntry,CALL_INFO,ListEntry);
      
      if(pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(CALL_INFO))
      {
        RtlCopyMemory(pOutputBuffer,gp_callinfo,sizeof(CALL_INFO));
        dwwrite = sizeof(CALL_INFO);
        //can_get_callinfo = FALSE;
      }
      else dwwrite = 0;
      ExFreePool(gp_callinfo);
    }    
  }

  //*pdwDataWritten == 0 表示失败....否则返回真实的..用户程序需要根据这个返回值判断自己提供的缓冲区是否足够
  *pdwDataWritten = dwwrite;
  return NtStatus;
  
}

/////////////////////

NTSTATUS get_eip_info(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, ULONG* pdwDataWritten)
{
  NTSTATUS NtStatus = STATUS_SUCCESS;
  PCHAR pOutputBuffer = NULL;
  int dwwrite = 0;


  if(Irp->MdlAddress)
    {
        pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
    }

  //DbgPrint("------------------get data 0000000 --------------------");
  if(pOutputBuffer)  
    {
    if(!IsListEmpty(&heipinfo_list)&&(can_get_callinfo == TRUE))  // 因为结构被多次用..除非慢满了..否则有数据也不取的..
    {
      PLIST_ENTRY pEntry;
      
      //DbgPrint("------------------get data --------------------");
      pEntry = RemoveHeadList(&heipinfo_list);
      gp_eipinfo = CONTAINING_RECORD(pEntry,EIP_INFO,ListEntry);
      
      if(pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(EIP_INFO))
      {
        RtlCopyMemory(pOutputBuffer,gp_eipinfo,sizeof(EIP_INFO));
        dwwrite = sizeof(EIP_INFO);
        //can_get_callinfo = FALSE;
      }
      else dwwrite = 0;
      ExFreePool(gp_eipinfo);
    }    
  }

  //*pdwDataWritten == 0 表示失败....否则返回真实的..用户程序需要根据这个返回值判断自己提供的缓冲区是否足够
  *pdwDataWritten = dwwrite;
  return NtStatus;
  
}
NTSTATUS SysIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION pIoStackIrp = NULL;
    ULONG dwDataWritten = 0;

  pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);    
  if(pIoStackIrp) /* Should Never Be NULL! */
    {
    switch(pIoStackIrp->Parameters.DeviceIoControl.IoControlCode)
    {

    case IOCTL_GET_DBGPRINT_DATA:
      handle_get_dbdata(Irp, pIoStackIrp, &dwDataWritten);
      break;
    case IOCTL_PASS_USER_EVENT:
      handle_pass_uevent(Irp, pIoStackIrp, &dwDataWritten);
      InitializeListHead(&hdbdata_list);
       
      install_idt_hook(0x2d, (PVOID)my_int_2d);

      break;
    case IOCTL_UNPASS_USER_EVENT:
      if(pKEvent)
      {
        ObDereferenceObject(pKEvent);
        pKEvent = NULL;
      }
      break;
    case IOCTL_INSTALL_INT3:
      InitializeListHead(&hbpdata_list);
      install_idt_hook(0x3, (PVOID)my_interrupt_hook);
      
      break;
    case IOCTL_UNINSTALL_INT3:
      unistall_idt_hook(0x3);
      break;
    case IOCTL_INSERT_BREAKPOINT:
      // 验证一下..
      insert_breakpoint((PVOID)(*(ULONG*)Irp->AssociatedIrp.SystemBuffer));
      break;
    case IOCTL_GET_BREAKPOINT_CONTEXT:
      get_bpcontext(Irp, pIoStackIrp, &dwDataWritten);
      break;
    case IOCTL_SET_STEPING:
      b_steping = TRUE;
      break;
    case IOCTL_SET_STEPING_COUNT:
      tmp_count = *(int*)Irp->AssociatedIrp.SystemBuffer;
      break;
    case IOCTL_UNSET_STEPING:
      b_steping = FALSE;
      break;
    case IOCTL_INSTALL_INT1:
      InitializeListHead(&hcalldata_list);
      InitializeListHead(&heipinfo_list);
      install_idt_hook(0x1, (PVOID)my_int_1);
      break;
    case IOCTL_UNINSTALL_INT1:
      unistall_idt_hook(0x1);
      break;
    case IOCTL_GET_CALL_DATA:
      get_call_info(Irp, pIoStackIrp, &dwDataWritten);
      break;
    case IOCTL_SET_GET_EIPINFO:
      call_or_address = TRUE;  //// 是否只用一个命令就可以,...
      can_get_callinfo = FALSE; //////////////////////////////////// ????????
      break;
    case IOCTL_SET_GET_CALLINFO:
      call_or_address = FALSE;
      break;
    case IOCTL_GET_EIP_DATA:
      get_eip_info(Irp, pIoStackIrp, &dwDataWritten);
      break;


    }
  }
    Irp->IoStatus.Status = NtStatus;
    Irp->IoStatus.Information = dwDataWritten;
  IoCompleteRequest(Irp, IO_NO_INCREMENT);
  return NtStatus;
}




////////////////////////////////

#define DELAY_ONE_MICROSECOND   (-10)
#define DELAY_ONE_MILLISECOND  (DELAY_ONE_MICROSECOND*1000)

VOID MySleep(LONG msec)
  {
    LARGE_INTEGER my_interval;
    my_interval.QuadPart = DELAY_ONE_MILLISECOND;
    my_interval.QuadPart *= msec;
    KeDelayExecutionThread(KernelMode,0,&my_interval);
  }

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
  
  NTSTATUS NtStatus = STATUS_SUCCESS;
    ULONG uiIndex = 0;
    PDEVICE_OBJECT pDeviceObject = NULL;
    UNICODE_STRING usDriverName, usDosDeviceName;
  ULONG i;
  NTSTATUS status;  
  

//  install_idt_hook(NT_INT_TIMER, (PVOID)my_interrupt_hook);
//  install_idt_hook(1, (PVOID)my_int_1);
  
  

    RtlInitUnicodeString(&usDriverName, L"\\Device\\Sys_SKD");
    RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\Sys_SKD"); 

    NtStatus = IoCreateDevice(theDriverObject, 
                          0, 
                &usDriverName, 
                FILE_DEVICE_UNKNOWN, 
                FILE_DEVICE_SECURE_OPEN, 
                FALSE, 
                &pDeviceObject);


    if(NtStatus == STATUS_SUCCESS)
    {
        theDriverObject->MajorFunction[IRP_MJ_CLOSE]             = SysClose;
        theDriverObject->MajorFunction[IRP_MJ_CREATE]            = SysCreate;
        theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]    = SysIoControl;
    theDriverObject->DriverUnload  = OnUnload; 
    IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);
  }

  
  
//   insert_breakpoint((PVOID)0x8057a588);

//   install_idt_hook(0x2d, (PVOID)my_int_2d);


   
   return STATUS_SUCCESS;
}