COM---注册表

//
//   Category.cpp -
//   组件类演示程序
//

// 不编译为 UNICODE.

#include <stdlib.h>
#include <iostream.h>
#include <assert.h>

#include <comcat.h>

/////////////////////////////////////////////////
//
// 函数声明
//

// 工作函数

// 列出已注册的组件类别
BOOL ListCategories() ;

// 注册样本组件类别
BOOL RegisterCategory() ;

// 卸载样本组件类别
void UnregisterCategory() ;

// 将组件添加到样本组件类别中
void AddComponent() ;

// 从样本组件类别中移除组件
void RemoveComponent() ;

// 列出样本类别成员的所有组件
void ListCategoryMembers() ;

// 帮助函数

// 打印HRESULT所代表的COM/OLE错误信息
void ErrorMessage(const char* str, HRESULT hr) ;

// 从注册表获取和显示一个CLSID的友好名称。
// Get friendly name for a CLSID from the Registry and display.
void OutputFriendlyName(const CLSID& clsid) ;

/////////////////////////////////////////////////
//
// 全局数据和常量
//

// 全局接口指针
ICatInformation*  g_pICatInformation = NULL ;
ICatRegister*     g_pICatRegister = NULL ;

// 数组类别ID
// {f2484d60-e8d0-11cf-a6bb-0080c7b2d682}
static GUID CATID_SampleCategories[1] = 
    {0xf2484d60, 0xe8d0, 0x11cf,
    {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

// 类别信息结构,用于注册类别
CATEGORYINFO g_SampleCategoryInfo =
{    
    {0xf2484d60, 0xe8d0, 0x11cf,
    {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}},  // CATID catid 
    LOCALE_SYSTEM_DEFAULT,                             // LCID lcid 
    L"This is the sample category"      // OLECHAR szDescription[128] 
} ;

// 将组件类添加到上面定义的样本类别
// {0c092c20-882c-11cf-a6bb-0080c7b2d682}
extern "C" const CLSID CLSID_Component1 =
    {0x0c092c20, 0x882c, 0x11cf,
    {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

/////////////////////////////////////////////////
//
// main 
//
int main()
{
    // 初始化 COM 库
    // OleInitialize 会调用 CoInitialize
    OleInitialize(NULL) ;

    // 创建标准COM类管理器
    // 取代上一篇中的CallCreateInstance
    // CLSID_StdComponentCategoriesMgr:待创建组件的CLSID
    // NULL:指向IUnknown接口的指针,用于聚合组件,此处不需要聚合组件
    // CLSCTX_ALL:运行可执行代码的上下文
    // CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLE
    //            | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
    // = 客户希望在同一进程中运行组件 | 客户希望创建进程中处理器
    // | 客户希望创建一个在同一机器上的另外一个进程中运行的组件
    // | 客户希望创建一个在远程机器上运行的组件
    // IID_ICatInformation:创建的Com对象的接口标识符
    // (void**)&g_pICatInformation):用来接收指向Com对象接口地址的指针变量
    HRESULT hr = ::CoCreateInstance(CLSID_StdComponentCategoriesMgr,
                                    NULL, 
                                    CLSCTX_ALL,
                                    IID_ICatInformation, 
                                    (void**)&g_pICatInformation) ;
    if (FAILED(hr))
    {
        ErrorMessage("main: Could not create component category manager.", hr) ;
        goto Uninitialize ;
    }

    // 列出类别
    if (!ListCategories())
    {
        goto Release ;
    }

    // 得到类别的注册接口
    hr = g_pICatInformation->QueryInterface(IID_ICatRegister,
                                            (void**)&g_pICatRegister) ;
    if (FAILED(hr))
    {
        ErrorMessage("Attempt to query for ICatRegister failed.", hr) ;
        goto Release ;
    }

    //
    // 注册样本组件类别
    //
    cout << "--------Register---------------" << endl ;
    if (!RegisterCategory())
    {
        goto Release ;
    }

    // 再次列出类别,以显示新注册的类别
    ListCategories() ;

    // 添加组件到样本类别
    cout << "--------Add Component----------" << endl ;
    AddComponent() ;

    // 列出样本类别的所有组件
    cout << "--------List Category----------" << endl ;
    ListCategoryMembers();  

    // 从样本类别中移除组件
    cout << "--------Remove Component-------" << endl ;
    RemoveComponent();

    // 列出样本类别的所有组件
    // 应该为空
    cout << "--------List Category----------" << endl ;
    ListCategoryMembers() ; 

    // 注销样品组件类别
    cout << "--------Unregister-------------" << endl ;
    UnregisterCategory() ;

    // 列出要显示组件类别的类别们
    // 已经被移除
    ListCategories() ;

Release:    
    // 释放接口指针
    if (g_pICatInformation != NULL)
    {
        g_pICatInformation->Release() ;
    }
    if (g_pICatRegister != NULL)
    {
        g_pICatRegister->Release() ;
    }

Uninitialize:
    // 注销 COM 库
    OleUninitialize() ;

    return 0 ;
}

/////////////////////////////////////////////////
//
// 工作函数
//

//
// 列出已注册的组件类别
//
BOOL ListCategories()
{
    BOOL bReturn = TRUE ;

    // 得到类别的 enumerator 
    IEnumCATEGORYINFO* pIEnumCATEGORYINFO = NULL ; 
    HRESULT hr = g_pICatInformation->EnumCategories(::GetUserDefaultLCID(),
                                                    &pIEnumCATEGORYINFO) ;
    if (FAILED(hr))
    {
        ErrorMessage("ListCategories: ICatInformation::EnumCategories failed.", hr) ;
        return FALSE ;
    }

    // 循环准备
    char szDescription[128] ;
    CATEGORYINFO CategoryInfo ;

    // 枚举类别 
    while ((hr = pIEnumCATEGORYINFO->Next(1, &CategoryInfo, NULL)) == S_OK)
    {
            // 将 wchar_t 转换为 char.
            ::wcstombs(szDescription, CategoryInfo.szDescription,
                       sizeof(szDescription)) ;

            // 输出描述信息
            cout << szDescription << "\r\n" ;
    } 

    if (FAILED(hr))
    {
        ErrorMessage("ListCategories: IEnumCATEGORYINFO::Next failed.", hr) ;
        bReturn = FALSE ;
    }


    // 释放接口
    if (pIEnumCATEGORYINFO != NULL)
    {
        pIEnumCATEGORYINFO->Release() ;
    }

    return bReturn ;
}

//
// 注册组件类别
//
BOOL RegisterCategory()
{
    HRESULT hr = g_pICatRegister->RegisterCategories(1, &g_SampleCategoryInfo) ;
    if (FAILED(hr))
    {
        ErrorMessage("RegisterCategory: Registering the component category failed.",
                     hr) ;
        return FALSE ;
    }
    return TRUE ;
}

//
// 销毁组件类别
//
void UnregisterCategory()
{
    HRESULT hr = g_pICatRegister->UnRegisterCategories(1, CATID_SampleCategories) ; 
    if (FAILED(hr))
    {
        ErrorMessage("UnregisterCategory: Unregistering component category failed.",
                     hr) ;
    }
}

//
// 为组件类别添加组件
//
void AddComponent()
{   
    HRESULT hr = g_pICatRegister->RegisterClassImplCategories(CLSID_Component1,
                                                              1, 
                                                              CATID_SampleCategories) ; 
    if (FAILED(hr))
    {
        ErrorMessage("AddComponent: Adding component to category failed.", hr) ;
    }
}

//
// 从组件类别中移除组件
//
void RemoveComponent()
{   
    HRESULT hr = 
        g_pICatRegister->UnRegisterClassImplCategories(CLSID_Component1,    
                                                       1, 
                                                       CATID_SampleCategories) ; 
    if (FAILED(hr))
    {
         ErrorMessage("RemoveComponent: Removing component to category failed.",
                      hr) ;
    }
}

//
// 列出属于特定类别成员的所有组件
//
void ListCategoryMembers()
{
    // 获得类别枚举器
    IEnumCLSID* pIEnumCLSID = NULL; 
    HRESULT hr 
        = g_pICatInformation->EnumClassesOfCategories(1,
                                                      CATID_SampleCategories,
                                                      0,
                                                      NULL,
                                                      &pIEnumCLSID) ;
    if (FAILED(hr))
    {
        ErrorMessage("ListCategoryMembers: EnumClassesOfCategories  failed.", hr) ;
    }

    // 循环准备
    char szDescription[128] ;
    CLSID clsid ;

    // 枚举类别
    while (TRUE)    
    {

        // 获得下一个类别
        hr = pIEnumCLSID->Next( 1, &clsid, NULL) ;
        if (hr != S_OK)
        {
            if (FAILED(hr))
            {
                ErrorMessage("ListCategoryMembers: IEnumCLSID::Next failed.",
                             hr) ;
            }
            break ;
        }

        // 打印友好名称
        OutputFriendlyName(clsid) ;
    } 

    // 释放接口
    if (pIEnumCLSID != NULL)
    {
        pIEnumCLSID->Release() ;
    }
}


/////////////////////////////////////////////////
//
// Helper 函数
//

// 输出HRESULT所代表的COM/OLE错误信息
void ErrorMessage(const char* str, HRESULT hr)

{
    void* pMsgBuf ;

    //将HRESULT所代表错误信息转换为字符串
    //第1个参数:标志位,决定如何说明第2个参数
    //FORMAT_MESSAGE_ALLOCATE_BUFFER:分配一个足够大的缓冲区保存格式化信息
    //FORMAT_MESSAGE_FROM_SYSTEM:为请求的信息搜索系统的消息资源表
    //NULL:根据第1个参数而定
    //hr:请求消息的标识符
    //第4个参数:请求的消息的语言标识符
    //(LPTSTR) &pMsgBuf:接收错误信息描述的缓冲区指针
    //0:输出缓冲区的大小
    //NULL:保存格式化信息中的插入值的一个数组
    ::FormatMessage( 
         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,  
         NULL,
         hr,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 默认语言
         (LPTSTR) &pMsgBuf,
         0,
         NULL 
    ) ;

    // 显示字符串
    cout << str << "\r\n" ;
    cout << "Error (" << hex << hr << "):  " 
         << (char*)pMsgBuf << endl ;

    // 释放缓冲区
    LocalFree( pMsgBuf ) ;

}

//
// 从注册表获取并显示一个CLSID的友好名称
//
void OutputFriendlyName(const CLSID& clsid)
{
    // 将 clsid 转换为一个字符串
    wchar_t wszCLSID[80] ;
    int r = ::StringFromGUID2(clsid, wszCLSID, 80) ;
    assert(r != 0) ;

    // 转换为单字节字符.
    char szCLSID[40] ;
    wcstombs(szCLSID, wszCLSID, 40) ;

    // 打开注册表项
    HKEY key = NULL ;
    long l = ::RegOpenKeyEx(HKEY_CLASSES_ROOT,
                            "CLSID",
                            0,
                            KEY_ALL_ACCESS,
                            &key) ;
    assert(l == ERROR_SUCCESS) ;

    // 得到友好名称
    char szFriendly[256] ;
    long size = sizeof(szFriendly) ;
    l = ::RegQueryValue(key,
                        szCLSID,
                        szFriendly,
                        &size) ;
    assert(l == ERROR_SUCCESS) ;

    // 输出友好名称
    cout << szFriendly << endl ;

    // 清空
    ::RegCloseKey(key) ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值