384 lines
13 KiB
C++
384 lines
13 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999, Microsoft Corp. All rights reserved.
|
|
//
|
|
// FILE
|
|
//
|
|
// Database.cpp
|
|
//
|
|
// SYNOPSIS
|
|
//
|
|
// Implementation of the CDatabase class. Mainly initialize, compact...
|
|
//
|
|
// MODIFICATION HISTORY
|
|
//
|
|
// 02/12/1999 Original version. Thierry Perraut
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
#include "precomp.hpp"
|
|
|
|
#include "database.h"
|
|
#include "msjetoledb.h"
|
|
#include "jetoledb.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Uninitialize: called at the end by main(), that calls compact()
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CDatabase::Uninitialize (bool bFatalError)
|
|
{
|
|
HRESULT hres;
|
|
|
|
#ifdef THPDEBUG
|
|
bFatalError = false;
|
|
#endif
|
|
|
|
////////////////////////////////////////
|
|
// if a fatal error occured before
|
|
////////////////////////////////////////
|
|
if (bFatalError)
|
|
{
|
|
hres = (m_pITransactionLocal->Abort (NULL, TRUE, FALSE));
|
|
TracePrintf ("Fatal Error: import to the database aborted.");
|
|
}
|
|
else
|
|
{
|
|
hres = (m_pITransactionLocal->Commit (TRUE, XACTTC_SYNC, 0));
|
|
#ifdef DEBUG
|
|
TracePrintf ("Successful import.\n");
|
|
#endif
|
|
}
|
|
|
|
///////////
|
|
// Clean
|
|
///////////
|
|
m_pIOpenRowset->Release();
|
|
m_pITransactionLocal->Release();
|
|
m_pIDBCreateSession->Release();
|
|
|
|
////////////////////////////////////////
|
|
// compact the DB
|
|
////////////////////////////////////////
|
|
CHECK_CALL_HRES (Compact());
|
|
|
|
m_pIDBInitialize->Release();
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Compact the database
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CDatabase::Compact ()
|
|
{
|
|
HRESULT hres;
|
|
|
|
CHECK_CALL_HRES (m_pIDBInitialize->Uninitialize ());
|
|
|
|
///////////////////////////////////////////////
|
|
// Set the properties for the data source.
|
|
//////////////////////////////////////////////
|
|
CComPtr <IDBProperties> l_pIDBProperties;
|
|
|
|
CHECK_CALL_HRES (m_pIDBInitialize->QueryInterface (
|
|
__uuidof (IDBProperties),
|
|
(void **) &l_pIDBProperties)
|
|
);
|
|
|
|
//////////////////////////////////
|
|
// Prepare the create session
|
|
//////////////////////////////////
|
|
DBPROP lprop[2];
|
|
|
|
VariantInit(&lprop[0].vValue);
|
|
lprop[0].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
lprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
|
|
V_VT (&(lprop[0].vValue)) = VT_BSTR;
|
|
|
|
//////////////////////////////////////////////////////
|
|
// put the path to the DB in the property.
|
|
// remark: temporaryname was used befire
|
|
// but the compacted database will have the name
|
|
// that was given as a parameter to that program
|
|
//////////////////////////////////////////////////////
|
|
V_BSTR (&(lprop[0].vValue)) = SysAllocString (TEMPORARY_FILENAME);
|
|
|
|
VariantInit(&lprop[1].vValue);
|
|
lprop[1].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
lprop[1].dwPropertyID = DBPROP_INIT_MODE;
|
|
V_VT (&(lprop[1].vValue)) = VT_I4;
|
|
V_I4 (&(lprop[1].vValue)) = DB_MODE_READ;
|
|
|
|
|
|
DBPROPSET lPropSet;
|
|
lPropSet.rgProperties = lprop;
|
|
lPropSet.cProperties = 2;
|
|
lPropSet.guidPropertySet = DBPROPSET_DBINIT;
|
|
|
|
///////////////////////
|
|
// Set the properties
|
|
///////////////////////
|
|
CHECK_CALL_HRES (l_pIDBProperties->SetProperties (
|
|
1,
|
|
&lPropSet
|
|
));
|
|
|
|
|
|
CHECK_CALL_HRES (m_pIDBInitialize->Initialize ());
|
|
|
|
IJetCompact* l_pIJetCompact;
|
|
CHECK_CALL_HRES ((m_pIDBInitialize->QueryInterface (
|
|
__uuidof (IJetCompact),
|
|
(void **) &l_pIJetCompact))
|
|
);
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// Prepare the properties for the data dest. (destination)
|
|
/////////////////////////////////////////////////////////////
|
|
DBPROP lpropDest[1];
|
|
|
|
VariantInit (&lprop[0].vValue);
|
|
lpropDest[0].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
lpropDest[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
|
|
V_VT (&(lpropDest[0].vValue)) = VT_BSTR;
|
|
|
|
///////////////////////////////////////////////////
|
|
// Delete the database file if it already existed.
|
|
// that should be safe because the temporary DB
|
|
// was succesfully created
|
|
///////////////////////////////////////////////////
|
|
DeleteFileW(mpDBPath.c_str());
|
|
|
|
//////////////////////////////////////////////
|
|
// put the path to the DB in the property.
|
|
//////////////////////////////////////////////
|
|
V_BSTR (&(lpropDest[0].vValue)) = SysAllocString (mpDBPath.c_str());
|
|
|
|
DBPROPSET lPropSetDest[1];
|
|
lPropSetDest[0].rgProperties = lpropDest;
|
|
lPropSetDest[0].cProperties = 1;
|
|
lPropSetDest[0].guidPropertySet = DBPROPSET_DBINIT;
|
|
|
|
|
|
CHECK_CALL_HRES (l_pIJetCompact->Compact(1, lPropSetDest));
|
|
|
|
/////////////
|
|
// Clean
|
|
/////////////
|
|
CHECK_CALL_HRES (m_pIDBInitialize->Uninitialize());
|
|
|
|
////////////////////////////////////////////
|
|
//result not checked: that's not important
|
|
////////////////////////////////////////////
|
|
DeleteFileW(TEMPORARY_FILENAME);
|
|
SysFreeString( V_BSTR (&(lpropDest[0].vValue)) );
|
|
SysFreeString( V_BSTR (&(lprop[0].vValue)) );
|
|
|
|
// The CHECK_CALL_HRES set the value of hres
|
|
return hres;
|
|
}
|
|
|
|
|
|
// ///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InitializeDB
|
|
//
|
|
// Comes from the file \ias\devtest\services\dictionary\dnary\dnarydump.cpp
|
|
//
|
|
// ///////////////////////////////////////////////////////////////////////////
|
|
HRESULT CDatabase::InitializeDB(WCHAR * pDatabasePath)
|
|
{
|
|
CLSID clsid;
|
|
HRESULT hres;
|
|
|
|
////////////////////////////////////////////////////
|
|
// Retrieve the classID for the jet 4.0 provider
|
|
////////////////////////////////////////////////////
|
|
CHECK_CALL_HRES(
|
|
CLSIDFromProgID (
|
|
OLESTR ("Microsoft.Jet.OLEDB.4.0"),
|
|
&clsid //Pointer to the CLSID
|
|
)
|
|
);
|
|
|
|
|
|
////////////////////////////////////
|
|
// init: init the provider directly
|
|
////////////////////////////////////
|
|
CHECK_CALL_HRES(
|
|
CoCreateInstance (
|
|
clsid,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
__uuidof (IDBInitialize),
|
|
(void **) &m_pIDBInitialize
|
|
)
|
|
);
|
|
|
|
mpDBPath = pDatabasePath;
|
|
|
|
//////////////////////////////////////////////
|
|
// Set the properties for the data source.
|
|
//////////////////////////////////////////////
|
|
CComPtr <IDBProperties> pIDBProperties;
|
|
|
|
CHECK_CALL_HRES(
|
|
m_pIDBInitialize->QueryInterface(
|
|
__uuidof (IDBProperties),
|
|
(void **) &pIDBProperties
|
|
)
|
|
);
|
|
|
|
///////////////////////////////
|
|
// Prepare the create session
|
|
///////////////////////////////
|
|
DBPROP lprop[2];
|
|
|
|
VariantInit (&lprop[0].vValue);
|
|
lprop[0].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
lprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
|
|
V_VT (&(lprop[0].vValue)) = VT_BSTR;
|
|
|
|
//////////////////////////////////////////////
|
|
// put the path to the DB in the property.
|
|
// this is the temporary filename
|
|
//////////////////////////////////////////////
|
|
V_BSTR (&(lprop[0].vValue)) = SysAllocString (TEMPORARY_FILENAME);
|
|
|
|
VariantInit(&lprop[1].vValue);
|
|
lprop[1].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
lprop[1].dwPropertyID = DBPROP_INIT_MODE;
|
|
V_VT (&(lprop[1].vValue)) = VT_I4;
|
|
V_I4 (&(lprop[1].vValue)) = DB_MODE_READWRITE;
|
|
|
|
|
|
DBPROPSET lPropSet;
|
|
lPropSet.rgProperties = lprop;
|
|
lPropSet.cProperties = 2;
|
|
lPropSet.guidPropertySet = DBPROPSET_DBINIT;
|
|
|
|
|
|
// Set the properties
|
|
CHECK_CALL_HRES(pIDBProperties->SetProperties (1, &lPropSet));
|
|
|
|
|
|
////////////////////
|
|
// Lock properties
|
|
////////////////////
|
|
DBPROP dbpropb[1];
|
|
dbpropb[0].dwPropertyID = DBPROP_JETOLEDB_DATABASELOCKMODE;
|
|
dbpropb[0].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
dbpropb[0].colid = DB_NULLID;
|
|
dbpropb[0].vValue.vt = VT_I4;
|
|
dbpropb[0].vValue.lVal = DBPROPVAL_DL_OLDMODE;
|
|
|
|
|
|
DBPROPSET dbpropSetb;
|
|
dbpropSetb.guidPropertySet = DBPROPSET_JETOLEDB_DBINIT;
|
|
dbpropSetb.cProperties = 1;
|
|
dbpropSetb.rgProperties = dbpropb;
|
|
|
|
// Set the properties
|
|
CHECK_CALL_HRES (pIDBProperties->SetProperties(1, &dbpropSetb));
|
|
|
|
CHECK_CALL_HRES (m_pIDBInitialize->Initialize ());
|
|
|
|
|
|
CHECK_CALL_HRES(
|
|
m_pIDBInitialize->QueryInterface(
|
|
__uuidof (IDBCreateSession),
|
|
(void **) &m_pIDBCreateSession
|
|
)
|
|
);
|
|
|
|
|
|
CHECK_CALL_HRES(
|
|
m_pIDBCreateSession->CreateSession (
|
|
NULL, // pUnkOuter
|
|
__uuidof (IOpenRowset),
|
|
(IUnknown **) & m_pIOpenRowset
|
|
)
|
|
);
|
|
|
|
|
|
CHECK_CALL_HRES(
|
|
m_pIOpenRowset->QueryInterface (
|
|
__uuidof (ITransactionLocal),
|
|
(PVOID *) & m_pITransactionLocal
|
|
)
|
|
);
|
|
|
|
//////////////////////////////////////////////
|
|
// start a transaction
|
|
// everything is "under" that transaction
|
|
//////////////////////////////////////////////
|
|
|
|
CHECK_CALL_HRES(
|
|
m_pITransactionLocal->StartTransaction (
|
|
ISOLATIONLEVEL_READUNCOMMITTED,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
)
|
|
);
|
|
|
|
////////////////////////////
|
|
// prepare the properties
|
|
////////////////////////////
|
|
|
|
mlrgProperties[0].dwPropertyID = DBPROP_IRowsetChange;
|
|
mlrgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
mlrgProperties[0].colid = DB_NULLID;
|
|
VariantInit(&mlrgProperties[0].vValue);
|
|
V_VT (&(mlrgProperties[0].vValue)) = VT_BOOL;
|
|
V_BOOL (&(mlrgProperties[0].vValue)) = VARIANT_TRUE;
|
|
|
|
|
|
mlrgProperties[1].dwPropertyID = DBPROP_UPDATABILITY;
|
|
mlrgProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
mlrgProperties[1].colid = DB_NULLID;
|
|
VariantInit (&mlrgProperties[1].vValue);
|
|
V_VT (&(mlrgProperties[1].vValue)) = VT_I4;
|
|
V_I4 (&(mlrgProperties[1].vValue)) = DBPROPVAL_UP_CHANGE |
|
|
DBPROPVAL_UP_DELETE |
|
|
DBPROPVAL_UP_INSERT;
|
|
|
|
mlrgPropSets->rgProperties = mlrgProperties;
|
|
mlrgPropSets->cProperties = 2;
|
|
mlrgPropSets->guidPropertySet = DBPROPSET_ROWSET;
|
|
|
|
|
|
SysFreeString(V_BSTR (&(lprop[0].vValue)));
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
// ///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InitializeRowset
|
|
//
|
|
// ///////////////////////////////////////////////////////////////////////////
|
|
HRESULT CDatabase::InitializeRowset(WCHAR * pTableName, IRowset ** ppRowset)
|
|
{
|
|
//Create the tableID
|
|
mTableID.eKind = DBKIND_NAME;
|
|
mTableID.uName.pwszName = pTableName;
|
|
|
|
//Open the (defined by parameters) rowset
|
|
return m_pIOpenRowset->OpenRowset(
|
|
NULL,
|
|
&mTableID,
|
|
NULL,
|
|
__uuidof (IRowset),
|
|
1,
|
|
mlrgPropSets,
|
|
(IUnknown **) ppRowset
|
|
);
|
|
}
|