⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s15_01.cpp

📁 本书分为五个部分
💻 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 + -