705 lines
18 KiB
C++
705 lines
18 KiB
C++
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
schemaextensions.cpp
|
|
|
|
Abstract:
|
|
|
|
This file contains the implementation of the CSchemaExtensions class.
|
|
This is the only class that talks to the catalog.
|
|
|
|
Author:
|
|
|
|
MarcelV
|
|
|
|
Revision History:
|
|
|
|
Mohit Srivastava 28-Nov-00
|
|
|
|
--*/
|
|
|
|
#include "iisprov.h"
|
|
#include "schemaextensions.h"
|
|
#include "metabase.hxx"
|
|
|
|
LPWSTR g_wszDatabaseName = L"Metabase";
|
|
|
|
HRESULT GetMetabasePath(LPTSTR io_tszPath)
|
|
/*++
|
|
|
|
Synopsis:
|
|
This beast was copied and modified from
|
|
\%sdxroot%\iis\svcs\infocomm\metadata\dll\metasub.cxx
|
|
|
|
Arguments: [io_tszPath] - must be at least size MAX_PATH
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(io_tszPath != NULL);
|
|
|
|
HRESULT hresReturn = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
|
TCHAR tszBuffer[MAX_PATH] = {0};
|
|
HKEY hkRegistryKey = NULL;
|
|
DWORD dwRegReturn;
|
|
DWORD dwType;
|
|
DWORD dwSize = MAX_PATH * sizeof(TCHAR);
|
|
|
|
dwRegReturn = RegOpenKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
ADMIN_REG_KEY, // TEXT("SOFTWARE\\Microsoft\\INetMgr\\Parameters")
|
|
&hkRegistryKey);
|
|
if (dwRegReturn == ERROR_SUCCESS)
|
|
{
|
|
dwRegReturn = RegQueryValueEx(
|
|
hkRegistryKey,
|
|
MD_FILE_VALUE, // TEXT("MetadataFile")
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *) tszBuffer,
|
|
&dwSize);
|
|
if ((dwRegReturn == ERROR_SUCCESS) && dwType == (REG_SZ))
|
|
{
|
|
//
|
|
// TODO: Change this error code
|
|
//
|
|
hresReturn = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
|
for(ULONG i = dwSize/sizeof(TCHAR)-1; i > 0; i--)
|
|
{
|
|
if(tszBuffer[i] == TEXT('\\'))
|
|
{
|
|
tszBuffer[i] = TEXT('\0');
|
|
hresReturn = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey( hkRegistryKey );
|
|
hkRegistryKey = NULL;
|
|
|
|
}
|
|
if (FAILED(hresReturn))
|
|
{
|
|
dwRegReturn = RegOpenKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
SETUP_REG_KEY, // TEXT("SOFTWARE\\Microsoft\\InetStp")
|
|
&hkRegistryKey);
|
|
if (dwRegReturn == ERROR_SUCCESS)
|
|
{
|
|
dwSize = MAX_PATH * sizeof(TCHAR);
|
|
dwRegReturn = RegQueryValueEx(hkRegistryKey,
|
|
INSTALL_PATH_VALUE,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *) tszBuffer,
|
|
&dwSize);
|
|
if ((dwRegReturn == ERROR_SUCCESS) && dwType == (REG_SZ))
|
|
{
|
|
hresReturn = HRESULT_FROM_WIN32(dwRegReturn);
|
|
}
|
|
RegCloseKey( hkRegistryKey );
|
|
}
|
|
else
|
|
{
|
|
hresReturn = HRESULT_FROM_WIN32(dwRegReturn);
|
|
}
|
|
}
|
|
|
|
_tcscpy(io_tszPath, tszBuffer);
|
|
|
|
if(FAILED(hresReturn))
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Could not get metabase path, hr=0x%x\n", hresReturn));
|
|
}
|
|
return hresReturn;
|
|
}
|
|
|
|
int __cdecl
|
|
CompDBNames (const void * pDBMetaLHS, const void * pDBMetaRHS)
|
|
{
|
|
const tDATABASEMETARow *pLHS = static_cast<const tDATABASEMETARow *> (pDBMetaLHS );
|
|
const tDATABASEMETARow *pRHS = static_cast<const tDATABASEMETARow *> (pDBMetaRHS );
|
|
|
|
return _wcsicmp (pLHS->pInternalName, pRHS->pInternalName);
|
|
}
|
|
|
|
int __cdecl
|
|
CompTableMeta (const void * pTableMetaLHS, const void * pTableMetaRHS)
|
|
{
|
|
const CTableMeta *pLHS = static_cast<const CTableMeta *> (pTableMetaLHS );
|
|
const CTableMeta *pRHS = static_cast<const CTableMeta *> (pTableMetaRHS );
|
|
|
|
return _wcsicmp (pLHS->TableMeta.pInternalName, pRHS->TableMeta.pInternalName);
|
|
}
|
|
|
|
int __cdecl
|
|
CompTableDBName (const void * pTableMetaLHS, const void * pTableMetaRHS)
|
|
{
|
|
const CTableMeta *pLHS = static_cast<const CTableMeta *> (pTableMetaLHS );
|
|
const CTableMeta *pRHS = static_cast<const CTableMeta *> (pTableMetaRHS );
|
|
|
|
return _wcsicmp (pLHS->TableMeta.pDatabase, pRHS->TableMeta.pDatabase);
|
|
}
|
|
|
|
// sorted by table name and index
|
|
int __cdecl
|
|
CompColumnMetas (const void * pColumnMetaLHS, const void * pColumnMetaRHS)
|
|
{
|
|
const CColumnMeta *pLHS = static_cast<const CColumnMeta *> (pColumnMetaLHS );
|
|
const CColumnMeta *pRHS = static_cast<const CColumnMeta *> (pColumnMetaRHS );
|
|
|
|
int iCmp = _wcsicmp (pLHS->ColumnMeta.pTable, pRHS->ColumnMeta.pTable);
|
|
if (iCmp != 0)
|
|
{
|
|
return iCmp;
|
|
}
|
|
|
|
return (*pLHS->ColumnMeta.pIndex) - (*pRHS->ColumnMeta.pIndex);
|
|
}
|
|
|
|
// sorted by table name and index
|
|
int __cdecl
|
|
CompTagMetas (const void * pTagMetaLHS, const void * pTagMetaRHS)
|
|
{
|
|
const tTAGMETARow *pLHS = static_cast<const tTAGMETARow *> (pTagMetaLHS );
|
|
const tTAGMETARow *pRHS = static_cast<const tTAGMETARow *> (pTagMetaRHS );
|
|
|
|
int iCmp = _wcsicmp (pLHS->pTable, pRHS->pTable);
|
|
if (iCmp != 0)
|
|
{
|
|
return iCmp;
|
|
}
|
|
|
|
int iResult = (*pLHS->pColumnIndex) - (*pRHS->pColumnIndex);
|
|
if (iResult != 0)
|
|
{
|
|
return iResult;
|
|
}
|
|
|
|
return (*pLHS->pValue) - (*pRHS->pValue);
|
|
}
|
|
|
|
CSchemaExtensions::CSchemaExtensions ()
|
|
{
|
|
m_paTableMetas = 0;
|
|
m_cNrTables = 0;
|
|
|
|
m_paColumnMetas = 0;
|
|
m_cNrColumns = 0;
|
|
|
|
m_paTags = 0;
|
|
m_cNrTags = 0;
|
|
|
|
m_pQueryCells = 0;
|
|
m_cQueryCells = 0;
|
|
|
|
m_wszBinFileName = 0;
|
|
m_tszBinFilePath = 0;
|
|
|
|
m_bBinFileLoaded = false;
|
|
}
|
|
|
|
CSchemaExtensions::~CSchemaExtensions()
|
|
{
|
|
if(m_bBinFileLoaded)
|
|
{
|
|
m_spIMbSchemaComp->ReleaseBinFileName(m_wszBinFileName);
|
|
}
|
|
|
|
delete [] m_paTableMetas;
|
|
delete [] m_paColumnMetas;
|
|
delete [] m_paTags;
|
|
|
|
delete [] m_pQueryCells;
|
|
delete [] m_wszBinFileName;
|
|
delete [] m_tszBinFilePath;
|
|
}
|
|
|
|
HRESULT CSchemaExtensions::Initialize(bool i_bUseExtensions)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cch = 0;
|
|
|
|
InitializeSimpleTableDispenser();
|
|
|
|
//
|
|
// Get the dispenser
|
|
//
|
|
hr = GetSimpleTableDispenser (WSZ_PRODUCT_IIS, 0, &m_spDispenser);
|
|
if(FAILED(hr))
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Could not get dispenser, hr=0x%x\n", hr));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Get the schema compiler interface from the dispenser which will help us
|
|
// get the bin file name.
|
|
//
|
|
hr = m_spDispenser->QueryInterface(IID_IMetabaseSchemaCompiler,
|
|
(LPVOID*)&m_spIMbSchemaComp);
|
|
if(FAILED(hr))
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Couldn't get SchemaCompiler interface, hr=0x%x\n", hr));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Get the path of mbschema.xml
|
|
//
|
|
m_tszBinFilePath = new TCHAR[MAX_PATH+1];
|
|
if(m_tszBinFilePath == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
hr = GetMetabasePath(m_tszBinFilePath);
|
|
if(FAILED(hr))
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Couldn't get metabase path, hr=0x%x\n", hr));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Convert it to Unicode, Set Bin Path
|
|
//
|
|
#ifndef UNICODE
|
|
// we want to convert an MBCS string in lpszA
|
|
int nLen = MultiByteToWideChar(CP_ACP, 0,m_tszBinFilePath, -1, NULL, NULL);
|
|
LPWSTR lpszW = new WCHAR[nLen];
|
|
if(lpszW == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
if(MultiByteToWideChar(CP_ACP, 0, m_tszBinFilePath, -1, lpszW, nLen) == 0)
|
|
{
|
|
delete [] lpszW;
|
|
hr = GetLastError();
|
|
return HRESULT_FROM_WIN32(hr);
|
|
}
|
|
hr = m_spIMbSchemaComp->SetBinPath(lpszW);
|
|
delete [] lpszW;
|
|
#else
|
|
hr = m_spIMbSchemaComp->SetBinPath(m_tszBinFilePath);
|
|
#endif
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Get Bin FileName
|
|
//
|
|
hr = m_spIMbSchemaComp->GetBinFileName(NULL, &cch);
|
|
if(FAILED(hr))
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Couldn't get schema bin filename size, hr=0x%x\n", hr));
|
|
return hr;
|
|
}
|
|
m_wszBinFileName = new WCHAR[cch+1];
|
|
if(m_wszBinFileName == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
hr = m_spIMbSchemaComp->GetBinFileName(m_wszBinFileName, &cch);
|
|
if(FAILED(hr))
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Couldn't get schema bin filename, hr=0x%x\n", hr));
|
|
return hr;
|
|
}
|
|
m_bBinFileLoaded = true;
|
|
|
|
//
|
|
// Set up the query cells
|
|
//
|
|
m_cQueryCells = 2;
|
|
m_pQueryCells = new STQueryCell[m_cQueryCells];
|
|
if(m_pQueryCells == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if(i_bUseExtensions)
|
|
{
|
|
m_pQueryCells[0].pData = (LPVOID)m_wszBinFileName;
|
|
}
|
|
else
|
|
{
|
|
m_pQueryCells[0].pData = (LPVOID)NULL;
|
|
}
|
|
|
|
m_pQueryCells[0].eOperator = eST_OP_EQUAL;
|
|
m_pQueryCells[0].iCell = iST_CELL_SCHEMAFILE;
|
|
m_pQueryCells[0].dbType = DBTYPE_WSTR;
|
|
m_pQueryCells[0].cbSize = 0;
|
|
|
|
m_pQueryCells[1].pData = (void *) g_wszDatabaseName;
|
|
m_pQueryCells[1].eOperator = eST_OP_EQUAL;
|
|
m_pQueryCells[1].iCell = iCOLLECTION_META_Database;
|
|
m_pQueryCells[1].dbType = DBTYPE_WSTR;
|
|
m_pQueryCells[1].cbSize = 0;
|
|
|
|
hr = GenerateIt();
|
|
if(FAILED(hr))
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "GenerateIt failed, hr=0x%x\n", hr));
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSchemaExtensions::GetMbSchemaTimeStamp(
|
|
FILETIME* io_pFileTime) const
|
|
{
|
|
DBG_ASSERT(io_pFileTime != NULL);
|
|
DBG_ASSERT(m_tszBinFilePath != NULL);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
ULONG cchBinFilePath = _tcslen(m_tszBinFilePath);
|
|
ULONG cchSchFileName = _tcslen(MD_SCHEMA_FILE_NAME);
|
|
|
|
TCHAR* tszPathPlusName = new TCHAR[cchBinFilePath+1+cchSchFileName+1];
|
|
TCHAR* tszCurPos = tszPathPlusName;
|
|
if(tszPathPlusName == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// Copy the path
|
|
//
|
|
tszCurPos = tszPathPlusName;
|
|
memcpy(tszCurPos, m_tszBinFilePath, sizeof(TCHAR)*(cchBinFilePath+1));
|
|
|
|
//
|
|
// Concat a \ if necessary, and the filename,
|
|
//
|
|
tszCurPos = tszPathPlusName + cchBinFilePath;
|
|
if(m_tszBinFilePath[cchBinFilePath-1] != TEXT('\\'))
|
|
{
|
|
memcpy(tszCurPos, TEXT("\\"), sizeof(TCHAR)*2);
|
|
tszCurPos++;
|
|
}
|
|
memcpy(tszCurPos, MD_SCHEMA_FILE_NAME, sizeof(TCHAR)*(cchSchFileName+1));
|
|
|
|
//
|
|
// Now get the file info
|
|
//
|
|
{
|
|
WIN32_FIND_DATA FindFileData;
|
|
memset(&FindFileData, 0, sizeof(WIN32_FIND_DATA));
|
|
|
|
HANDLE hFindFile = FindFirstFile(tszPathPlusName, &FindFileData);
|
|
if(hFindFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
hr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto exit;
|
|
}
|
|
FindClose(hFindFile);
|
|
|
|
//
|
|
// Set out parameters if everything succeeded
|
|
//
|
|
memcpy(io_pFileTime, &FindFileData.ftLastWriteTime, sizeof(FILETIME));
|
|
}
|
|
|
|
exit:
|
|
delete [] tszPathPlusName;
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSchemaExtensions::GenerateIt ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = GetTables ();
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
hr = GetColumns ();
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = GetTags ();
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = BuildInternalStructures ();
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSchemaExtensions::GetTables ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ULONG one = 1;
|
|
|
|
hr = m_spDispenser->GetTable (wszDATABASE_META, wszTABLE_TABLEMETA,
|
|
m_pQueryCells, (void *)&one, eST_QUERYFORMAT_CELLS, 0, (void **) &m_spISTTableMeta);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = m_spISTTableMeta->GetTableMeta (0, 0, &m_cNrTables, 0);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (m_cNrTables == 0)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
m_paTableMetas = new CTableMeta [m_cNrTables];
|
|
if (m_paTableMetas == 0)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
for (ULONG idx =0; idx < m_cNrTables; ++idx)
|
|
{
|
|
hr = m_spISTTableMeta->GetColumnValues (idx, sizeof (tTABLEMETARow)/sizeof (ULONG *), 0, 0, (void **) &m_paTableMetas[idx].TableMeta);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (m_paTableMetas[idx].ColCount () > 0)
|
|
{
|
|
// set number of columns
|
|
m_paTableMetas[idx].paColumns = new LPCColumnMeta[m_paTableMetas[idx].ColCount()];
|
|
if (m_paTableMetas[idx].paColumns == 0)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
// and sort them by table name
|
|
|
|
qsort (m_paTableMetas, m_cNrTables, sizeof (CTableMeta), CompTableMeta);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSchemaExtensions::GetColumns ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ULONG one = 1;
|
|
|
|
hr = m_spDispenser->GetTable (wszDATABASE_META, wszTABLE_COLUMNMETA,
|
|
m_pQueryCells, (void *)&one, eST_QUERYFORMAT_CELLS, 0, (void **) &m_spISTColumnMeta);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = m_spISTColumnMeta->GetTableMeta (0, 0, &m_cNrColumns, 0);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (m_cNrColumns == 0)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
m_paColumnMetas = new CColumnMeta[m_cNrColumns];
|
|
if (m_paColumnMetas == 0)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
ULONG acbSizes[cCOLUMNMETA_NumberOfColumns];
|
|
for (ULONG idx =0; idx < m_cNrColumns; ++idx)
|
|
{
|
|
hr = m_spISTColumnMeta->GetColumnValues (idx, sizeof (tCOLUMNMETARow)/sizeof (ULONG *), 0, acbSizes, (void **) &m_paColumnMetas[idx].ColumnMeta);
|
|
m_paColumnMetas[idx].cbDefaultValue = acbSizes[iCOLUMNMETA_DefaultValue];
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
qsort (m_paColumnMetas, m_cNrColumns, sizeof (CColumnMeta), CompColumnMetas);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSchemaExtensions::GetTags ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ULONG one = 1;
|
|
|
|
hr = m_spDispenser->GetTable (wszDATABASE_META, wszTABLE_TAGMETA,
|
|
m_pQueryCells, (void *)&one, eST_QUERYFORMAT_CELLS, 0, (void **) &m_spISTTagMeta);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = m_spISTTagMeta->GetTableMeta (0, 0, &m_cNrTags, 0);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (m_cNrTags == 0)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
m_paTags = new tTAGMETARow[m_cNrTags];
|
|
if (m_paTags == 0)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
for (ULONG idx =0; idx < m_cNrTags; ++idx)
|
|
{
|
|
hr = m_spISTTagMeta->GetColumnValues (idx, sizeof (tTAGMETARow)/sizeof (ULONG *), 0, 0, (void **) &m_paTags[idx]);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
qsort (m_paTags, m_cNrTags, sizeof (tTAGMETARow), CompTagMetas);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSchemaExtensions::BuildInternalStructures ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// attach the tags to the tables
|
|
|
|
ULONG idx = 0;
|
|
while (idx < m_cNrTags)
|
|
{
|
|
// find the correct column
|
|
CColumnMeta dummyColumnMeta;
|
|
dummyColumnMeta.ColumnMeta.pTable = m_paTags[idx].pTable;
|
|
dummyColumnMeta.ColumnMeta.pIndex = m_paTags[idx].pColumnIndex;
|
|
// get column
|
|
CColumnMeta *pColMeta = (CColumnMeta *) bsearch (&dummyColumnMeta,
|
|
m_paColumnMetas,
|
|
m_cNrColumns,
|
|
sizeof (CColumnMeta),
|
|
CompColumnMetas);
|
|
|
|
DBG_ASSERT (pColMeta != NULL);
|
|
DBG_ASSERT (wcscmp(pColMeta->ColumnMeta.pTable, m_paTags[idx].pTable) == 0 &&
|
|
*pColMeta->ColumnMeta.pIndex == *m_paTags[idx].pColumnIndex);
|
|
|
|
// get count
|
|
ULONG iStartIdx = idx;
|
|
pColMeta->cNrTags = 1;
|
|
idx++; // skip over this element
|
|
while ((idx < m_cNrTags) &&
|
|
(wcscmp(pColMeta->ColumnMeta.pTable, m_paTags[idx].pTable) == 0) &&
|
|
(*pColMeta->ColumnMeta.pIndex == *m_paTags[idx].pColumnIndex))
|
|
{
|
|
idx++;
|
|
pColMeta->cNrTags += 1;
|
|
}
|
|
|
|
if (pColMeta->cNrTags > 0)
|
|
{
|
|
// allocate memory and copy the stuff
|
|
pColMeta->paTags = new LPtTAGMETA[pColMeta->cNrTags];
|
|
if (pColMeta->paTags == 0)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
for (ULONG tagIdx = 0; tagIdx < pColMeta->cNrTags; ++tagIdx)
|
|
{
|
|
pColMeta->paTags[tagIdx] = &m_paTags[iStartIdx + tagIdx];
|
|
}
|
|
}
|
|
}
|
|
|
|
// attach the columns to the tables
|
|
for (idx=0; idx < m_cNrColumns; ++idx)
|
|
{
|
|
CTableMeta dummyTableMeta;
|
|
dummyTableMeta.TableMeta.pInternalName = m_paColumnMetas[idx].ColumnMeta.pTable;
|
|
// find table
|
|
CTableMeta *pTableMeta = (CTableMeta *) bsearch (&dummyTableMeta, m_paTableMetas,
|
|
m_cNrTables,
|
|
sizeof (CTableMeta),
|
|
CompTableMeta);
|
|
DBG_ASSERT (pTableMeta != 0);
|
|
DBG_ASSERT (wcscmp(pTableMeta->TableMeta.pInternalName, m_paColumnMetas[idx].ColumnMeta.pTable) == 0);
|
|
|
|
// add Column to table
|
|
|
|
ULONG iColumnIndex = *(m_paColumnMetas[idx].ColumnMeta.pIndex);
|
|
DBG_ASSERT (iColumnIndex < pTableMeta->ColCount ());
|
|
pTableMeta->paColumns[iColumnIndex] = &m_paColumnMetas[idx];
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CTableMeta* CSchemaExtensions::EnumTables(ULONG *io_idx)
|
|
{
|
|
DBG_ASSERT(io_idx != NULL);
|
|
|
|
CTableMeta* pRet = NULL;
|
|
|
|
while(1)
|
|
{
|
|
if(*io_idx < m_cNrTables)
|
|
{
|
|
pRet = &m_paTableMetas[*io_idx];
|
|
if( _wcsicmp(pRet->TableMeta.pDatabase, g_wszDatabaseName) == 0 &&
|
|
!(*pRet->TableMeta.pMetaFlags & fTABLEMETA_HIDDEN) )
|
|
{
|
|
*io_idx = 1 + *io_idx;
|
|
return pRet;
|
|
}
|
|
else
|
|
{
|
|
*io_idx = 1 + *io_idx;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*io_idx = 1 + *io_idx;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|