怎么在WINDOWS下对CMOS进行读写?就是怎么去读/写CMOS用VISUAL C++ 6.0来做.DOS下的我知道,70和71端口,但WINDOWS编程本人一壳不同,请各位大狭多多指教了.

解决方案 »

  1.   

    embed asm code to do this job :)
      

  2.   

    In DOS , you can can simply call the _inp/_outp functions to access CMOS, in windows I recommend WinIO to you. http://www.internals.com/utilities/winio.zipWhy should I use the WinIo library if I can simply call the _inp/_outp functions? 
    Port access under Windows 9x is possible as long as you refrain from accessing trapped ports. Several VxDs hook I/O ports to virtualize hardware and will block any attempt to modify these ports from a Windows application. If you wish to control a piece of hardware which is mapped to free addresses such as 300h, you can use the inp/outp functions with no fear. However, any attempt to access system ports (such as those reserved for the DMA chip, HD controller, etc.) will be to no avail. To control such ports from your application, you'll need to use the WinIo library which executes in ring 0 and bypasses Windows port trapping mechanism. Under Windows NT/2000, user mode applications are completely prohibited from accessing I/O ports. Any attempt to access an I/O port from a ring 3 application is terminated with a protection fault. Thus, the only way to overcome this limitation is by using a kernel-mode device driver, such as the one supplied with the WinIo library.
      

  3.   

    1.在Win95/98下,您可以使用_inpw,_outpw;
    2.在Win2000下,您可以使用CreateFile()或ReadFile()读写70,71;
      在Win2000下,您也可以使用楼上提供的WinIO,
      address:http://www.internals.com/
      

  4.   

    你的的程序必须有ring0的特权级,才能在winXP下对cmos访问
      

  5.   

    那怎樣才能獲得ring0的特权级
      

  6.   

    转贴过来
    Windows  NT/2000下不用驱动的Ring0代码实现              
                           WebCrazy(http://webcrazy.yeah.net/)    
     
           大家知道,Windows  NT/2000为实现其可靠性,严格将系统划分为内核模式与用户模式,在i386系统中分别对应CPU的Ring0与Ring3级别。Ring0下,可以执行特权级指令,对任何I/O设备都有访问权等等。要实现从用户态进入核心态,即从Ring  3进入Ring  0必须借助CPU的某种门机制,如中断门、调用门等。而Windows  NT/2000提供用户态执行系统服务(Ring  0例程)的此类机制即System  Service的int  2eh中断服务等,严格的参数检查,只能严格的执行Windows  NT/2000提供的服务,而如果想执行用户提供的Ring  0代码(指运行在Ring  0权限的代码),常规方法似乎只有编写设备驱动程序。本文将介绍一种在用户态不借助任何驱动程序执行Ring0代码的方法。  
     
           Windows  NT/2000将设备驱动程序调入内核区域(常见的位于地址0x80000000上),由DPL为0的GDT项8,即cs为8时实现Ring  0权限。本文通过在系统中构造一个指向我们的代码的调用门(CallGate),实现Ring0代码。基于这个思路,为实现这个目的主要是构造自己的CallGate。CallGate由系统中叫Global  Descriptor  Table(GDT)的全局表指定。GDT地址可由i386指令sgdt获得(sgdt不是特权级指令,普通Ring  3程序均可执行)。GDT地址在Windows  NT/2000保存于KPCR(Processor  Control  Region)结构中(见《再谈Windows  NT/2000环境切换》)。GDT中的CallGate是如下的格式:  
     
           typedef  struct  
           {  
                   unsigned  short    offset_0_15;  
                   unsigned  short    selector;  
     
                   unsigned  char        param_count  :  4;  
                   unsigned  char        some_bits      :  4;  
     
                   unsigned  char        type                :  4;  
                   unsigned  char        app_system    :  1;  
                   unsigned  char        dpl                  :  2;  
                   unsigned  char        present          :  1;  
             
                   unsigned  short    offset_16_31;  
           }  CALLGATE_DESCRIPTOR;  
     
           GDT位于内核区域,一般用户态的程序是不可能对这段内存区域有直接的访问权。幸运的是Windows  NT/2000提供了一个叫PhysicalMemory的Section内核对象位于\Device的路径下。顾名思义,通过这个Section对象可以对物理内存进行操作。用objdir.exe对这个对象分析如下:  
     
           C:\NTDDK\bin  >objdir  /D  \Device  
     
           PhysicalMemory                                        
                   Section  
                   DACL  -    
                         Ace[  0]  -  Grant  -  0xf001f  -  NT  AUTHORITY\SYSTEM  
                                                             Inherit:    
                                                             Access:  0x001F    and    (  D  RCtl  WOwn  WDacl  )  
     
                         Ace[  1]  -  Grant  -  0x2000d  -  BUILTIN\Administrators  
                                                             Inherit:    
                                                             Access:  0x000D    and    (  RCtl  )  
     
           从dump出的这个对象DACL的Ace可以看出默认情况下只有SYSTEM用户才有对这个对象的读写权限,即对物理内存有读写能力,而Administrator只有读权限,普通用户根本就没有权限。不过如果我们有Administrator权限就可以通过GetSecurityInfo、SetEntriesInAcl与SetSecurityInfo这些API来修改这个对象的ACE。这也是我提供的代码需要Administrator的原因。实现的代码如下:  
     
           VOID  SetPhyscialMemorySectionCanBeWrited(HANDLE  hSection)  
           {  
     
                 PACL  pDacl=NULL;  
                 PACL  pNewDacl=NULL;  
                 PSECURITY_DESCRIPTOR  pSD=NULL;  
                 DWORD  dwRes;  
                 EXPLICIT_ACCESS  ea;  
     
                 if(dwRes=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,  
                                       NULL,NULL,&pDacl,NULL,&pSD)!=ERROR_SUCCESS)  
                       {  
                             printf(    "GetSecurityInfo  Error  %u\n  ",  dwRes  );  
                             goto  CleanUp;  
                       }  
     
                 ZeroMemory(&ea,  sizeof(EXPLICIT_ACCESS));  
                 ea.grfAccessPermissions  =  SECTION_MAP_WRITE;  
                 ea.grfAccessMode  =  GRANT_ACCESS;  
                 ea.grfInheritance=  NO_INHERITANCE;  
                 ea.Trustee.TrusteeForm  =  TRUSTEE_IS_NAME;  
                 ea.Trustee.TrusteeType  =  TRUSTEE_IS_USER;  
                 ea.Trustee.ptstrName  =    "CURRENT_USER  ";  
     
     
                 if(dwRes=SetEntriesInAcl(1,&ea,pDacl,&pNewDacl)!=ERROR_SUCCESS)  
                       {  
                             printf(    "SetEntriesInAcl  %u\n  ",  dwRes  );  
                             goto  CleanUp;  
                       }  
     
                 if(dwRes=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL)!=ERROR_SUCCESS)  
                       {  
                             printf(  "SetSecurityInfo  %u\n  ",dwRes);  
                             goto  CleanUp;  
                       }  
     
           CleanUp:  
     
                 if(pSD)  
                       LocalFree(pSD);  
                 if(pNewDacl)  
                       LocalFree(pSD);  
           }  
     
           这段代码对给定HANDLE的对象增加了如下的ACE:    
     
           PhysicalMemory                                        
                   Section  
                   DACL  -    
                         Ace[  0]  -  Grant  -  0x2  -  WEBCRAZY\Administrator  
                                                             Inherit:    
                                                             Access:  0x0002        //SECTION_MAP_WRITE  
     
           这样我们在有Administrator权限的条件下就有了对物理内存的读写能力。但若要修改GDT表实现Ring  0代码。我们将面临着另一个难题,因为sgdt指令获得的GDT地址是虚拟地址(线性地址),我们只有知道GDT表的物理地址后才能通过\Device\PhysicalMemory对象修改GDT表,这就牵涉到了线性地址转化成物理地址的问题。我们先来看一看Windows  NT/2000是如何实现这个的:  
     
           kd  >  u  nt!MmGetPhysicalAddress  l  30  
           ntoskrnl!MmGetPhysicalAddress:  
           801374e0  56                              push        esi  
           801374e1  8b742408                  mov          esi,[esp+0x8]  
           801374e5  33d2                          xor          edx,edx  
           801374e7  81fe00000080          cmp          esi,0x80000000  
           801374ed  722c                          jb        ntoskrnl!MmGetPhysicalAddress+0x2b  (8013751b)  
           801374ef  81fe000000a0          cmp          esi,0xa0000000  
           801374f5  7324                          jnb      ntoskrnl!MmGetPhysicalAddress+0x2b  (8013751b)  
           801374f7  39153ce71780          cmp          [ntoskrnl!MmKseg2Frame  (8017e73c)],edx  
           801374fd  741c                          jz        ntoskrnl!MmGetPhysicalAddress+0x2b  (8013751b)  
           801374ff  8bc6                          mov          eax,esi  
           80137501  c1e80c                      shr          eax,0xc  
           80137504  25ffff0100              and          eax,0x1ffff  
           80137509  6a0c                          push        0xc  
           8013750b  59                              pop          ecx  
           8013750c  e8d3a7fcff              call        ntoskrnl!_allshl  (80101ce4)  
           80137511  81e6ff0f0000          and          esi,0xfff  
           80137517  03c6                          add          eax,esi  
           80137519  eb17                          jmp      ntoskrnl!MmGetPhysicalAddress+0x57  (80137532)  
           8013751b  8bc6                          mov          eax,esi  
           8013751d  c1e80a                      shr          eax,0xa  
           80137520  25fcff3f00              and          eax,0x3ffffc  
           80137525  2d00000040              sub          eax,0x40000000  
           8013752a  8b00                          mov          eax,[eax]  
           8013752c  a801                          test        al,0x1  
           8013752e  7506                          jnz      ntoskrnl!MmGetPhysicalAddress+0x44  (80137536)  
           80137530  33c0                          xor          eax,eax  
           80137532  5e                              pop          esi  
           80137533  c20400                      ret          0x4  
      

  7.   

    http://www.internals.com/faq_main.htmWe have learned sth from there,u' come here if u have time,I think it maybe help u;