青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 126,  comments - 73,  trackbacks - 0
摘要:數字簽名SIGN保證控件在下載時候的安全性。如果你的代碼已經經過數字簽名,即使用戶IE的安全設置很高也能下載,安裝并登記。但是在頁面上初始化,或者用腳本運行這個控件,為了保證安全性,還需要進行MARK。  
   
  數字簽名SIGN  
  曹曉峰  
   
  摘要:數字簽名保證控件的安全性。數字簽名使用證書。證書一般有個人證書和授信公司證書。個人證書是對個人的信任,由個人承擔責任,控件每次下載時需要進行確認。公司證書是由第三方公司發布的,保證控件的安全性,公司證書需要付費。Windows授信的證書公司有VeriSign,SecureSign等等。由這些公司證書簽名的控件在下載的時候不需要確認。  
   
  一.工具  
  工具包括以下幾個軟件:  
  makecert.exe     制作cer格式的證書,即X.509證書,同時可以創建私鑰(防止抵賴)  
  cert2spc.exe     將cer格式證書轉換成spc格式證書,即PKCS   #7證書  
  signcode.exe     將證書簽署到ocx上去  
  chktrust.exe     檢查簽署證書后的ocx是否正確  
  certmgr.exe,是管理證書用的,可以從這里面導出root.cer來,不過沒有私鑰用不上。  
   
  二.步驟  
  下面是具體的步驟:  
  1、創建一個自己的證書文件:  
  makecert   /sv   "Record.PVK"   /n   "CN=SinoWave"   dream.cer  
  這里,Record.PVK表示新創建的私人密鑰保存文件名  
              SinoWave是你想顯示的公司名  
              dream.cer是你創建最后的證書文件名  
  這些根據你自己的要求填寫,最后得到Record.PVK和dream.cer兩個文件。其中,運行過程中需要輸入私人密鑰的保護密碼(sw),一定要輸入一致,不要出錯。  
   
  2、轉換cer格式為spc格式(可以省略),得到dream.spc文件。  
   
  cert2spc   dream.cer   dream.spc  
   
  3、用VS6工具中的   cabarc生成internet分發的CAB包,  
  cabarc.exe   N   DataTransfer.cab   DataTransfer.ocx  
   
  4、同時制作分發代碼(.htm,其中包含使IE可以自動下載安裝包的代碼)。  
  現在得到了2個文件DataTransfer.CAB和DataTransfer.htm。  
  .htm中包含類似如下的代碼:  
  <OBJECT   ID="   DataTransfer   "   CLASSID="CLSID:   CA466D54-0684-49D2-B0C3-DD7E09EA76D3"   CODEBASE="http://192.9.200.8/DataTransfer.CAB#version=1,0,0,0"></OBJECT>  
  注意:一定要寫上"http://   192.9.200.8/",真正發行時最好使用url。  
   
  5、給CAB文件簽名  
  運行signcode,命令行的我沒有試驗通過,我是通過界面實現的。signcode運行后會出現數字簽名向導,首先選擇DataTransfer.CAB,下一步后會出現簽名選項,一種是典型,一種是自定義。選擇自定義,這樣才能從文件選擇證書,選擇前面制作的dream.spc,再下一步是選擇私鑰文件,選擇Record.PVK,輸入私人密鑰的保護密碼,選擇散列算法,一般用md5就可以了,下一步是選擇其他證書,直接下一步,填寫一下這個控件的聲明,用戶用ie瀏覽的時候,會彈出證書說明,再下一步是加蓋時間戳,例如http://timestamp.sheca.com/timestamp  
     
  6、用chktrust檢查是否正確  
  chktrust   -v   DataTransfer.CAB  
   
  7、將簽名后的DataTransfer.CAB和DataTransfer.htm復制到IIS的某個目錄下。并在IE中打開DataTransfer.htm文件進行測試。  

ActiveX控件的安全初始化和腳本操作MARK  
  曹曉峰  
   
  簡介  
  很多微軟的ActiveX控件(本地/遠程)都需要使用持久性數據進行初始化,而且它們大多數都是可以通過腳本進行操作的   (支持一個方法,事件和屬性的集合提供腳本語言操作)。初始化(使用持久性數據)和腳本操作都需要一個確定的安全性機制保證其安全性不被違背。  
   
  初始化安全性  
  當一個控件初始化時,可以從一個   IPersist*   接口獲得數據   (來自一個本地/遠端的URL)提供初始化狀態。這是一個潛在的安全隱患,因為數據可能來自一個不可信的數據源。不提供安全性保證的控件將無視數據源的安全性。  
  有兩種方法可以檢測控件的初始化安全性。第一種使用組件分組管理器(Component   Categories   Manager)創建一個正確的入口到系統注冊表。IE檢測注冊表之后才調用你的控件決定是否這些入口存在。第二種方法實現一個名稱為IObjectSafe的接口到你的控件。如果IE發現你的控件支持IObjectSafety,它調用   IObjectSafety::SetInterfaceSafetyOptions   方法然后才載入你的控件。  
  注意,第一種方法是基于組件的安全性,也就是如果設置了注冊表,那么整個組件的所有的接口都被標注為安全的;而第二種方法(實現IObjectSafety)是基于接口的,也就是它的作用范圍是接口,必須一個接口一個接口地標注。第二種方法的運行性能要優于第一種。在保證安全的情況下,兩種方法同時使用更好。  
   
  腳本操作安全性  
  代碼簽字可以保證用戶其代碼的可信度。但是運行一個   ActiveX   控件可以被腳本訪問將帶來幾個新的安全性問題。即使控件被認為是可靠的,如果使用不可信腳本代碼訪問也不能保證其安全性。比如,微軟的   Word   被認為是一個安全的程序,但是一個宏可以使用自動化模型的腳本刪除用戶計算機上的文件,載入宏病毒或者蠕蟲病毒。  
  有兩種方法提供你的控件的腳本操作安全性保證。第一種是使用組件分組管理器   (Component   Categories   Manager)   ——在組件導入以后在注冊表上面創建正確的入口。IE在腳本操作之前檢查注冊表確認安全性。第二種是實現一個   IObjectSafety   接口到你的控件。如果IE發現你的控件支持   IObjectSafety,就在導入控件之前調用   IObjectSafety::SetInterfaceSafetyOptions   方法來確保安全性腳本操作。  
  注意,第一種方法是基于組件的安全性,也就是如果設置了注冊表,那么整個組件的所有的接口都被標注為安全的;而第二種方法是基于接口的,也就是它的作用范圍是接口,必須一個接口一個接口地標注。第二種方法的運行性能要優于第一種。在保證安全的情況下,兩種方法同時使用更好。  
   
  方法一:IObjectSafety方法:  
  MFC:實現接口IObjectSafety  
  ATL:繼承接口IObjectSafetyImpl<CPolyCtl,   INTERFACESAFE_FOR_UNTRUSTED_CALLER|   INTERFACESAFE_FOR_UNTRUSTED_DATA   >  
   
  具體方法:  
  一. MFC  
  1. 在控件類的頭文件里  
  (1)加入文件#include   <objsafe.h>  
  (2)在類的定義里,聲明接口映射表,并加入接口定義(以嵌套類的形式)  
  DECLARE_INTERFACE_MAP()  
  BEGIN_INTERFACE_PART(ObjSafe,   IObjectSafety)  
  STDMETHOD_(HRESULT,   GetInterfaceSafetyOptions)   (    
                          /*   [in]   */   REFIID   riid,  
                          /*   [out]   */   DWORD   __RPC_FAR   *pdwSupportedOptions,  
                          /*   [out]   */   DWORD   __RPC_FAR   *pdwEnabledOptions  
  );  
                   
                  STDMETHOD_(HRESULT,   SetInterfaceSafetyOptions)   (    
                          /*   [in]   */   REFIID   riid,  
                          /*   [in]   */   DWORD   dwOptionSetMask,  
                          /*   [in]   */   DWORD   dwEnabledOptions  
  );  
  END_INTERFACE_PART(ObjSafe);  
   
  2. 在控件類的CPP文件里  
  (1)建立接口映射表  
  BEGIN_INTERFACE_MAP(   CMyCtrl,   COleControl   )  
  INTERFACE_PART(CMyCtrl,   IID_IObjectSafety,   ObjSafe)  
  END_INTERFACE_MAP()  
  (2)加入接口類的實現  
  ULONG   FAR   EXPORT   CMyCtrl::XObjSafe::AddRef()  
  {  
          METHOD_PROLOGUE(CMyCtrl,   ObjSafe)  
          return   pThis->ExternalAddRef();  
  }  
   
  ULONG   FAR   EXPORT   CMyCtrl::XObjSafe::Release()  
  {  
          METHOD_PROLOGUE(CMyCtrl,   ObjSafe)  
          return   pThis->ExternalRelease();  
  }  
   
  HRESULT   FAR   EXPORT   CMyCtrl::XObjSafe::QueryInterface(  
          REFIID   iid,   void   FAR*   FAR*   ppvObj)  
  {  
          METHOD_PROLOGUE(CMyCtrl,   ObjSafe)  
          return   (HRESULT)pThis->ExternalQueryInterface(&iid,   ppvObj);  
  }  
   
  const   DWORD   dwSupportedBits   =    
  INTERFACESAFE_FOR_UNTRUSTED_CALLER   |  
  INTERFACESAFE_FOR_UNTRUSTED_DATA;  
  const   DWORD   dwNotSupportedBits   =   ~   dwSupportedBits;  
   
  /////////////////////////////////////////////////////////////////////////////  
  //   CStopLiteCtrl::XObjSafe::GetInterfaceSafetyOptions  
  //   Allows   container   to   query   what   interfaces   are   safe   for   what.   We're  
  //   optimizing   significantly   by   ignoring   which   interface   the   caller   is  
  //   asking   for.  
  HRESULT   STDMETHODCALLTYPE    
  CMyCtrl::XObjSafe::GetInterfaceSafetyOptions(    
  /*   [in]   */   REFIID   riid,  
                  /*   [out]   */   DWORD   __RPC_FAR   *pdwSupportedOptions,  
                  /*   [out]   */   DWORD   __RPC_FAR   *pdwEnabledOptions)  
  {  
  METHOD_PROLOGUE(CMyCtrl,   ObjSafe)  
   
  HRESULT   retval   =   ResultFromScode(S_OK);  
   
  //   does   interface   exist?  
  IUnknown   FAR*   punkInterface;  
  retval   =   pThis->ExternalQueryInterface(&riid,    
  (void   *   *)&punkInterface);  
  if   (retval   !=   E_NOINTERFACE)   { //   interface   exists  
  punkInterface->Release();   //   release   it--just   checking!  
  }  
   
  //   we   support   both   kinds   of   safety   and   have   always   both   set,  
  //   regardless   of   interface  
  *pdwSupportedOptions   =   *pdwEnabledOptions   =   dwSupportedBits;  
   
  return   retval;   //   E_NOINTERFACE   if   QI   failed  
  }  
   
  /////////////////////////////////////////////////////////////////////////////  
  //   CStopLiteCtrl::XObjSafe::SetInterfaceSafetyOptions  
  //   Since   we're   always   safe,   this   is   a   no-brainer--but   we   do   check   to   make  
  //   sure   the   interface   requested   exists   and   that   the   options   we're   asked   to  
  //   set   exist   and   are   set   on   (we   don't   support   unsafe   mode).  
  HRESULT   STDMETHODCALLTYPE    
  CMyCtrl::XObjSafe::SetInterfaceSafetyOptions(    
                  /*   [in]   */   REFIID   riid,  
                  /*   [in]   */   DWORD   dwOptionSetMask,  
                  /*   [in]   */   DWORD   dwEnabledOptions)  
  {  
          METHOD_PROLOGUE(CMyCtrl,   ObjSafe)  
   
  //   does   interface   exist?  
  IUnknown   FAR*   punkInterface;  
  pThis->ExternalQueryInterface(&riid,   (void   *   *)&punkInterface);  
  if   (punkInterface)   { //   interface   exists  
  punkInterface->Release();   //   release   it--just   checking!  
  }  
  else   {   //   interface   doesn't   exist  
  return   ResultFromScode(E_NOINTERFACE);  
  }  
   
  //   can't   set   bits   we   don't   support  
  if   (dwOptionSetMask   &   dwNotSupportedBits)   {    
  return   ResultFromScode(E_FAIL);  
  }  
   
  //   can't   set   bits   we   do   support   to   zero  
  dwEnabledOptions   &=   dwSupportedBits;  
  //   (we   already   know   there   are   no   extra   bits   in   mask   )  
  if   ((dwOptionSetMask   &   dwEnabledOptions)   !=  
    dwOptionSetMask)   {  
  return   ResultFromScode(E_FAIL);  
  }  
  //   don't   need   to   change   anything   since   we're   always   safe  
  return   ResultFromScode(S_OK);  
  }  
  二. ATL  
  在控件類加一個繼承接口即可  
  public   IObjectSafetyImpl<CAtlCtrl,   INTERFACESAFE_FOR_UNTRUSTED_CALLER    
                                                      |   INTERFACESAFE_FOR_UNTRUSTED_DATA>  
方法二:使用組件分組管理器  
  前面提到,IE通過檢測注冊表決定一個控件是否是可以安全性初始化和腳本操作的。IE通過調用   ICatInformation::IsClassOfCategories   方法決定是否控件支持給出的安全性分組。  
  如果一個控件使用組件分組管理器將自己注冊為安全的,該控件的注冊表入口就包含一個實現的分組關鍵字,該關鍵字含有一個或者兩個子鍵。一個子鍵設置控件支持安全性初始化,另一個設置支持安全性腳本操作。安全性初始化子鍵依賴于   CATID_SafeForInitializing;   安全性腳本操作子鍵依賴于   CATID_SafeForScripting。(其他組件分組子鍵定義在   Comcat.h   文件,而安全性初始化和腳本操作子鍵定義在   Objsafe.h   文件。)    
  下列演示顯示了一個注冊表入口(Tabular   Data   Control),該ActiveX控件同IE綁定支持創建數據驅動的網頁。因為控件是可以安全性腳本操作和初始化的,注冊表中將其標記為安全性腳本操作  
  (7DD95801-9882-11CF-9FA9-00AA006C42C4)   和安全性初始化  
  (7DD95802-9882-11CF-9FA9-00AA006C42C4)。  
  注意,這兩個GUID值是固定的。  
  將一個控件注冊為安全的  
  系統注冊表含有一個組件分組鍵來羅列每一個安裝在系統中的組件的功能性分組。下面演示了一個組件分組鍵。假設   CATID_SafeForScripting   (7DD95801-9882-11CF-9FA9-00AA006C42C4)   和   CATID_SafeForInitializing   (7DD95802-9882-11CF-9FA9-00AA006C42C4)   在列表之中。    
  要創建一個組件分組的子鍵,你的控件必須包含以下步驟:  
  1.創建一個組件分組管理器(Component   Categories   Manager)實例來接收   ICatRegister   接口的地址。  
  2.設置正確的   CATEGORYINFO   結構分量。  
  3.調用   ICatRegister::RegisterCategories   方法,將初始化的   CATEGORYINFO   結構變量傳遞給這個方法。  
     
  下面的例子演示如何使用這些步驟來完成一個名稱為   CreateComponentCategory全局函數,生成組件分組。  
  #include   "comcat.h"  
  HRESULT   CreateComponentCategory(CATID   catid,WCHAR*   catDescription)  
  {  
  ICatRegister*   pcr   =   NULL   ;  
  HRESULT   hr   =   S_OK   ;  
       
  //創建一個組件管理器實例(進程內)  
  hr   =   CoCreateInstance(CLSID_StdComponentCategoriesMgr,  
  NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&pcr);  
  if   (FAILED(hr))  
  return   hr;  
       
  //   確信   HKCR\Component   Categories\{..catid...}   鍵已經被注冊  
  CATEGORYINFO   catinfo;  
  catinfo.catid   =   catid;  
  catinfo.lcid   =   0x0409   ;   //   英語  
       
  //   確信提供的描述在127個字符以內  
  int   len   =   wcslen(catDescription);  
  if   (len>127)  
  len   =   127;  
  wcsncpy(catinfo.szDescription,catDescription,len);  
  //   確信描述使用'\0'結束  
  catinfo.szDescription[len]   =   '\0';  
       
  hr   =   pcr->RegisterCategories(1,&catinfo);  
  pcr->Release();  
       
  return   hr;  
  }  
   
  當一個子鍵被創建到需要的分組,控件應該注冊到該分組,需要以下步驟:  
  1.創建一個組件分組管理器實例接收   ICatRegister   接口地址。  
  2.調用   ICatRegister::RegisterClassImplCategories   方法,將控件的   CLSID   和需要的   category   ID   作為參數傳遞給函數。  
       
  下面的例子演示如何將一個名稱為   RegisterCLSIDInCategory   加入實例控件。  
       
  #include   "comcat.h"  
  HRESULT   RegisterCLSIDInCategory(REFCLSID   clsid,CATID   catid)  
  {  
  //   注冊你的組件分組信息  
  ICatRegister*   pcr   =   NULL   ;  
  HRESULT   hr   =   S_OK   ;  
  hr   =   CoCreateInstance(CLSID_StdComponentCategoriesMgr,  
  NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&pcr);  
  if   (SUCCEEDED(hr))  
  {  
  //   注冊已實現的類到分組  
  CATID   rgcatid[1]   ;  
  rgcatid[0]   =   catid;  
  hr   =   pcr->RegisterClassImplCategories(clsid,1,rgcatid);  
  }  
       
  if   (pcr   !=   NULL)  
  pcr->Release();  
       
  return   hr;  
  }  
       
  一個控件應該在調用   DLLRegisterServer   函數是注冊安全性初始化和腳本操作。(DLLRegisterServer   由組件對象模型   [COM]   調用創建注冊表入口)   在實例組件中   DLLRegisterServer   函數調用了   CreateComponentCategory   和   RegisterCLSIDInCategory   函數   (它們保證控件的安全性初始化和腳本操作)。下面的就是   DLLRegisterServer   的實現。  
       
  STDAPI   DllRegisterServer(void)  
  {  
  HRESULT   hr;   //   return   for   safety   functions  
       
  AFX_MANAGE_STATE(_afxModuleAddrThis);  
       
  if   (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(),_tlid))    
  return   ResultFromScode(SELFREG_E_TYPELIB);  
       
  if   (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))  
  return   ResultFromScode(SELFREG_E_CLASS);  
       
  RegisterTwo(CLSID_SafeItem);  
       
  return   NOERROR;  
  }  
       
  HRESULT   RegisterTwo(REFCLSID   clsid)  
  {  
  //   注冊控件是安全性初始化的  
  /////////////////////////////////////////////////  
  HRESULT   hr;  
  hr   =   CreateComponentCategory(CATID_SafeForInitializing,   L"Controls   safely   initializable   from   persistent   data!");  
  if   (FAILED(hr))  
  return   hr;  
   
  hr   =   RegisterCLSIDInCategory(clsid,   CATID_SafeForInitializing);  
  if   (FAILED(hr))  
  return   hr;  
  //   注冊控件是安全性腳本操作的  
   
  hr   =   CreateComponentCategory(CATID_SafeForScripting,   L"Controls   safely   scriptable!");  
  if   (FAILED(hr))  
  return   hr;  
   
  hr   =   RegisterCLSIDInCategory(clsid,   CATID_SafeForScripting);  
  if   (FAILED(hr))  
  return   hr;  
   
  return   S_OK;  
  }  
  作為一個創建所有安全性分組入口到注冊表的控件,它也應該負責卸載所有的分組信息。COM   調用控件的   DLLUnRegisterServer   函數刪除相應的注冊表入口然后卸載該控件。  
       
  要卸載一個安全性初始化和腳本操作控件,控件應該完成以下任務:  
  1   創建一個組件分類管理器實例接收   ICatRegister   接口地址。  
  2   調用   ICatRegister::UnRegisterClassImplCategories   方法,將控件的   CLSID   和必要的   category   ID   作為參數傳遞  
       
  下面的例子演示如何完成一個   UnRegisterCLSIDInCategory   。  
       
  HRESULT   UnRegisterCLSIDInCategory(REFCLSID   clsid,CATID   catid)  
  {  
  ICatRegister*   pcr   =   NULL   ;  
  HRESULT   hr   =   S_OK   ;  
       
  hr   =   CoCreateInstance(CLSID_StdComponentCategoriesMgr,  
  NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&pcr);  
  if   (SUCCEEDED(hr))  
  {  
  //   從分組卸載組件  
  CATID   rgcatid[1]   ;  
  rgcatid[0]   =   catid;  
  hr   =   pcr->UnRegisterClassImplCategories(clsid,1,rgcatid);  
  }  
       
  if   (pcr   !=   NULL)  
  pcr->Release();  
       
  return   hr;  
  }  
       
  我們前面提過,一個控件負責刪除安全性初始化和腳本操作入口,下面演示如何完成這兩個步驟:    
       
  STDAPI   DllUnregisterServer(void)  
  {  
  AFX_MANAGE_STATE(_afxModuleAddrThis);  
   
  if   (!AfxOleUnregisterTypeLib(_tlid,   _wVerMajor,   _wVerMinor))  
  return   ResultFromScode(SELFREG_E_TYPELIB);  
   
  if   (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))  
  return   ResultFromScode(SELFREG_E_CLASS);  
   
  UnRegisterTwo(CLSID_SafeItem);  
   
  return   NOERROR;  
  }  
   
  HRESULT   UnRegisterCLSIDInCategory(REFCLSID   clsid,CATID   catid)  
  {  
  ICatRegister*   pcr   =   NULL   ;  
  HRESULT   hr   =   S_OK   ;  
   
  hr   =   CoCreateInstance(CLSID_StdComponentCategoriesMgr,  
  NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&pcr);  
  if   (SUCCEEDED(hr))  
  {  
  //   從分組卸載組件  
  CATID   rgcatid[1]   ;  
  rgcatid[0]   =   catid;  
  hr   =   pcr->UnRegisterClassImplCategories(clsid,   1,   rgcatid);  
  }  
   
  if   (pcr   !=   NULL)  
  pcr->Release();  
   
  return   hr;  
  }  
  附件,   CXFMARK.h  
  以上函數形成一個文件,  
  #include   "comcat.h"  
   
  const   GUID   CATID_SafeForInitializing   =    
  {0x7DD95802,0x9882,0x11CF,{0x9F,0xA9,0x00,0xAA,0x00,0x6C,0x42,0xC4}};  
  const   GUID   CATID_SafeForScripting   =    
  {0x7DD95801,0x9882,0x11CF,{0x9F,0xA9,0x00,0xAA,0x00,0x6C,0x42,0xC4}};  

HRESULT   CreateComponentCategory(CATID   catid,WCHAR*   catDescription)  
  {  
  ICatRegister*   pcr   =   NULL   ;  
  HRESULT   hr   =   S_OK;  
   
  //創建一個組件管理器實例(進程內)  
  hr   =   CoCreateInstance(CLSID_StdComponentCategoriesMgr,  
  NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&pcr);  
  if   (FAILED(hr))  
  return   hr;  
   
  //   確信   HKCR\Component   Categories\{..catid...}   鍵已經被注冊  
  CATEGORYINFO   catinfo;  
  catinfo.catid   =   catid;  
  catinfo.lcid   =   0x0409   ;   //   英語  
   
  //   確信提供的描述在127個字符以內  
  int   len   =   wcslen(catDescription);  
  if   (len>127)  
  len   =   127;  
  wcsncpy(catinfo.szDescription,catDescription,len);  
  //   確信描述使用'\0'結束  
  catinfo.szDescription[len]   =   '\0';  
   
  hr   =   pcr->RegisterCategories(1,&catinfo);  
  pcr->Release();  
   
  return   hr;  
  }  
   
  HRESULT   RegisterCLSIDInCategory(REFCLSID   clsid,   CATID   catid)  
  {  
  //   注冊你的組件分組信息  
  ICatRegister*   pcr   =   NULL   ;  
  HRESULT   hr   =   S_OK   ;  
  hr   =   CoCreateInstance(CLSID_StdComponentCategoriesMgr,  
  NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&pcr);  
  if   (SUCCEEDED(hr))  
  {  
  //   注冊已實現的類到分組  
  CATID   rgcatid[1]   ;  
  rgcatid[0]   =   catid;  
  hr   =   pcr->RegisterClassImplCategories(clsid,1,rgcatid);  
  }  
   
  if   (pcr   !=   NULL)  
  pcr->Release();  
   
  return   hr;  
  }  
   
  HRESULT   UnRegisterCLSIDInCategory(REFCLSID   clsid,CATID   catid)  
  {  
  ICatRegister*   pcr   =   NULL   ;  
  HRESULT   hr   =   S_OK   ;  
   
  hr   =   CoCreateInstance(CLSID_StdComponentCategoriesMgr,  
  NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(void**)&pcr);  
  if   (SUCCEEDED(hr))  
  {  
  //   從分組卸載組件  
  CATID   rgcatid[1]   ;  
  rgcatid[0]   =   catid;  
  hr   =   pcr->UnRegisterClassImplCategories(clsid,   1,   rgcatid);  
  }  
   
  if   (pcr   !=   NULL)  
  pcr->Release();  
   
  return   hr;  
  }  
   
  //下面來兩個函數分別在DllRegisterServer和DllUnregisterServer中使用,參數均為控件的GUID。  
  HRESULT   RegisterTwo(REFCLSID   clsid)//   注意clsid就是控件的GUID  
  {  
  //   注冊控件是安全性初始化的  
  /////////////////////////////////////////////////  
  HRESULT   hr;  
  hr   =   CreateComponentCategory(CATID_SafeForInitializing,   L"Controls   safely   initializable   from   persistent   data!");  
  if   (FAILED(hr))  
  return   hr;  
   
  hr   =   RegisterCLSIDInCategory(clsid,   CATID_SafeForInitializing);  
  if   (FAILED(hr))  
  return   hr;  
  //   注冊控件是安全性腳本操作的  
   
  hr   =   CreateComponentCategory(CATID_SafeForScripting,   L"Controls   safely   scriptable!");  
  if   (FAILED(hr))  
  return   hr;  
   
  hr   =   RegisterCLSIDInCategory(clsid,   CATID_SafeForScripting);  
  if   (FAILED(hr))  
  return   hr;  
   
  return   S_OK;  
  }  
   
  HRESULT   UnRegisterTwo(REFCLSID   clsid)   //   注意clsid就是控件的GUID  
  {  
  //   刪除注冊表入口  
  HRESULT   hr;  
  hr   =   UnRegisterCLSIDInCategory(clsid,   CATID_SafeForInitializing);  
  if   (FAILED(hr))  
  return   hr;  
  //REFCLSID  
  hr   =   UnRegisterCLSIDInCategory(clsid,   CATID_SafeForScripting);  
  if   (FAILED(hr))  
  return   hr;  
   
  return   S_OK;  
  }  


from:http://topic.csdn.net/t/20030704/00/1988641.html
posted on 2007-07-04 10:01 我風 閱讀(1312) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


<2007年6月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用鏈接

留言簿(12)

隨筆分類

隨筆檔案

文章檔案

相冊

收藏夾

C++

MyFavorite

搜索

  •  

積分與排名

  • 積分 - 328998
  • 排名 - 75

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲无限av看| 翔田千里一区二区| 亚洲视频综合在线| 亚洲一区免费看| 影音先锋久久久| 欧美亚洲一区二区在线| 亚洲一区二区三区精品动漫| 亚洲一区三区视频在线观看| 久久久av毛片精品| 午夜精彩视频在线观看不卡| 久久久久久久综合日本| 一区二区三区免费网站| 亚洲三级视频| 国产精品萝li| 亚洲国产成人精品视频| 亚洲欧美日韩在线综合| 欧美在线关看| 午夜精彩国产免费不卡不顿大片| 久久超碰97中文字幕| 久久久久久九九九九| 亚洲国产精品电影在线观看| 国产精品试看| 欧美国产日韩一二三区| 欧美精品乱人伦久久久久久| 国产精品区一区二区三| 亚洲日韩第九十九页| 欧美黑人多人双交| 亚洲激情视频在线| 欧美国产精品人人做人人爱| 亚洲天堂成人| 欧美jizzhd精品欧美巨大免费| 中文日韩在线| 嫩草影视亚洲| 亚洲视频 欧洲视频| 久久久久久久性| 欧美激情在线播放| 久久久欧美一区二区| 亚洲女性喷水在线观看一区| 99热这里只有精品8| 欧美在线中文字幕| 亚洲一二三区在线| 国产欧美一区二区精品忘忧草| 亚洲电影下载| 最新精品在线| aⅴ色国产欧美| 99精品久久久| 欧美高清视频一二三区| 欧美v国产在线一区二区三区| 欧美插天视频在线播放| 免费成人性网站| 欧美精品黄色| 欧美噜噜久久久xxx| 麻豆91精品| 亚洲国产高清一区二区三区| 韩国一区二区三区在线观看| 中文久久精品| 久久天堂成人| 亚洲视频1区| 亚洲国产成人久久综合| 午夜亚洲一区| 亚洲国产一区视频| 国产精品嫩草影院一区二区| 久久精品综合一区| 欧美色精品天天在线观看视频| 一本色道久久88综合日韩精品| 午夜免费在线观看精品视频| 一区二区三区波多野结衣在线观看| 国产主播一区二区三区四区| 久久精品视频在线观看| 欧美国产综合| 亚洲欧美三级伦理| 亚洲人成高清| 久久激五月天综合精品| 欧美成年人视频| 91久久精品国产91性色tv| 99在线观看免费视频精品观看| 国产伦精品免费视频| 久久高清免费观看| 亚洲欧美日本日韩| 午夜精品偷拍| 国产综合精品| 国产精品高清网站| 国产精品毛片va一区二区三区| 在线观看久久av| 一区二区精品在线| 欧美日韩国产小视频| 在线天堂一区av电影| 久久夜精品va视频免费观看| 亚洲日本一区二区| 国产精品主播| 伊人久久综合97精品| 亚洲欧美一区二区三区久久 | 亚洲国产成人精品女人久久久 | 欧美日韩亚洲三区| 久久久999精品免费| 欧美女主播在线| 欧美中在线观看| 欧美一二三视频| 在线日韩成人| 欧美性大战久久久久久久蜜臀| 亚洲伦理在线免费看| 99视频热这里只有精品免费| 国产女主播在线一区二区| 久久久午夜精品| 欧美成人中文字幕| 中文日韩在线视频| 欧美在线三级| 亚洲精品美女在线| 香蕉久久夜色精品| 亚洲欧洲美洲综合色网| 午夜精品免费视频| 精品电影一区| 亚洲一级片在线观看| 亚洲高清视频一区二区| 亚洲天堂av在线免费观看| 亚洲国产你懂的| 亚洲一区二区三区成人在线视频精品 | 欧美国产一区二区| 久久精品国产96久久久香蕉| 欧美性事在线| 久久嫩草精品久久久精品一 | 亚洲第一狼人社区| 在线免费观看成人网| 在线精品国精品国产尤物884a| 午夜精品久久久久久久99樱桃 | 篠田优中文在线播放第一区| 亚洲国产精品热久久| 国产精品人人做人人爽人人添| 激情婷婷亚洲| 99这里只有久久精品视频| 午夜精品一区二区三区在线视| 亚洲国产一区二区三区a毛片 | 久久aⅴ国产欧美74aaa| 免费成人av| 国产精品亚发布| 久久国产精品久久久久久| 久久久综合视频| 亚洲一区二区三区成人在线视频精品 | 亚洲一区二区欧美日韩| 亚洲大胆av| 欧美体内she精视频| 亚洲美女在线观看| 蜜臀av性久久久久蜜臀aⅴ| 亚洲中午字幕| 欧美福利一区二区| 亚洲欧美电影院| 亚洲三级免费| 亚洲国产精品一区二区久| 国产精品丝袜91| 欧美激情综合色| 国模精品娜娜一二三区| 免费中文日韩| 影音先锋亚洲一区| 亚洲欧美在线aaa| 99re成人精品视频| 艳妇臀荡乳欲伦亚洲一区| 亚洲尤物视频在线| 久久久久欧美| 国产精品免费视频xxxx| 国产综合av| 亚洲高清一二三区| 国产精品专区h在线观看| 欧美日韩亚洲系列| 国产精品进线69影院| 国产亚洲精品美女| 亚洲香蕉成视频在线观看| 久久精品国内一区二区三区| 久久精品人人爽| 一本色道久久综合亚洲精品婷婷| 亚洲精品在线二区| 欧美亚洲综合在线| 久久香蕉精品| 久久婷婷色综合| 欧美日本一区二区高清播放视频| 欧美日韩国产系列| 伊人影院久久| 亚洲精品免费网站| 国产精品女主播| 日韩视频在线你懂得| 久久一二三区| 亚洲视频999| 欧美日韩国产一级| 精品电影在线观看| 欧美伊久线香蕉线新在线| 在线视频你懂得一区二区三区| 久久成人这里只有精品| 红桃视频成人| 免费一级欧美片在线播放| 男男成人高潮片免费网站| 在线看一区二区| 黄色小说综合网站| 美女精品自拍一二三四| avtt综合网| 欧美激情中文字幕一区二区 | 日韩一级大片| 久久精品亚洲| 亚洲与欧洲av电影| 亚洲精品裸体| 亚洲丁香婷深爱综合| 欧美日一区二区在线观看|