256 lines
6.3 KiB
C++
256 lines
6.3 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright (c) 1997, Microsoft Corp. All rights reserved.
|
||
|
//
|
||
|
// FILE
|
||
|
//
|
||
|
// DataSource.cpp
|
||
|
//
|
||
|
// SYNOPSIS
|
||
|
//
|
||
|
// This file implements the class CIasDataSource.
|
||
|
//
|
||
|
// MODIFICATION HISTORY
|
||
|
//
|
||
|
// 11/05/1997 Original version.
|
||
|
// 12/19/1997 Added ExecuteCommand method.
|
||
|
// 01/15/1998 Implemented IIasComponent method.
|
||
|
// 02/09/1998 Added AllowUpdate property.
|
||
|
// 03/17/1999 Create TMP dir before calling IDBInitialize::Initialize.
|
||
|
// 04/22/1999 Clean-up session and connection in destructor.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include <iascore.h>
|
||
|
#include <iasutil.h>
|
||
|
#include <guard.h>
|
||
|
#include <DataSource.h>
|
||
|
#include <PropSet.h>
|
||
|
|
||
|
CIasDataSource::CIasDataSource() throw ()
|
||
|
: initStatus(E_FAIL),
|
||
|
provider(NULL),
|
||
|
name(NULL),
|
||
|
userID(NULL),
|
||
|
password(NULL),
|
||
|
allowUpdate(false),
|
||
|
connection(NULL),
|
||
|
session(NULL)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CIasDataSource::~CIasDataSource() throw ()
|
||
|
{
|
||
|
if (session) { session->Release(); }
|
||
|
if (connection) { connection->Release(); }
|
||
|
|
||
|
delete[] password;
|
||
|
delete[] userID;
|
||
|
delete[] name;
|
||
|
delete[] provider;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////
|
||
|
// Macros to handle getting and putting a string property.
|
||
|
//////////
|
||
|
|
||
|
#define WSTRING_PROPERTY(class, prop, member) \
|
||
|
STDMETHODIMP class ## ::put_ ## prop (LPCWSTR newVal) \
|
||
|
{ \
|
||
|
_com_serialize \
|
||
|
delete[] member; \
|
||
|
member = ias_wcsdup(newVal); \
|
||
|
return S_OK; \
|
||
|
} \
|
||
|
\
|
||
|
STDMETHODIMP class ## ::get_ ## prop (LPWSTR* pVal) \
|
||
|
{ \
|
||
|
if (pVal == NULL) return E_POINTER; \
|
||
|
_com_serialize \
|
||
|
*pVal = com_wcsdup(member); \
|
||
|
return S_OK; \
|
||
|
}
|
||
|
|
||
|
WSTRING_PROPERTY(CIasDataSource, Provider, provider)
|
||
|
WSTRING_PROPERTY(CIasDataSource, Name, name)
|
||
|
WSTRING_PROPERTY(CIasDataSource, UserID, userID)
|
||
|
WSTRING_PROPERTY(CIasDataSource, Password, password)
|
||
|
|
||
|
STDMETHODIMP CIasDataSource::put_AllowUpdate(boolean newVal)
|
||
|
{
|
||
|
allowUpdate = (newVal != 0);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CIasDataSource::get_AllowUpdate(boolean* pVal)
|
||
|
{
|
||
|
return pVal ? (*pVal = (boolean)allowUpdate), S_OK : E_POINTER;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////
|
||
|
// Macro to set the InitStatus and bail on an error.
|
||
|
//////////
|
||
|
#define CHECK_INIT(expr) \
|
||
|
if (FAILED(initStatus = expr)) return initStatus;
|
||
|
|
||
|
|
||
|
STDMETHODIMP CIasDataSource::Initialize()
|
||
|
{
|
||
|
_com_serialize
|
||
|
|
||
|
// Clean up an existing connection.
|
||
|
Shutdown();
|
||
|
|
||
|
// Convert the ProgID to a ClsID.
|
||
|
CLSID clsid;
|
||
|
CHECK_INIT(CLSIDFromProgID(provider, &clsid));
|
||
|
|
||
|
// Create the OLE DB provider.
|
||
|
CHECK_INIT(CoCreateInstance(clsid,
|
||
|
NULL,
|
||
|
CLSCTX_INPROC_SERVER,
|
||
|
IID_IDBInitialize,
|
||
|
(PVOID*)&connection));
|
||
|
|
||
|
//////////
|
||
|
// Set the properties for the data source.
|
||
|
//////////
|
||
|
|
||
|
CComPtr<IDBProperties> properties;
|
||
|
CHECK_INIT(connection->QueryInterface(IID_IDBProperties,
|
||
|
(PVOID*)&properties));
|
||
|
|
||
|
DBPropertySet<4> propSet(DBPROPSET_DBINIT);
|
||
|
|
||
|
propSet.AddProperty(DBPROP_INIT_MODE, allowUpdate ? DB_MODE_READWRITE
|
||
|
: DB_MODE_READ);
|
||
|
|
||
|
if (name) propSet.AddProperty(DBPROP_INIT_DATASOURCE, name);
|
||
|
if (userID) propSet.AddProperty(DBPROP_AUTH_USERID, userID);
|
||
|
if (password) propSet.AddProperty(DBPROP_AUTH_PASSWORD, password);
|
||
|
|
||
|
CHECK_INIT(properties->SetProperties(1, &propSet));
|
||
|
|
||
|
//////////
|
||
|
// JetInit fails if the TMP directory doesn't exist, so we'll try to
|
||
|
// create it just in case.
|
||
|
//////////
|
||
|
|
||
|
DWORD needed = GetEnvironmentVariableW(L"TMP", NULL, 0);
|
||
|
if (needed)
|
||
|
{
|
||
|
PWCHAR buf = (PWCHAR)_alloca(needed * sizeof(WCHAR));
|
||
|
DWORD actual = GetEnvironmentVariableW(L"TMP", buf, needed);
|
||
|
if (actual > 0 && actual < needed)
|
||
|
{
|
||
|
CreateDirectoryW(buf, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////
|
||
|
// Initialize the connection.
|
||
|
//////////
|
||
|
|
||
|
CHECK_INIT(connection->Initialize());
|
||
|
|
||
|
//////////
|
||
|
// Create a session.
|
||
|
//////////
|
||
|
|
||
|
CComPtr<IDBCreateSession> creator;
|
||
|
CHECK_INIT(connection->QueryInterface(IID_IDBCreateSession,
|
||
|
(PVOID*)&creator));
|
||
|
|
||
|
CHECK_INIT(creator->CreateSession(NULL,
|
||
|
IID_IOpenRowset,
|
||
|
(IUnknown**)&session));
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CIasDataSource::Shutdown()
|
||
|
{
|
||
|
_com_serialize
|
||
|
|
||
|
IAS_DEREF(session);
|
||
|
IAS_DEREF(connection);
|
||
|
|
||
|
initStatus = E_FAIL;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CIasDataSource::OpenTable(LPCWSTR szTableName, IUnknown** ppTable)
|
||
|
{
|
||
|
if (!ppTable)
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
// Make sure the data source has been successfully initialized.
|
||
|
_com_serialize
|
||
|
|
||
|
if (FAILED(initStatus))
|
||
|
{
|
||
|
return initStatus;
|
||
|
}
|
||
|
|
||
|
*ppTable = NULL;
|
||
|
|
||
|
DBID idTable;
|
||
|
idTable.eKind = DBKIND_NAME;
|
||
|
idTable.uName.pwszName = const_cast<LPWSTR>(szTableName);
|
||
|
|
||
|
return session->OpenRowset(NULL,
|
||
|
&idTable,
|
||
|
NULL,
|
||
|
IID_IUnknown,
|
||
|
0,
|
||
|
NULL,
|
||
|
ppTable);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CIasDataSource::ExecuteCommand(REFGUID rguidDialect,
|
||
|
LPCWSTR szCommandText,
|
||
|
IUnknown** ppRowset)
|
||
|
{
|
||
|
if (!ppRowset)
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
_com_serialize
|
||
|
|
||
|
// Make sure the data source has been successfully initialized.
|
||
|
if (FAILED(initStatus))
|
||
|
{
|
||
|
return initStatus;
|
||
|
}
|
||
|
|
||
|
*ppRowset = NULL;
|
||
|
|
||
|
CComPtr<IDBCreateCommand> creator;
|
||
|
RETURN_ERROR(session->QueryInterface(IID_IDBCreateCommand,
|
||
|
(PVOID*)&creator));
|
||
|
|
||
|
CComPtr<ICommandText> command;
|
||
|
RETURN_ERROR(creator->CreateCommand(NULL,
|
||
|
IID_ICommandText,
|
||
|
(IUnknown**)&command));
|
||
|
|
||
|
RETURN_ERROR(command->SetCommandText(rguidDialect,
|
||
|
szCommandText));
|
||
|
|
||
|
return command->Execute(NULL,
|
||
|
IID_IUnknown,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
ppRowset);
|
||
|
}
|