|
|
/*******************************************************
* @doc SHROOM EXTERNAL API * * * * DBIMP.CPP * * * * Copyright (C) Microsoft Corporation 1997 * * All rights reserved. * * * * This file contains the local * * implementation of CDatabase. * * * ******************************************************** * * * Header section added by Anita Legsdin so that * * comments will appear in Autodoc * * * *******************************************************/ // DBIMP.CPP: Implementation of CDatabase
// I'd like to get rid of this, but for now we include it so this compiles
#ifdef _DEBUG
static char s_aszModule[] = __FILE__; /* For error report */ #endif
#include <atlinc.h>
// MediaView (InfoTech) includes
#include <mvopsys.h>
#include <groups.h>
#include <wwheel.h>
#include <msitstg.h>
#include <ccfiles.h>
#include "itdb.h"
#include "DBImp.h"
// TODO TODO TODO: Replace the blind use of critical sections with a
// better way of ensuring thread-safeness while preserving performance.
// But for now, in the interest of coding time, we just make sure the
// code is thread-safe.
//---------------------------------------------------------------------------
// Constructor and Destructor
//---------------------------------------------------------------------------
CITDatabaseLocal::CITDatabaseLocal() { m_pStorage = NULL; }
CITDatabaseLocal::~CITDatabaseLocal() { Close(); }
//---------------------------------------------------------------------------
// IITDatabase Method Implemenations
//---------------------------------------------------------------------------
/********************************************************************
* @method STDMETHODIMP | IITDatabase | Open | * Opens a database * * @parm LPCWSTR | lpszHost | Host name. You can pass NULL if calling Open * locally, otherwise this string should contain the host description string, described * below. * * @parm LPCWSTR | lpszMoniker | Name of database file to open. This should include * the full path to the file name, if calling locally. If calling using HTTP, this * should contain the ISAPI extension DLL name followed by the relative path to the database * file, for example: * * isapiext.dll?path1\path2\db.its * * @parm DWORD | dwFlags | Currently not used * * @rvalue STG_E* | Any of the IStorage errors that can occur when opening a storage. * @rvalue S_OK | The database was successfully opened * * @comm Current implementation opens all databases using the IT storage system (ITSS). * As a consequence, all databases must be built using ITSS. * * Currently two transport protocols are supported: local in-proc and HTTP. For the * local protocol the host name is NULL. For HTTP, it must be set to the transport address * of the machine which is running the ITIR ISAPI extension. For example, one possible HTTP * host name string would be "http:\\www.microsoft.com\" * * This method might attempt to connect to the database in order to load configuration information. ********************************************************************/ STDMETHODIMP CITDatabaseLocal::Open(LPCWSTR lpszHost, LPCWSTR lpszMoniker, DWORD dwFlags) { HRESULT hr; IITStorage* pITStorage = NULL; if (NULL == lpszMoniker) return SetErrReturn(E_INVALIDARG);
// For now, we assume we're getting an ITSS file
// We might want to replace this later with more sophisticated code
// that parses the given moniker
m_cs.Lock();
if (m_pStorage) return SetErrReturn(E_ALREADYINIT);
// Open storage READ-only; we only need one instance
if (SUCCEEDED(hr = CoCreateInstance(CLSID_ITStorage, NULL, CLSCTX_INPROC_SERVER, IID_ITStorage, (VOID **) &pITStorage)) && SUCCEEDED(hr = pITStorage->StgOpenStorage(lpszMoniker, NULL, STGM_READ, NULL, 0, &m_pStorage))) { hr = Load(m_pStorage); }
// Free ITSS interface no longer needed
if (pITStorage) pITStorage->Release();
m_cs.Unlock(); return hr; }
/********************************************************************
* @method STDMETHODIMP | IITDatabase | Close | * Closes a database * * @rvalue S_OK | The database was successfully closed * ********************************************************************/ STDMETHODIMP CITDatabaseLocal::Close() { m_cs.Lock();
// release storage pointer
if (m_pStorage) { m_pStorage->Release(); m_pStorage = NULL; } else return SetErrReturn(E_NOTINIT); m_ObjInst.Close();
m_cs.Unlock(); return S_OK; }
/******************************************************************* *
* @method STDMETHODIMP WINAPI | IITDatabase | CreateObject | * Creates an unnamed object that can be referenced in the future * by *pdwObjInstance. * * @parm REFCLSID | refclsid | Class ID for object. * @parm DWORD | *pdwObjInstance | Identifier for object. * * @rvalue S_OK | The object was successfully created * @rvalue E_INVALIDARG | The argument was not valid * @rvalue E_NOTINIT | * @rvalue E_OUTOFMEMORY | * * @comm * The value in *pdwObjInstance will be * persisted by the database when it is asked to save using * IPersistStorage::Save. * ********************************************************************/ STDMETHODIMP CITDatabaseLocal::CreateObject(REFCLSID rclsid, DWORD *pdwObjInstance) { return m_ObjInst.AddObject(rclsid, pdwObjInstance); }
/******************************************************************* *
* @method STDMETHODIMP WINAPI | IITDatabase | GetObject | * Retrieves a specified IUnknown-based interface on the object identified * by dwObjInstance. * * @parm DWORD | dwObjInstance | Identifier for object. * @parm REFIID | refiid | Interface ID * @parm LPVOID | *ppvObj | * * @rvalue S_OK | The operation completed successfully. * @rvalue E_INVALIDARG | The argument was not valid. * @rvalue E_NOTINIT | * @rvalue E_OUTOFMEMORY | * * ********************************************************************/ STDMETHODIMP CITDatabaseLocal::GetObject(DWORD dwObjInstance, REFIID riid, LPVOID *ppvObj) { return m_ObjInst.GetObject(dwObjInstance, riid, ppvObj); }
/******************************************************************* *
* @method STDMETHODIMP WINAPI | IITDatabase | GetObjectPersistence | * Retrieves persistence data for a named object. * * @parm LPCWSTR | lpwszObject | Name of the object * @parm DWORD | dwObjInstance | Object instance ID * @parm LPVOID | *ppvPersistence | Pointer to persistence data for the object. * @parm BOOL | fStream | Identifies whether the object is a stream object (true) * or storage object (false). * * @rvalue S_OK | The operation completed successfully. * @rvalue E_INVALIDARG | The argument was not valid. * @rvalue STG_E_FILENOTFOUND |The specified object's persistence does not * exist, or it is of the wrong type. * @rvalue E_NOTINIT | * @rvalue E_OUTOFMEMORY | * * @comm
* To obtain a pointer to a named object's persistence, specify the * object's full name (including any object-specific type prefix) in * lpswszObject. If *lpwszObject is NULL, then the database's own storage * is returned. If lpwszObject is NULL, then dwObjInstance is * used to identify the object and locate its persistence. On exit, * *ppvPersistence is either an IStorage* or an IStream*, depending * on what you specified in the fStream param. Only read operations * can be performed on *ppvPersistence. * ********************************************************************/ STDMETHODIMP CITDatabaseLocal::GetObjectPersistence(LPCWSTR lpwszObject, DWORD dwObjInstance, LPVOID *ppvPersistence, BOOL fStream) { HRESULT hr = S_OK;
m_cs.Lock();
if (m_pStorage != NULL) { if (lpwszObject != NULL) { if (fStream) hr = m_pStorage->OpenStream(lpwszObject, NULL, STGM_READ, 0, (IStream **) ppvPersistence); else { if (*lpwszObject == (WCHAR) NULL) { m_pStorage->AddRef(); *ppvPersistence = (LPVOID) m_pStorage; } else hr = m_pStorage->OpenStorage(lpwszObject, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, (IStorage **) ppvPersistence); } } else { if (fStream) { // REVIEW (billa, johnrush): Need to allocate memory for the
// object's persistent data and call CreateStreamOnHGlobal.
hr = E_NOTSUPPORTED; } else hr = STG_E_FILENOTFOUND; } } else hr = E_UNEXPECTED;
m_cs.Unlock(); return (hr); }
//---------------------------------------------------------------------------
// IPersistStorage Method Implementations
//---------------------------------------------------------------------------
STDMETHODIMP CITDatabaseLocal::GetClassID(CLSID *pclsid) { *pclsid = CLSID_IITDatabaseLocal; return (S_OK); }
STDMETHODIMP CITDatabaseLocal::InitNew(IStorage *pStorage) { HRESULT hr = S_OK;
if (pStorage == NULL) return (E_POINTER);
m_cs.Lock();
if (m_pStorage == NULL) (m_pStorage = pStorage)->AddRef(); else hr = E_UNEXPECTED;
m_ObjInst.InitNew();
m_cs.Unlock();
return (hr); }
STDMETHODIMP CITDatabaseLocal::IsDirty(void) { return m_ObjInst.IsDirty(); }
STDMETHODIMP CITDatabaseLocal::Load(IStorage *pStorage) { HRESULT hr = S_OK;;
if (pStorage == NULL) return (E_POINTER);
m_cs.Lock();
IStream *pistmObjectManager; if (FAILED(hr = pStorage->OpenStream (SZ_OBJINST_STREAM, STGM_READ, 0, 0, &pistmObjectManager))) return (hr);
hr = m_ObjInst.Load(pistmObjectManager); pistmObjectManager->Release();
m_cs.Unlock(); return (hr); }
STDMETHODIMP CITDatabaseLocal::Save(IStorage *pStorage, BOOL fSameAsLoad) { HRESULT hr = S_OK;;
if (pStorage == NULL) return (E_POINTER);
m_cs.Lock();
IStream *pistmObjectManager; if (FAILED(hr = pStorage->CreateStream (SZ_OBJINST_STREAM, STGM_WRITE, 0, 0, &pistmObjectManager))) return (hr);
hr = m_ObjInst.Save(pistmObjectManager, TRUE); pistmObjectManager->Release();
m_cs.Unlock(); return (hr); }
STDMETHODIMP CITDatabaseLocal::SaveCompleted(IStorage *pStorageNew) { if (pStorageNew != NULL) { m_cs.Lock();
if (m_pStorage != NULL) m_pStorage->Release();
(m_pStorage = pStorageNew)->AddRef();
m_cs.Unlock(); }
return (S_OK); }
STDMETHODIMP CITDatabaseLocal::HandsOffStorage(void) { // REVIEW (billa): At some point, we should implement IPersistStorage
// mode tracking so that we explicitly enter/leave the No Scribble and
// Hands Off Storage modes.
return (S_OK); }
|