|
|
/*++
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; }
|