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

📄 s15_03.cpp

📁 本书分为五个部分
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// S15_03.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "HandleResult.h"

BOOL	g_bPrompt;	// 是否提示用户选择数据源
#define	MAX_NAME_LEN		255		// 表名字符串的最大长度
#define MAX_COL_SIZE        5000	// 列的最大字节数
#define MAX_ROWS			1		// 每次取的最大行数
#define MAX_DISPLAY_SIZE	20		// 
#define MIN_DISPLAY_SIZE	3		// 

// OLE DB ODBC提供程序的CLSID
extern const MSDASQLDECLSPEC GUID CLSID_MSDASQL = {0xC8B522CBL,0x5CF3,0x11CE,{0xAD,0xE5,0x00,0xAA,0x00,0x44,0x77,0x3D}};

// 创建数据源对象.
HRESULT CreateDataSource(IUnknown **ppUnkDataSource);

// 初始化数据源对象.
HRESULT DoInitialization(IUnknown *pIUnknown);

// 初始化单个属性结构DBPROP.
void AddProperty(DBPROP *pProp, DBPROPID dwPropertyID, VARIANT vValue, 
				 DBPROPOPTIONS dwOptions = DBPROPOPTIONS_REQUIRED,
				 DBID colid = DB_NULLID);
void AddProperty(DBPROP* pProp, DBPROPID dwPropertyID, VARTYPE vtType = VT_BOOL, 
				 LONG lValue = VARIANT_TRUE, DBPROPOPTIONS dwOptions =    DBPROPOPTIONS_OPTIONAL);

// 获取指定属性的BOOL值.
HRESULT GetProperty(IUnknown *pIUnknown, REFIID riid, DBPROPID dwPropertyID,
					REFGUID guidPropertySet, BOOL *pbValue );

// 提示用户输入字符串.
BOOL GetInputFromUser(LPWSTR    pwszInput, LPCWSTR   pwszFmt, ... );

// 创建一个OLE DB会话对象(从指定的数据源对象).
HRESULT CreateSession( IUnknown *pUnkDataSource, IUnknown **ppUnkSession);
// 由会话对象创建一个行集对象.
HRESULT CreateRowset(IUnknown  *pUnkSession, IUnknown **ppUnkRowset);
// 设置行集属性.
void AddRowsetProperties(DBPROPSET *pPropSet, ULONG cProperties, DBPROP *rgProperties);
// 创建架构行集对象.
HRESULT CreateSchemaRowset(GUID  guidSchema, IUnknown  *pUnkSession,
						   ULONG  cchBuffer,  LPWSTR  pwszBuffer);
// 显示行集数据.
HRESULT DisplayRowset(IUnknown* pUnkRowset, LPCWSTR pwszColToReturn, 
					  ULONG cchBuffer, LPWSTR pwszBuffer);
// 显示表的列名.
HRESULT DisplayColumnNames(IUnknown* pUnkRowset, ULONG* rgDispSize);
HRESULT FindColumn(IUnknown * pUnkRowset, LPCWSTR pwszName, LONG* plIndex);
// 显示行集行数据.
HRESULT DisplayRow(ULONG iRow, ULONG cBindings, DBBINDING* rgBindings, 
				   void* pData, ULONG * rgDispSize);
// 更新显示尺寸.
HRESULT UpdateDisplaySize(ULONG cBindings, DBBINDING* rgBindings, 
						  void* pData, ULONG* rgDispSize);
// 设置绑定数据结构.
HRESULT SetupBindings(IUnknown *pUnkRowset, ULONG *pcBindings,
					  DBBINDING **prgBindings, ULONG *pcbRowSize );
// 释放绑定数据结构.
void FreeBindings(ULONG cBindings, DBBINDING* rgBindings);

// 试图从会话对象创建一个命令对话.
HRESULT CreateCommand(IUnknown *pUnkSession, IUnknown **ppUnkCommand);
// 执行命令, 并创建相应的行集对象.
HRESULT ExecuteCommand(IUnknown* pUnkCommand, WCHAR* pwszCommandText,
					   ULONG cPropSets, DBPROPSET* rgPropSets, IUnknown** ppUnkRowset);


int _tmain(int argc, _TCHAR* argv[])
{
	HRESULT			hr = NULL;
	IUnknown*		pUnkDataSource	= NULL;
	IUnknown*		pUnkSession		= NULL;
	IUnknown*		pUnkRowset		= NULL;

	//初始化COM库.
	CoInitialize(NULL);

	g_bPrompt = FALSE;
	
	// 创建并初始化数据源对象.
	XCHECK_HR(hr = CreateDataSource(&pUnkDataSource));

	// 创建会话对象.
	XCHECK_HR(hr = CreateSession(pUnkDataSource, &pUnkSession));

	// 创建行集对象.
	XCHECK_HR(hr = CreateRowset(pUnkSession, &pUnkRowset));

	// 显示行集对象数据.
	CHECK_HR(hr = DisplayRowset(pUnkRowset, NULL, 0, NULL));

CLEANUP:
	if( pUnkDataSource )	pUnkDataSource->Release();
	if( pUnkSession )		pUnkSession->Release();
	if( pUnkRowset )		pUnkRowset->Release();

	//清除COM库.
	CoUninitialize();
	return 0;
}

HRESULT CreateDataSource(IUnknown ** ppUnkDataSource)
{
	HRESULT                hr;
	IDataInitialize *      pIDataInitialize         = NULL;
	IDBPromptInitialize *  pIDBPromptInitialize     = NULL;
	IDBInitialize *        pIDBInitialize           = NULL;
	CLSID                  clsid                    = CLSID_MSDASQL;

	//使用数据连接(Data Links)用户界面, 提示用户选择一个连接的提供程序.
	if( g_bPrompt )
	{
		//创建数据连接组件对象, 并获取它的IDBPromptInitialize接口.
		XCHECK_HR(hr = CoCreateInstance(
			CLSID_DataLinks,                   // clsid--Data Links UI
			NULL,                              // pUnkOuter
			CLSCTX_INPROC_SERVER,              // dwClsContext
			IID_IDBPromptInitialize,           // riid
			(void**)&pIDBPromptInitialize));   // ppvObj

		//提示用户选择一个要创建的数据提供程序.
		XCHECK_HR(hr = pIDBPromptInitialize->PromptDataSource(
			NULL,                             // pUnkOuter
			GetDesktopWindow(),               // hWndParent
			DBPROMPTOPTIONS_PROPERTYSHEET,    // dwPromptOptions
			0,                                // cSourceTypeFilter
			NULL,                             // rgSourceTypeFilter
			NULL,                             // pwszszzProviderFilter
			IID_IDBInitialize,                // riid
			(IUnknown**)&pIDBInitialize));    // ppDataSource

		// 已经从数据连接对象获取了数据提供程序数据源对象.
		// 这个对象已经包含有初始化属性集, 于是我们可以直接对其初始化.
		XCHECK_HR(hr = pIDBInitialize->Initialize());
	}
	//不使用数据连接组件, 而直接创建OLE DB ODBC提供程序数据源对象.
	else
	{
		// 创建OLE DB ODBC提供程序数据源对象.
		XCHECK_HR(hr = CoCreateInstance(
			CLSID_MSDASQL,                   // clsid--provider
			NULL,                            // pUnkOuter
			CLSCTX_INPROC_SERVER,            // dwClsContext
			IID_IDBInitialize,               // riid
			(LPVOID*)&pIDBInitialize));   // ppDataSource

		// 初始化数据源对象.
		CHECK_HR(hr = DoInitialization(pIDBInitialize));
	}

CLEANUP:
	*ppUnkDataSource = pIDBInitialize;
	if( pIDataInitialize )
		pIDataInitialize->Release();
	if( pIDBPromptInitialize )
		pIDBPromptInitialize->Release();

	return hr;
}

HRESULT DoInitialization(IUnknown* pIUnknown)
{
	HRESULT              hr;
	IDBInitialize *      pIDBInitialize      = NULL;
	IDBProperties *      pIDBProperties      = NULL;
	HWND                 hWnd                = GetDesktopWindow();
	//const ULONG          cProperties         = 2;
	const ULONG          cProperties         = 4;
	DBPROP               rgProperties[cProperties];
	DBPROPSET            rgPropSets[1];

	VARIANT vValue;
	// 设置初始化属性. 
	// 提示用户提供所需的初始化属性.
	//vValue.vt = VT_I2; vValue.lVal = DBPROMPT_COMPLETE;
	//AddProperty(&rgProperties[0], DBPROP_INIT_PROMPT, vValue );
	//vValue.vt = VT_I4; vValue.lVal = (LONG)hWnd;
	//AddProperty(&rgProperties[1], DBPROP_INIT_HWND, vValue);

	// 直接指定初始化属性, 而不提示用户.
	// 指定不提示用户选择初始化属性.
	vValue.vt = VT_I2; vValue.lVal = DBPROMPT_NOPROMPT;
	AddProperty(&rgProperties[0], DBPROP_INIT_PROMPT, vValue);
	// 提定用户名.	
	vValue.vt = VT_BSTR; vValue.bstrVal=SysAllocString((LPOLESTR)L"");
	AddProperty(&rgProperties[1], DBPROP_AUTH_USERID, vValue);
	// 指定用户口令.
	vValue.vt = VT_BSTR; vValue.bstrVal=SysAllocString((LPOLESTR)L"");
	AddProperty(&rgProperties[2], DBPROP_AUTH_PASSWORD, vValue);
	// 指定数据源名称.
	vValue.vt = VT_BSTR; vValue.bstrVal=SysAllocString((LPOLESTR)L"ENorthwind");
	AddProperty(&rgProperties[3], DBPROP_INIT_DATASOURCE, vValue); 

	rgPropSets[0].rgProperties      = rgProperties;
	rgPropSets[0].cProperties       = cProperties;
	rgPropSets[0].guidPropertySet   = DBPROPSET_DBINIT;

	// 获取设置属性的接口: IDBProperties.
	XCHECK_HR(hr = pIUnknown->QueryInterface(IID_IDBProperties,
		(void**)&pIDBProperties));
	XCHECK_HR(hr = pIUnknown->QueryInterface(IID_IDBInitialize,
		(void**)&pIDBInitialize));

	// 设置初始化属性.
	XCHECK_HR(hr = pIDBProperties->SetProperties(1, rgPropSets));

	// 初始化数据源对象..
	XCHECK_HR(hr = pIDBInitialize->Initialize());

CLEANUP:
	if( pIDBProperties )
		pIDBProperties->Release();
	if( pIDBInitialize )
		pIDBInitialize->Release();
	return hr;
}

/////////////////////////////////////////////////////////////////
// 函数: AddProperty
//
// 这个函数初始化属性结构(DBPROP)pProp.
//
////////////////////////////////////////////////////////////////
void AddProperty(DBPROP *           pProp,
				 DBPROPID           dwPropertyID,
				 VARIANT			vValue,
				 DBPROPOPTIONS      dwOptions,
				 DBID				colid)
{
	pProp->dwPropertyID    = dwPropertyID;
	pProp->dwOptions       = dwOptions;
	pProp->dwStatus        = DBPROPSTATUS_OK;
	pProp->colid           = DB_NULLID;
	pProp->vValue		   = vValue;
}
void AddProperty(DBPROP *           pProp,
				 DBPROPID           dwPropertyID,
				 VARTYPE            vtType,
				 LONG               lValue,
				 DBPROPOPTIONS      dwOptions )
{
	// Set up the property structure.
	pProp->dwPropertyID    = dwPropertyID;
	pProp->dwOptions       = dwOptions;
	pProp->dwStatus        = DBPROPSTATUS_OK;
	pProp->colid           = DB_NULLID;
	V_VT(&pProp->vValue)   = vtType;

	// Since VARIANT data is a union, we can place the value in any
	// member (except for VT_DECIMAL, which is a union with the whole
	// VARIANT structure -- but we know we're not passing VT_DECIMAL).
	V_I4(&pProp->vValue)   = lValue;
}

/////////////////////////////////////////////////////////////////
// 函数: GetProperty
//
// 这个函数获取指定属性的BOOL值, 并将结果放在*pbValue中.
//
/////////////////////////////////////////////////////////////////
HRESULT GetProperty(IUnknown *             pIUnknown,
					REFIID                 riid,
					DBPROPID               dwPropertyID,
					REFGUID                guidPropertySet,
					BOOL *                 pbValue )
{
	HRESULT                hr;
	DBPROPID               rgPropertyIDs[1];
	DBPROPIDSET            rgPropertyIDSets[1];

	ULONG                  cPropSets        = 0;
	DBPROPSET *            rgPropSets       = NULL;

	IDBProperties *        pIDBProperties   = NULL;
	ISessionProperties *   pISesProps       = NULL;
	ICommandProperties *   pICmdProps       = NULL;
	IRowsetInfo *          pIRowsetInfo     = NULL;

	// 初始化输出值.
	*pbValue = FALSE;

	// 设置属性ID数组.
	rgPropertyIDs[0] = dwPropertyID;

	// 设置属性ID集.
	rgPropertyIDSets[0].rgPropertyIDs     = rgPropertyIDs;
	rgPropertyIDSets[0].cPropertyIDs      = 1;
	rgPropertyIDSets[0].guidPropertySet   = guidPropertySet;

	// 从提供程序获取指定属性的属性值.
	if( riid == IID_IDBProperties )
	{
		XCHECK_HR(hr = pIUnknown->QueryInterface(IID_IDBProperties,
			(void**)&pIDBProperties));
		CHECK_HR(hr = pIDBProperties->GetProperties(
			1,                                 // cPropertyIDSets
			rgPropertyIDSets,                  // rgPropertyIDSets
			&cPropSets,                        // pcPropSets
			&rgPropSets                        // prgPropSets
			));
	}
	else if( riid == IID_ISessionProperties )
	{
		XCHECK_HR(hr = pIUnknown->QueryInterface(IID_ISessionProperties,
			(void**)&pISesProps));
		CHECK_HR(hr = pISesProps->GetProperties(
			1,                                 // cPropertyIDSets
			rgPropertyIDSets,                  // rgPropertyIDSets
			&cPropSets,                        // pcPropSets
			&rgPropSets                        // prgPropSets
			));
	}
	else if( riid == IID_ICommandProperties )
	{
		XCHECK_HR(hr = pIUnknown->QueryInterface(IID_ICommandProperties,
			(void**)&pICmdProps));
		CHECK_HR(hr = pICmdProps->GetProperties(
			1,                                 // cPropertyIDSets
			rgPropertyIDSets,                  // rgPropertyIDSets
			&cPropSets,                        // pcPropSets
			&rgPropSets                        // prgPropSets
			));
	}
	else
	{
		XCHECK_HR(hr = pIUnknown->QueryInterface(IID_IRowsetInfo,
			(void**)&pIRowsetInfo));
		CHECK_HR(hr = pIRowsetInfo->GetProperties(
			1,                                 // cPropertyIDSets
			rgPropertyIDSets,                  // rgPropertyIDSets
			&cPropSets,                        // pcPropSets
			&rgPropSets                        // prgPropSets
			));
	}

	// 将属性值返回给调用者(如果是一个VT_BOOL类型值).
	if( V_VT(&rgPropSets[0].rgProperties[0].vValue) == VT_BOOL )
		*pbValue = V_BOOL(&rgPropSets[0].rgProperties[0].vValue);

CLEANUP:
	if( rgPropSets )
	{
		CoTaskMemFree(rgPropSets[0].rgProperties);
		CoTaskMemFree(rgPropSets);
	}
	if( pIDBProperties )
		pIDBProperties->Release();
	if( pISesProps )
		pISesProps->Release();
	if( pICmdProps )
		pICmdProps->Release();
	if( pIRowsetInfo )
		pIRowsetInfo->Release();
	return hr;
}


/////////////////////////////////////////////////////////////////
// 函数: CreateSession

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -