📄 s15_01.cpp
字号:
// S15_01.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
// 提供程序枚举所需要的变量和常量
#define NUMELEM(p1) (sizeof(p1) / sizeof(p1[0]))
#define COLUMN_ALIGNVAL 8
#define ROUND_UP( Size, Amount ) (((DWORD)(Size) + ((Amount) - 1)) & ~((Amount) - 1))
const ULONG DEF_SOURCES_CBMAXLEN = 64;
const ULONG MAX_NUM_PROVIDERS = 32;
ULONG g_cProvNames;
CHAR g_rgszProvName[MAX_NUM_PROVIDERS][DEF_SOURCES_CBMAXLEN];
WCHAR g_rgwszParseName[MAX_NUM_PROVIDERS][DEF_SOURCES_CBMAXLEN];
//枚举所有的数据源提供程序
HRESULT EnumerateProviders()
{
HRESULT hr = NULL;
ULONG i, ul, cRows = 0;
ISourcesRowset* pISourceRowset = NULL;
IRowset* pIRowset = NULL;
IAccessor* pIAccessor = NULL;
BYTE* pData = NULL; // 数据缓冲区
DWORD dwOffset; // 缓冲区偏移量
HACCESSOR hAccessor = NULL;
DBBINDING rgBind[4]; // 数据绑定缓冲区
HROW rghRows[256]; // 行句柄数组
HROW* pRows = &rghRows[0]; // 行句柄数组指针
// 描述获取数据元素的结构
struct COLUMNDATA {
DBSTATUS wStatus; // 列状态
DWORD dwLength; // 列长度
BYTE bData[1]; // 列数据
};
// 数据源行集接口返回的数据列(索引号)
enum enumSOURCES_COLUMNS {
eid_SOURCES_NAME = 1,
eid_SOURCES_PARSENAME,
eid_SOURCES_DESCRIPTION,
eid_SOURCES_TYPE,
eid_SOURCES_ISPARENT,
eid_SOURCES_CLSID
};
// 定义一个标识数据列信息的结构
// 这里获取三个列: 数据源名, 数据源解析名和数据源类型
static struct tagSOURCES
{
ULONG iOrdinal;
DBTYPE wType;
ULONG cbMaxLen;
} s_rgSources[] = {
eid_SOURCES_NAME, DBTYPE_STR, DEF_SOURCES_CBMAXLEN,
eid_SOURCES_PARSENAME, DBTYPE_WSTR, DEF_SOURCES_CBMAXLEN * sizeof(WCHAR),
eid_SOURCES_TYPE, DBTYPE_UI4, sizeof(ULONG),
eid_SOURCES_ISPARENT, DBTYPE_BOOL, sizeof(bool),
};
printf("Enumerate The Provides:\n");
printf("----------------------------------------------------\n");
memset(rghRows, 0, sizeof(rghRows));
// 初始化OLE DB根枚举器
if( FAILED(hr = CoCreateInstance(CLSID_OLEDB_ENUMERATOR, NULL,
CLSCTX_INPROC_SERVER, IID_ISourcesRowset, (LPVOID*)&pISourceRowset)) )
{
printf("Error(%ld): CoCreateInstance FAILED!!\n", hr);
goto EXIT;
}
// 获取行集对象
if( FAILED(hr = pISourceRowset->GetSourcesRowset(NULL, IID_IRowset, 0, NULL,
(IUnknown**)&pIRowset)) )
{
printf("Error(%ld): GetSourcesRowset FAILED!!\n", hr);
goto EXIT;
}
memset(rgBind, 0, sizeof(rgBind));
// 获取访问器对象
if( FAILED(hr = pIRowset->QueryInterface(IID_IAccessor, (LPVOID*)&pIAccessor)) )
{
printf("Error(%ld): QueryInterface of IID_IAccessor from pIRowset failed!!\n", hr );
goto EXIT;
}
// 初始化列绑定信息(按照前面的s_rgSources数组)
dwOffset = 0;
for( i=0; i<NUMELEM(s_rgSources); i++ )
{
rgBind[i].dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
// 绑定值(value), 长度(length)和状态(status)信息
rgBind[i].eParamIO = DBPARAMIO_NOTPARAM;// 不是参数
rgBind[i].iOrdinal = s_rgSources[i].iOrdinal;// 缓冲区起始位置
rgBind[i].wType = s_rgSources[i].wType;// 列类型
rgBind[i].obValue = dwOffset + offsetof(COLUMNDATA, bData);// 值的偏移位置
rgBind[i].obLength = dwOffset + offsetof(COLUMNDATA, dwLength);// 长度的偏移位置
rgBind[i].obStatus = dwOffset + offsetof(COLUMNDATA, wStatus);// 状态的偏移位置
rgBind[i].cbMaxLen = s_rgSources[i].cbMaxLen;// 列的最大长度
rgBind[i].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
// 指定缓冲区的分配者, 这里是枚举器客户(本程序)
dwOffset += rgBind[i].cbMaxLen + offsetof(COLUMNDATA, bData);// 下一列的偏移位置
dwOffset = ROUND_UP( dwOffset, COLUMN_ALIGNVAL );
}
// 创建访问器对象
if( FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, NUMELEM(s_rgSources),
rgBind, dwOffset, &hAccessor, NULL)) )
{
printf("Error(%ld): Accessor Creation failed!!\n", hr);
goto EXIT;
}
// 获取数据源提供程序信息
if( SUCCEEDED(hr = pIRowset->GetNextRows(NULL, 0, MAX_NUM_PROVIDERS, &cRows, &pRows)) )
{
// 为获取的行数据分配存储块
pData = new BYTE[dwOffset];
if( pData == NULL )
{
printf("Error(%ld): Unable to allocate memory for buffer!!\n", E_OUTOFMEMORY);
goto EXIT;
}
// 在行集数据中循环, 收集数据提供程序信息, 并释放枚举器对象.
for(ul=0; (ul<cRows) && (ul<MAX_NUM_PROVIDERS); ul++)
{
memset(pData, 0, dwOffset);
if( SUCCEEDED(hr = pIRowset->GetData(rghRows[ul], hAccessor, pData)) )
{
if( *((ULONG*)(pData + rgBind[2].obValue)) == DBSOURCETYPE_DATASOURCE )
//if( *((ULONG*)(pData + rgBind[2].obValue)) == DBSOURCETYPE_ENUMERATOR &&
// *((ULONG*)(pData + rgBind[3].obValue)) == VARIANT_FALSE )
{
// 存储数据源提供程序显示名称
strcpy(g_rgszProvName[g_cProvNames], (CHAR*)(pData + rgBind[0].obValue));
// 存储解析名称
wcscpy(g_rgwszParseName[g_cProvNames], (WCHAR*)(pData + rgBind[1].obValue));
// 将解析名称字符串从Unicode转换成ANSI字符集.
//CHAR string[256];
//WideCharToMultiByte(CP_ACP,
// 0,
// (WCHAR*)(pData+rgBind[1].obValue),
// wcslen((WCHAR*)(pData + rgBind[1].obValue)),
// string,
// 256,
// NULL,
// FALSE);
//string[wcslen((WCHAR*)(pData + rgBind[1].obValue))] = '\0';
//cout<<"Provider #"<<i
// <<"\n\tName: "<<(CHAR*)(pData + rgBind[0].obValue)
// <<"\n\tParse Name: "<<string<<endl;
printf("Provider #%d\n", g_cProvNames);
printf("\tName: %s\n", g_rgszProvName[g_cProvNames]);
printf("\tParse Name: %S\n", g_rgwszParseName[g_cProvNames]);
g_cProvNames++;
}
}
}
}
else
{
printf("Error(%d): GetNextRows failed to retrieve Providers!!\n", hr);
goto EXIT;
}
EXIT:
if( pData ) delete[] pData;
if( pIAccessor ) {
if( hAccessor ) {
if( FAILED(hr = pIAccessor->ReleaseAccessor(hAccessor, NULL)) )
printf("Error(%ld): Release Accessor failed!!\n", hr );
}
pIAccessor->Release();
}
if( pIRowset ) {
if( cRows ) {
if( FAILED(hr = pIRowset->ReleaseRows(cRows, rghRows, NULL, NULL, NULL)) )
printf("Error(%ld): Release of Row handles failed!!\n", hr);
}
pIRowset->Release();
}
if( pISourceRowset )
pISourceRowset->Release();
return hr;
}
int _tmain(int argc, _TCHAR* argv[])
{
//初始化COM库
CoInitialize(NULL);
EnumerateProviders();
//释放COM库
CoUninitialize();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -