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

📄 ctable.cpp

📁 用测试OLE DB提供者的一个程序。能够测试出OEL DB提供者到底实现了哪些接口?很灵的。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			break;

		default:	//DBSTATUS_S_OK
		{
			//Set STATUS
			BINDING_STATUS(*pBinding, pData) = DBSTATUS_S_OK;
			
			//We have a problem if the user has entered a value (string) longer than
			//the buffer we have allocated.  If the length is greater than
			//cbMaxLen we need to truncate it and inform the user...
			ULONG cbBytes = strlen(pszValue);
			switch(pBinding->wType)
			{
				case DBTYPE_STR:
					cbBytes = (cbBytes + 1)*sizeof(CHAR);
					break;
				
				case DBTYPE_WSTR:
				case DBTYPE_BSTR:
					cbBytes = (cbBytes + 1)*sizeof(WCHAR);
					break;

				case DBTYPE_BYTES:
					cbBytes = cbBytes >> 1;
					break;
			};

			if(cbBytes > pBinding->cbMaxLen && 
				pBinding->wType != DBTYPE_VARIANT)
			{
				//Truncate the Value 
				if(pBinding->wType == DBTYPE_WSTR || pBinding->wType == DBTYPE_BSTR)
					pszValue[pBinding->cbMaxLen/2-1] = EOL;
				else if (pBinding->wType == DBTYPE_STR)
					pszValue[pBinding->cbMaxLen-1] = EOL;
				else if (pBinding->wType == DBTYPE_BYTES)
					pszValue[pBinding->cbMaxLen<<1] = EOL;

				//Inform user of Truncation...
				wMessageBox(
					m_pCMDIChild->m_hWnd, MB_TASKMODAL | MB_ICONHAND | MB_OK | MB_DEFBUTTON1, 
					wsz_ERROR, 
					L"You have entered a value for column %d of %d bytes\n\n"
					L"The cbMaxSize of this column is %d.\n"
					L"Your value will be truncated to\n"
					L"(%S)",
					pBinding->iOrdinal, 
					cbBytes, 
					pBinding->cbMaxLen, 
					pszValue 
					);			
			}

			//Set LENGTH and VALUE
			//We may have bound this column in the accessor differently...
			switch(pBinding->wType)
			{
				case DBTYPE_WSTR:
					ConvertToWCHAR(pszValue, wszBuffer, MAX_COL_SIZE);
					BINDING_LENGTH(*pBinding, pData) = cbBytes-sizeof(WCHAR);
					wcscpy((WCHAR*)&BINDING_VALUE(*pBinding, pData), wszBuffer);
					break;

				case DBTYPE_STR:
					BINDING_LENGTH(*pBinding, pData) = cbBytes-sizeof(CHAR);
					strcpy((CHAR*)&BINDING_VALUE(*pBinding, pData), pszValue);
					break;
					
				case DBTYPE_VARIANT:						
					ConvertToWCHAR(pszValue, wszBuffer, MAX_COL_SIZE);
					V_VT(&vVariant) = VT_BSTR;
					V_BSTR(&vVariant) = SysAllocString(wszBuffer);
					BINDING_LENGTH(*pBinding, pData) = sizeof(VARIANT);
					memcpy(&BINDING_VALUE(*pBinding, pData), &vVariant, sizeof(VARIANT));
					break;

				case DBTYPE_BYTES:
					XTESTC(m_pCMDIChild->m_hWnd, hr = StringToBYTES(pszValue, (BYTE*)&BINDING_VALUE(*pBinding, pData), cbBytes, &BINDING_LENGTH(*pBinding, pData)));
					break;

				case DBTYPE_IUNKNOWN: 
					//TODO
					//This is kind of a pain for SetData.  Since I'm going to
					//have to implement each object in order to pass it to the 
					//provider.  We might also be able to try the STGM_CREATE
					//which is supposed to return an empty implemented object
					//that we could "pump" our data into...
					
					//For now, the value is just set to NULL
					break;

				default:
					ASSERT(!"Unhandled Type!");
					break;
			}
			break;
		}
	}

CLEANUP:
	return hr;
}


////////////////////////////////////////////////////////////////
// CRowset::GetColumnData
//
/////////////////////////////////////////////////////////////////
HRESULT CRowset::GetColumnData(DBBINDING* pBinding, void* pData, DBSTATUS* pdwStatus, ULONG* pdwLength, DBTYPE* pwSubType, CHAR* pszValue, ULONG ulMaxSize, DWORD dwFlags, DBTYPE wBaseType)
{
	ASSERT(pBinding);
	ASSERT(pData);
	ASSERT(pszValue);
	HRESULT hr = S_OK;

	//STATUS
	DBSTATUS dwStatus = BINDING_STATUS(*pBinding, pData);

	//LENGTH
	DWORD dwLength = BINDING_LENGTH(*pBinding, pData);
	
	//SUB-DBTYPE
	DBTYPE	wSubType = wBaseType == DBTYPE_VARIANT ? DBTYPE_EMPTY : wBaseType;
	
	//LENGTH is the Actual (Untruncated) length of the string
	//We we need to make sure all operations are off of cbMaxLen and not LENGTH bound
	ULONG dwActualLength = min(pBinding->cbMaxLen-1, dwLength);
	ASSERT(pBinding->cbMaxLen <= ulMaxSize);

	//VALUE
	pszValue[0] = EOL;
	switch(dwStatus)
	{
		case DBSTATUS_S_ISNULL:
			break;

		//Let this case "fall" through to the S_OK case...
		case DBSTATUS_S_TRUNCATED:
			hr = DB_S_ERRORSOCCURRED;

		case DBSTATUS_S_OK:
		case DBSTATUS_S_DEFAULT:
		{
			switch(pBinding->wType)
			{
				case DBTYPE_WSTR:
				{	
					WCHAR* pwszData = (WCHAR*)&BINDING_VALUE(*pBinding, pData);
					ConvertToMBCS(pwszData, pszValue, ulMaxSize);
					break;
				}

				case DBTYPE_STR:
				{	
					CHAR* pszData = (CHAR*)&BINDING_VALUE(*pBinding, pData);
					strncpy(pszValue, pszData, dwActualLength);
					pszValue[dwActualLength] = EOL;
					break;
				}
					
				case DBTYPE_BYTES:
				{	
					//Otherwise treat it as a stream of BYTES
					BYTE* pbData = (BYTE*)&BINDING_VALUE(*pBinding, pData);
					BYTESToString(pbData, pszValue, dwActualLength, &dwLength);
					break;
				}

				case DBTYPE_VARIANT:
				{
					VARIANT* pVariant = (VARIANT*)&BINDING_VALUE(*pBinding, pData);
					if(pVariant)
					{
						wSubType = V_VT(pVariant);
						hr = VariantToString(pVariant, pszValue, ulMaxSize, dwFlags);
					}
					break;
				}

				case DBTYPE_IUNKNOWN: 
				{
					//This is required for ColumnsRowset IUnknown column
					//IUnknown is not a required conversion to string (WSTR)
					IUnknown* pIUnknown = (IUnknown*)BINDING_VALUE(*pBinding, pData);
					REFIID iid = pBinding->pObject ? pBinding->pObject->iid : IID_NULL;
					
					WCHAR wszBuffer[MAX_QUERY_LEN] = {0};
					void* pvBuffer = pszValue;
					dwLength = 0;

					//Need to handle WIDE streams...
					if(wBaseType == DBTYPE_BYTES || wBaseType == DBTYPE_WSTR || wBaseType == DBTYPE_BSTR)
						pvBuffer = wszBuffer;

					if(pIUnknown == NULL)
					{
						//I have no clue what type of object this is.
						//So just display the pointer
						sprintf(pszValue, "0x%08x", pIUnknown);
					}
					else if(iid == IID_ISequentialStream)
					{
						//Read the Data into our buffer
						ISequentialStream* pISeqStream = (ISequentialStream*)pIUnknown;
						XTESTC(NULL, hr = pISeqStream->Read(pvBuffer, ulMaxSize, &dwLength));
					}
					else if(iid == IID_ILockBytes)
					{
						//Read the Data into our buffer
						ULARGE_INTEGER ulOffset = {0};
						ILockBytes* pILockBytes = (ILockBytes*)pIUnknown;
						XTESTC(NULL, hr = pILockBytes->ReadAt(ulOffset, pvBuffer, ulMaxSize, &dwLength));
					}
					else if(iid == IID_IStream)
					{
						//Read the Data into our buffer
						IStream* pIStream = (IStream*)pIUnknown;
						XTESTC(NULL, hr = pIStream->Read(pvBuffer, ulMaxSize, &dwLength));
					}
//TODO				else if(iid == IID_IStorage)
//					{
//					}
					else
					{
						//I have no clue what type of object this is.
						//So just display the pointer
						sprintf(pszValue, "0x%08x", pIUnknown);
					}

					//Deal with the data returned...
					if(dwLength)
					{
						switch(wBaseType)
						{
							case DBTYPE_BSTR:
							case DBTYPE_WSTR:
								//Need to convert the stream to CHAR for display
								ConvertToMBCS(wszBuffer, pszValue, min(dwLength, ulMaxSize-1));
								break;

							case DBTYPE_STR:
								break;

							default:
								//Otherwise treat it as a stream of BYTES
								BYTESToString((BYTE*)pvBuffer, pszValue, min(dwLength, ulMaxSize-1), &dwLength);
								break;
						}

						//Need to NULL terminate the stream, since its just a stream
						//of bytes returned from the provider with no termination
						pszValue[min(dwLength, ulMaxSize-1)] = EOL;
					}

					SAFE_RELEASE(pIUnknown);
					break;
				}

				default:
					ASSERT(!"Unhandled Type!");
					hr = E_FAIL;
					break;
			}
			break;
		}

		default:
			//Error Status code...
			hr = E_FAIL;
			break;
	}
	
	//PostProcessing 
	if(SUCCEEDED(hr))
	{
		//Hexadecimal
		if(dwFlags & CONV_HEX)
		{
			switch(wSubType)
			{
				case DBTYPE_I1:
				case DBTYPE_UI1:
				case DBTYPE_I2:
				case DBTYPE_UI2:
				case DBTYPE_I4:
				case DBTYPE_UI4:
					ConvertString(pszValue, ulMaxSize, dwFlags);
					break;
			}
		}
	}


CLEANUP:
	//Output Params
	if(pdwStatus)
		*pdwStatus = dwStatus;
	if(pdwLength)
		*pdwLength = dwLength;
	if(pwSubType)
		*pwSubType = wSubType;
	return hr;
}


/////////////////////////////////////////////////////////////////
// HRESULT CRowset::CreateAccessors
//
/////////////////////////////////////////////////////////////////
HRESULT CRowset::CreateAccessors(BOOL fBindBookmark)
{
	HRESULT hr = S_OK;
	HRESULT hrOptional = S_OK;
	ULONG cbRowSize = 0;
	
	//Release Previous Accessors
	ReleaseAccessor(&m_hAccessor);
	FreeBindings(&m_cBindings, &m_rgBindings);
	SAFE_FREE(m_pData);

	ReleaseAccessor(&m_hBmkAccessor);
	FreeBindings(&m_cBmkBindings, &m_rgBmkBindings);

	//Delegate
	TESTC(hr = SetupBindings(fBindBookmark ? BIND_ALLCOLS : BIND_ALLCOLSEXPECTBOOKMARK, &m_cBindings, &m_rgBindings, &cbRowSize));
	TESTC(hr = CreateAccessor(DBACCESSOR_ROWDATA, m_cBindings, m_rgBindings, cbRowSize, &m_hAccessor));

	//Allocate pData
	SAFE_ALLOC(m_pData, BYTE, cbRowSize);

	//Create Bookmark Accessor (if bookmark is included)
	if(m_fContainsBmk)
	{
		TESTC(hrOptional = SetupBindings(BIND_BOOKMARKONLY, &m_cBmkBindings, &m_rgBmkBindings, &cbRowSize));
		TESTC(hrOptional = CreateAccessor(DBACCESSOR_ROWDATA, m_cBmkBindings, m_rgBmkBindings, cbRowSize, &m_hBmkAccessor));
	}

CLEANUP:
	return hr;
}
	

/////////////////////////////////////////////////////////////////
// HRESULT CRowset::SetupBindings
//
/////////////////////////////////////////////////////////////////
HRESULT CRowset::SetupBindings(BINDCOLS eBindCols, ULONG* pcBindings, DBBINDING** prgBindings, ULONG* pcRowSize, BOOL* pbOutofLine)
{
	HRESULT hr = S_OK;
	HWND hWnd = m_pCMDIChild->m_hWnd;
	CListBox* pCListBox = m_pCMDIChild->m_pCListBox;

	ULONG dwOffset = 0;
	ULONG i,cBindings = 0;
	DBBINDING* rgBindings = NULL;
	ULONG cStorageObjects = 0;
	
	//Only capable of the Following Converions (for Display)
	DBTYPE wBindingType = (DBTYPE)GetOptionsObj()->m_dwBindingType;
	DWORD  dwRowsetOpts = GetOptionsObj()->m_dwRowsetOpts;
	
	//Special Handling for Bookmark only accessor
	if(eBindCols == BIND_BOOKMARKONLY)
		wBindingType = DBTYPE_BYTES;
	else if(m_eRowsetSource == ROWSET_FROMCOMMANDDATASET)
 		wBindingType = DBTYPE_VARIANT;	// MSOLAP supports only variants

	//Alloc the space to hold the Bindings
	SAFE_ALLOC(rgBindings, DBBINDING, m_cColumns);

	cBindings = 0;
	for(i=0; i<m_cColumns; i++) 
	{
		ASSERT(m_rgColumnInfo);

		//Setup the Bindings
		rgBindings[cBindings].iOrdinal	= m_rgColumnInfo[i].iOrdinal;
		rgBindings[cBindings].obStatus	= dwOffset;
		rgBindings[cBindings].obLength	= dwOffset + sizeof(DBSTATUS);
		rgBindings[cBindings].obValue	= dwOffset + sizeof(DBSTATUS) + sizeof(ULONG);
		
		rgBindings[cBindings].pTypeInfo = NULL;
		rgBindings[cBindings].pBindExt  = NULL;

		rgBindings[cBindings].dwPart	= DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS;			
		rgBindings[cBindings].dwMemOwner= DBMEMOWNER_CLIENTOWNED;
		rgBindings[cBindings].eParamIO	= DBPARAMIO_NOTPARAM;
		
		rgBindings[cBindings].dwFlags	= 0;
		rgBindings[cBindings].bPrecision= m_rgColumnInfo[i].bPrecision;
		rgBindings[cBindings].bScale	= m_rgColumnInfo[i].bScale;

		rgBindings[cBindings].pObject	= NULL;
		rgBindings[cBindings].wType		= wBindingType;
		rgBindings[cBindings].cbMaxLen	= 0;
						
		//May need to adjust the MaxLen, depending upon what the BindingType is
		switch(wBindingType)
		{
			case DBTYPE_VARIANT:
				rgBindings[cBindings].cbMaxLen = sizeof(VARIANT);
				break;

⌨️ 快捷键说明

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