#include "stdafx.h"
#include "bridgedb.h"
#include <atlcomtime.h>


/////////////////////////////////
// the various records default values

// Note: when adding/removing fields the following items are affected:
// SetDefault, operator=, Stored Procedures, BridgeDB operations on that record

int NullUserId = -1;
int NullLocationId = -1;
int OtherLocationId = -3;
int NullGroupId = -1;
int NullCategoryId = -1;
int NullEventId = -1;
int NullYearId = -1;

void UserRecord::SetDefault()
{
	UserId = NullUserId;
	UserLogin = L"Unknown";
	Password = L"Unknown";
	FirstName = L"Unknown";
	LastName = L"Unknown";
	Email = L"Unknown";
	YearId = NullYearId;
	LoggedIn = 0;
	LoggedInSince = COleDateTime::GetCurrentTime();
	Idle = 0;
	IdleSince = COleDateTime::GetCurrentTime();
	LocationId = NullLocationId;
	LastLocationId = NullLocationId;
	Away = 0;
	AwayMessage = L"Unknown";
	PrivacyLevel = bcNormal;
	SecretWeapon = L"Unknown";
	Interest = L"Unknown";
	Background = L"Unknown";

	update = 1;
}

UserRecord & UserRecord::operator=(UserRecord& x)
{
	UserId = x.UserId;
	UserLogin = x.UserLogin;
	Password = x.Password;
	FirstName = x.FirstName;
	LastName = x.LastName;
	Email = x.Email;
	YearId = x.YearId;
	LoggedIn = x.LoggedIn;
	LoggedInSince = x.LoggedInSince;
	Idle = x.Idle;
	IdleSince = x.IdleSince;
	LocationId = x.LocationId;
	LastLocationId = x.LastLocationId;
	Away = x.Away;
	AwayMessage = x.AwayMessage;
	PrivacyLevel = x.PrivacyLevel;
	SecretWeapon = x.SecretWeapon;
	Interest = x.Interest;
	Background = x.Background;

	return *this;
}

void LocationRecord::SetDefault()
{
	LocationId = NullLocationId;
	LocationName = L"Unknown";
	ParentId = NullLocationId;
	Wireless = 0;
	nEvents = 0;
	nUsers = 0;
	Visible = 0;

	update = 1;
}

LocationRecord & LocationRecord::operator=(LocationRecord& x)
{
	LocationId = x.LocationId;
	LocationName = x.LocationName;
	ParentId = x.ParentId;
	Wireless = x.Wireless;
	nEvents = x.nEvents;
	nUsers = x.nUsers;
	Visible = x.Visible;

	return *this;
}


void GroupRecord::SetDefault()
{
	GroupId = NullGroupId;
	GroupName = L"Unknown";
	Description = L"";
	Idle = 1;
	IdleSince = COleDateTime::GetCurrentTime();
	LocationId = NullLocationId;
	OwnerId = NullUserId;
	PublicEdit = 0;
	PublicView = 1;

	update = 1;
}

GroupRecord & GroupRecord::operator=(GroupRecord& x)
{
	GroupId = x.GroupId;
	GroupName = x.GroupName;
	Description = x.Description;
	Idle = x.Idle;
	IdleSince = x.IdleSince;
	LocationId = x.LocationId;
	OwnerId = x.OwnerId;
	PublicEdit = x.PublicEdit;
	PublicView = x.PublicView;

	return *this;
}


void EventRecord::SetDefault()
{
	EventId = NullEventId;
	EventName = L"Unknown";
	StartTime = COleDateTime::GetCurrentTime();
	EndTime = COleDateTime::GetCurrentTime();
	Eternal = 0;
	Description = L"";
	CreatedTime = COleDateTime::GetCurrentTime();
	OwnerId = NullUserId;
	LocationId = NullLocationId;
	OtherLocation = L"";
	GroupId = NullGroupId;
	Private = 0;
	CategoryId = NullCategoryId;
	Keywords = L"";

	update = 1;
}

EventRecord & EventRecord::operator=(EventRecord& x)
{
	EventId = x.EventId;
	EventName = x.EventName;
	StartTime = x.StartTime;
	EndTime = x.EndTime;
	Eternal = x.Eternal;
	Description = x.Description;
	CreatedTime = x.CreatedTime;
	OwnerId = x.OwnerId;
	LocationId = x.LocationId;
	OtherLocation = x.OtherLocation;
	GroupId = x.GroupId;
	Private = x.Private;
	CategoryId = x.CategoryId;
	Keywords = x.Keywords;

	return *this;
}

void EventPermissionRecord::SetDefault()
{
	CanEdit = 0;
	CanView = 0;

	update = 1;
}

EventPermissionRecord & EventPermissionRecord::operator=(EventPermissionRecord& x)
{
	CanEdit = x.CanEdit;
	CanView = x.CanView;

	return *this;
}

void EventSubscriptionRecord::SetDefault()
{
	TrackingStart = COleDateTime::GetCurrentTime();
	TrackingEnd = COleDateTime::GetCurrentTime();
	Eternal = 0;

	update = 1;
}

EventSubscriptionRecord & EventSubscriptionRecord::operator=(EventSubscriptionRecord& x)
{
	TrackingStart = x.TrackingStart;
	TrackingEnd = x.TrackingEnd;
	Eternal = x.Eternal;

	return *this;
}

void EventCategoryRecord::SetDefault()
{
	CategoryId = NullCategoryId;
	Category = L"Unknown";

	update = 1;
}

EventCategoryRecord & EventCategoryRecord::operator=(EventCategoryRecord& x)
{
	CategoryId = x.CategoryId;
	Category = x.Category;

	return *this;
}

void YearRecord::SetDefault()
{
	YearId = NullYearId;
	DegreeYear = L"Unknown";
	
	update = 1;
}

YearRecord & YearRecord::operator=(YearRecord& x)
{
	YearId = x.YearId;
	DegreeYear = x.DegreeYear;

	return *this;
}


void VersionRecord::SetDefault()
{
	Build = 1;
	URL = L"none";
	ShowURL = 0;
	AllowLogin = 1;
	
	update = 1;
}

VersionRecord & VersionRecord::operator=(VersionRecord& x)
{
	Build = x.Build;
	URL = x.URL;
	ShowURL = x.ShowURL;
	AllowLogin = x.AllowLogin;

	return *this;
}
/////////////////////////////////
// Each stored procedure is executed in a separate thread
// while the calling thread waits and processes windows messages
typedef struct _ESPInfo {
	_CommandPtr pCom;
	_RecordsetPtr pRps;
	HANDLE finished;
	HRESULT hr;
	IErrorInfo * perrinfo;
} ESPInfo;

static DWORD WINAPI ThreadEntry(LPVOID p)
{
	ESPInfo * pInfo = (ESPInfo *)p;
	try {
		pInfo->pRps = pInfo->pCom->Execute(NULL,NULL,adCmdStoredProc);
		pInfo->hr = S_OK;
		SetEvent(pInfo->finished);
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB exception in stored procedure.\n");
		pInfo->hr = x.Error();
		pInfo->perrinfo = x.ErrorInfo();
		SetEvent(pInfo->finished);
		return dbException;
	}

}

_RecordsetPtr BridgeDB::ExecuteWithRetry(_CommandPtr & pCom) throw(...)
{
	try {
		// first just execute the stored procedure
		//BSTR tmp;
		//pCom->get_CommandText(&tmp);
		//print(L"execute with retry: %s\n",(TCHAR *)tmp);
		return pCom->Execute(NULL,NULL,adCmdStoredProc);
	} catch (_com_error & x) {
		BSTR tmp;
		pCom->get_CommandText(&tmp);
		print(L"BridgeDB exception in: %s\n\tError: %s\n\tDescription: %s\n",(TCHAR*)tmp,(TCHAR*)x.ErrorMessage(), (TCHAR*)x.Description());
		// if there is an error than try reconnecting
		if(Reconnect()){
			try {
				// successfully reconnected, so execute again
				print(L"Trying to execute stored procedure again...\n");
				return pCom->Execute(NULL,NULL,adCmdStoredProc);
			} catch (_com_error & x) {
				BSTR tmp;
				pCom->get_CommandText(&tmp);
				// failed again, so stop trying
				print(L"2nd try: BridgeDB exception in: %s\n\tError: %s\n\tDescription: %s\n",(TCHAR*)tmp,(TCHAR*)x.ErrorMessage(), (TCHAR*)x.Description());
				throw _com_error(x.Error(), x.ErrorInfo());
				return dbException;
			}
		} else {
			print(L"BridgeDB::Reconnect: unable to reconnect.\n");
			throw _com_error(x.Error(), x.ErrorInfo());
			return dbException;
		}
		return dbException;
	}
}

#ifndef THREADED_SQL_CALLS
//#define ExecuteStoredProcedure(pCom) pCom->Execute(NULL,NULL,adCmdStoredProc)
#define ExecuteStoredProcedure(pCom) ExecuteWithRetry(pCom)
#else
static _RecordsetPtr ExecuteStoredProcedure(_CommandPtr & pCom) throw(...)
{
	ESPInfo * pInfo = new ESPInfo;
	pInfo->pCom = pCom;
	pInfo->finished = CreateEvent(NULL,TRUE,FALSE,NULL);
	CreateThread(NULL,0,ThreadEntry,pInfo,0,NULL);
	DoEventsUntil(&(pInfo->finished),1);
	_RecordsetPtr pRps = pInfo->pRps;
	CloseHandle(pInfo->finished);
	if(pInfo->hr==S_OK){
		delete pInfo;
		return pRps;
	} else {
		throw _com_error(pInfo->hr, pInfo->perrinfo);
		delete pInfo;
		return pRps;
	}
}
#endif

/////////////////////////////////

BridgeDB::BridgeDB()
{
	connected = 0;
	ConnectionTimeout = 15;
	CommandTimeout = 5;
    InitializeCriticalSection(&uCS); 
	InitializeCriticalSection(&gCS); 
	InitializeCriticalSection(&lCS); 
	InitializeCriticalSection(&eCS); 
	InitializeCriticalSection(&ecCS); 
	InitializeCriticalSection(&yCS); 
}

BridgeDB::~BridgeDB()
{
	Disconnect();
    DeleteCriticalSection(&uCS); 
	DeleteCriticalSection(&gCS); 
	DeleteCriticalSection(&lCS); 
	DeleteCriticalSection(&eCS); 
	DeleteCriticalSection(&ecCS); 
	DeleteCriticalSection(&yCS); 
}

/////////////////////////////////

void BridgeDB::ClearCache()
{
	{
		EnterCriticalSection(&uCS);
		std::list<UserRecord *>::iterator i;
		for(i=users.begin();i!=users.end();i++)
			delete *i;
		users.clear();
		LeaveCriticalSection(&uCS);
	}
	{
		EnterCriticalSection(&gCS);
		std::list<GroupRecord *>::iterator i;
		for(i=groups.begin();i!=groups.end();i++)
			delete *i;
		groups.clear();
		LeaveCriticalSection(&gCS);
	}
	{
		EnterCriticalSection(&eCS);
		std::list<EventRecord *>::iterator i;
		for(i=events.begin();i!=events.end();i++)
			delete *i;
		events.clear();
		LeaveCriticalSection(&eCS);
	}
	{
		EnterCriticalSection(&lCS);
		std::list<LocationRecord *>::iterator i;
		for(i=locations.begin();i!=locations.end();i++)
			delete *i;
		locations.clear();
		LeaveCriticalSection(&lCS);
	}
	{
		EnterCriticalSection(&ecCS);
		std::list<EventCategoryRecord *>::iterator i;
		for(i=eventcategories.begin();i!=eventcategories.end();i++)
			delete *i;
		eventcategories.clear();
		LeaveCriticalSection(&ecCS);
	}
	{
		EnterCriticalSection(&yCS);
		years.deallocate();
		LeaveCriticalSection(&yCS);
	}
}

UserRecord * BridgeDB::CachedUser(int userId)
{
	std::list<UserRecord *>::iterator i;
	UserRecord * r = NULL;

	EnterCriticalSection(&uCS);

	for(i=users.begin();i!=users.end();i++){
		r = *i;
		if(r->UserId==userId){
			LeaveCriticalSection(&uCS);
			return r;
		}
	}

	LeaveCriticalSection(&uCS);
	return NULL;
}

LocationRecord * BridgeDB::CachedLocation(int locationId)
{
	std::list<LocationRecord *>::iterator i;
	LocationRecord * r = NULL;

	EnterCriticalSection(&lCS);

	for(i=locations.begin();i!=locations.end();i++){
		r = *i;
		if(r->LocationId==locationId){
			LeaveCriticalSection(&lCS);
			return r;
		}
	}

	LeaveCriticalSection(&lCS);
	return NULL;
}

GroupRecord * BridgeDB::CachedGroup(int groupId)
{
	std::list<GroupRecord *>::iterator i;
	GroupRecord * r = NULL;

	EnterCriticalSection(&gCS);

	for(i=groups.begin();i!=groups.end();i++){
		r = *i;
		if(r->GroupId==groupId){
			LeaveCriticalSection(&gCS);
			return r;
		}
	}

	LeaveCriticalSection(&gCS);
	return NULL;
}

EventRecord * BridgeDB::CachedEvent(int eventId)
{
	std::list<EventRecord *>::iterator i;
	EventRecord * r = NULL;

	EnterCriticalSection(&eCS);

	for(i=events.begin();i!=events.end();i++){
		r = *i;
		if(r->EventId==eventId){
			LeaveCriticalSection(&eCS);
			return r;
		}
	}

	LeaveCriticalSection(&eCS);
	return NULL;
}

EventCategoryRecord * BridgeDB::CachedEventCategory(int categoryId)
{
	std::list<EventCategoryRecord *>::iterator i;
	EventCategoryRecord * r = NULL;

	EnterCriticalSection(&ecCS);

	for(i=eventcategories.begin();i!=eventcategories.end();i++){
		r = *i;
		if(r->CategoryId==categoryId){
			LeaveCriticalSection(&ecCS);
			return r;
		}
	}

	LeaveCriticalSection(&ecCS);
	return NULL;
}

void BridgeDB::DeleteCachedUser(int userId)
{
	std::list<UserRecord *>::iterator i;
	UserRecord * r = NULL;

	EnterCriticalSection(&uCS);

	for(i=users.begin();i!=users.end();i++){
		r = *i;
		if(r->UserId==userId){
			users.erase(i);
			break;
		}
	}

	LeaveCriticalSection(&uCS);
}

void BridgeDB::DeleteCachedLocation(int locationId)
{
	std::list<LocationRecord *>::iterator i;
	LocationRecord * r = NULL;

	EnterCriticalSection(&lCS);

	for(i=locations.begin();i!=locations.end();i++){
		r = *i;
		if(r->LocationId==locationId){
			locations.erase(i);
			break;
		}
	}

	LeaveCriticalSection(&lCS);
}

void BridgeDB::DeleteCachedGroup(int groupId)
{
	std::list<GroupRecord *>::iterator i;
	GroupRecord * r = NULL;

	EnterCriticalSection(&gCS);

	for(i=groups.begin();i!=groups.end();i++){
		r = *i;
		if(r->GroupId==groupId){
			groups.erase(i);
			break;
		}
	}

	LeaveCriticalSection(&gCS);
}

void BridgeDB::DeleteCachedEvent(int eventId)
{
	std::list<EventRecord *>::iterator i;
	EventRecord * r = NULL;

	EnterCriticalSection(&eCS);

	for(i=events.begin();i!=events.end();i++){
		r = *i;
		if(r->EventId==eventId){
			events.erase(i);
			break;
		}
	}

	LeaveCriticalSection(&eCS);
}

void BridgeDB::DeleteCachedEventCategory(int categoryId)
{
	std::list<EventCategoryRecord *>::iterator i;
	EventCategoryRecord * r = NULL;

	EnterCriticalSection(&ecCS);

	for(i=eventcategories.begin();i!=eventcategories.end();i++){
		r = *i;
		if(r->CategoryId==categoryId){
			eventcategories.erase(i);
			break;
		}
	}

	LeaveCriticalSection(&ecCS);
}

int BridgeDB::GetCachedUser(int userId, UserRecord & record, int update)
{
	if(userId==NullUserId){
		record.SetDefault();
		return dbInvalidParam;
	}

	UserRecord * r = CachedUser(userId);

	// its not in the cache so get it from the db
	if(r==NULL){
		r = new UserRecord;
		users.push_back(r);
		update = 1;
	}

	int result = dbSuccess;
	if(update || r->update){
		result = GetUser(userId,*r);
		if(result==dbSuccess)
			r->update = 0;
	}

	record = *r;

	return result;
}

int BridgeDB::GetCachedUserState(int userId, UserRecord & record, int update)
{
	if(userId==NullUserId){
		record.SetDefault();
		return dbInvalidParam;
	}

	UserRecord * r = CachedUser(userId);

	// its not in the cache so get it from the db
	if(r==NULL){
		r = new UserRecord;
		users.push_back(r);
		update = 1;
	}

	int result = dbSuccess;
	if(update || r->update){
		if(r->UserId==NullUserId){
			result = GetUser(userId,*r);
		} else {
			result = GetUserState(userId,*r);
		}

		if(result==dbSuccess)
			r->update = 0;
	}

	record = *r;

	return result;
}

int BridgeDB::GetCachedUsername(int userId, std::wstring & username, int update)
{
	if(userId==NullUserId){
		username = L"unknown";
		return dbInvalidParam;
	}

	UserRecord * r = CachedUser(userId);

	// its not in the cache so get it from the db
	// we don't create a record in the cache, let GetCachedUser do that
	if(r==NULL || update){
		return GetUsername(userId,username);
	} else {
		username = r->UserLogin;
		return dbSuccess;
	}
}

int BridgeDB::GetCachedGroup(int groupId, GroupRecord & record, int update)
{
	if(groupId==NullGroupId){
		record.SetDefault();
		return dbInvalidParam;
	}

	GroupRecord * r = CachedGroup(groupId);

	// its not in the cache so get it from the db
	if(r==NULL){
		r = new GroupRecord;
		groups.push_back(r);
		update = 1;
	}

	int result = dbSuccess;
	if(update || r->update){
		result = GetGroup(groupId,*r);
		if(result==dbSuccess)
			r->update = 0;
	}

	record = *r;

	return result;
}

int BridgeDB::GetCachedEvent(int eventId, EventRecord & record, int update)
{
	if(eventId==NullEventId){
		record.SetDefault();
		return dbInvalidParam;
	}

	EventRecord * r = CachedEvent(eventId);

	// its not in the cache so get it from the db
	if(r==NULL){
		r = new EventRecord;
		events.push_back(r);
		update = 1;
	}

	// if we need to update from the db 
	int result = dbSuccess;
	if(update || r->update){
		result = GetEvent(eventId,*r);
		if(result==dbSuccess)
			r->update = 0;
	}

	// finally copy into the given record
	record = *r;

	return result;
}

int BridgeDB::GetCachedLocation(int locationId, LocationRecord & record, int update)
{
	if(locationId==NullLocationId){
		record.SetDefault();
		return dbInvalidParam;
	}

	LocationRecord * r = CachedLocation(locationId);

	// its not in the cache so get it from the db
	if(r==NULL){
		r = new LocationRecord;
		locations.push_back(r);
		update = 1;
	}

	// if we need to update from the db 
	int result = dbSuccess;
	if(update || r->update){
		result = GetLocation(locationId,*r);
		if(result==dbSuccess)
			r->update = 0;
	}

	// finally copy into the given record
	record = *r;

	return result;
}

int BridgeDB::GetCachedEventCategory(int categoryId, EventCategoryRecord & record, int update)
{
	if(categoryId==NullCategoryId){
		record.SetDefault();
		return dbInvalidParam;
	}

	EventCategoryRecord * r = CachedEventCategory(categoryId);

	// its not in the cache so get it from the db
	if(r==NULL){
		r = new EventCategoryRecord;
		eventcategories.push_back(r);
		update = 1;
	}

	// if we need to update from the db 
	int result = dbSuccess;
	if(update || r->update){
		result = GetEventCategory(categoryId,*r);
		if(result==dbSuccess)
			r->update = 0;
	}

	// finally copy into the given record
	record = *r;

	return result;
}

int BridgeDB::GetCachedYears(Vector<YearRecord>& y, int update)
{
	int result = dbSuccess;
	if(update || years.length==0){
		result = GetYears(years);
	}

	y = years;

	return result;
}

/////////////////////////////////




BOOL BridgeDB::Connect()
{
	// Log on to the SQL server
	std::wstring sqlserver, sqltable, sqluser, sqlpassword;
	sqlserver = env.GetWideString("sql","server",L"studiomit6.mit.edu");
	sqltable = env.GetWideString("sql","table",L"testBridge2");
	sqluser = env.GetWideString("sql","user",L"sa");
	sqlpassword = env.GetWideString("sql","password",L"Bridge2001");
	if(!Connect(sqlserver.data(),sqltable.data(),sqluser.data(),sqlpassword.data())){
		print(L"BridgeDB: Unable to open connection to SQL server %s( %s) as %s.\n",sqlserver.data(),sqltable.data(),sqluser.data());
		return 0;
	} else {
		print(L"BridgeDB: connected to SQL server %s (%s) as %s.\n",sqlserver.data(),sqltable.data(),sqluser.data());
		return dbSuccess;
	}
}


BOOL BridgeDB::Connect(const TCHAR * source, const TCHAR * table, const TCHAR * username, const TCHAR * password)
{
	if(FAILED(CoInitialize(NULL)))
		return FALSE;
		
	if (!connected) {

		try {
			TCHAR buffer[1024];
			_stprintf(buffer,L"Provider=sqloledb;Data Source=%s;Initial Catalog=%s;",source,table);
			connection.CreateInstance(__uuidof(Connection));
			connection->ConnectionString = buffer;
			connection->CursorLocation = adUseClient;
			connection->put_ConnectionTimeout(ConnectionTimeout);
			connection->put_CommandTimeout(CommandTimeout);
			if(connection->Open(buffer, username, password, NULL)==S_OK)
				connected = 1;
			else 
				connected = 0;

			ClearCache();

		} catch (_com_error & x) {
			print(L"BridgeDB::Connect Exception: %s\n",x.ErrorMessage());
		}
	}
	
	return connected;
}

_ConnectionPtr BridgeDB::GetConnection() throw(...)
{
	try {
		if(connected)
			return connection;
		else if(Reconnect())
			return connection;
		else
			return 0;
	} catch (_com_error & x) {
		print(L"BridgeDB: Unable to get a connection.\n\tError: %s\n\tDescription%s\n",(TCHAR*)x.ErrorMessage(), (TCHAR*)x.Description());
		throw _com_error(x.Error(), x.ErrorInfo());
		return 0;
	}
}

void BridgeDB::Disconnect()
{
	if(connected)
		connection->Close();
	connected = 0;
}

void BridgeDB::LoseConnection()
{
	connected = 0;
}

int BridgeDB::Reconnect()
{
	LoseConnection();
	return Connect();
}

int BridgeDB::Authenticate(int userId, const TCHAR * password, int & authenticated)
{
	std::wstring passwordDB;
	int result = GetPassword(userId,passwordDB);

	print(L"password = %s, passwordDB = %s\n",password,passwordDB.data());

	if(result==dbSuccess)
		authenticated = passwordDB==password;

	return result;
}

int BridgeDB::UserExist(int userId, int & exists)
{
	std::wstring username;
	int result = GetUsername(userId,username);

	if(result==dbSuccess)
		exists = username!=L"unknown";

	return result;
}

int BridgeDB::GetUserId(const TCHAR * username, int & userId)
{
	try {
		_CommandPtr pCom = NULL;
		
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetUserId";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(pCom->CreateParameter("UserLogin", adBSTR, adParamInput, _tcslen(username), username));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		if(pRps->GetRecordCount()>0){
			userId = pRps->Fields->GetItem("UserId")->GetValue().iVal;
			return dbSuccess;
		} else {
			userId = NullUserId;
			return dbInvalidParam;
		}
	} catch (_com_error & x) {
		print(L" BridgeDB::GetUserId Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::EventIsPrivate(int eventId, int & isprivate)
{
	// an unknown event is private

	try {
		_CommandPtr pCom = NULL;
		
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "EventIsPrivate";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), eventId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		if(pRps->GetRecordCount()>0){
			isprivate = pRps->Fields->GetItem("Private")->GetValue().iVal;
			return dbSuccess;
		} else {
			isprivate = 1; // default value
			return dbInvalidParam;
		}

	} catch (_com_error & x) {
		print(L" BridgeDB::GetUserId Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetGroupId(const TCHAR * groupname, int & groupId)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetGroupId";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(pCom->CreateParameter("GroupName", adBSTR, adParamInput, _tcslen(groupname), groupname));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		if(pRps->GetRecordCount()>0){
			groupId = pRps->Fields->GetItem("GroupId")->GetValue().iVal;
			return dbSuccess;
		} else {
			groupId = NullGroupId;
			return dbInvalidParam;
		}

	} catch (_com_error & x) {
		print(L"BridgeDB::GetGroupId Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetEventId(const TCHAR * eventname, int & eventId)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetEventId";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(pCom->CreateParameter("EventName", adBSTR, adParamInput, _tcslen(eventname), eventname));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		if(pRps->GetRecordCount()>0) {
			eventId = pRps->Fields->GetItem("EventId")->GetValue().iVal;
			return dbSuccess;
		} else {
			eventId = NullEventId;
			return dbInvalidParam;
		}

	} catch (_com_error & x) {
		print(L"BridgeDB::GetEventId Exception: %s\n",x.ErrorMessage());
		return dbSuccess;
	}

}

int BridgeDB::GetPassword(int userId, std::wstring & password) 
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetPassword";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		if(pRps->RecordCount==0)
			return dbInvalidParam;
		else {
			password = pRps->Fields->GetItem("Password")->GetValue().bstrVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetPassword Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetUsername(int userId, std::wstring & username) 
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetUsername";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		if(pRps->RecordCount==0)
			return dbInvalidParam;
		else {
			username = pRps->Fields->GetItem("UserLogin")->GetValue().bstrVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetUsername Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetYear(int yearId, std::wstring & year) 
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetYear";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(pCom->CreateParameter("YearId", adInteger, adParamInput, sizeof(int), yearId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		if(pRps->RecordCount==0)
			return dbInvalidParam;
		else {
			year = pRps->Fields->GetItem("DegreeYear")->GetValue().bstrVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetYear Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}


int BridgeDB::AddLocationSignature(int locationId, int SignalStrength, int Mac1, int Mac2)
{
	try {
		_CommandPtr pCom = NULL;
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "AddLocationSignature";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), locationId));
		pCom->Parameters->Append(
			pCom->CreateParameter("SignalStrength", adInteger, adParamInput, sizeof(int), SignalStrength));
		pCom->Parameters->Append(
			pCom->CreateParameter("MacAddress1", adInteger, adParamInput, sizeof(int), Mac1));
		pCom->Parameters->Append(
			pCom->CreateParameter("MacAddress2", adInteger, adParamInput, sizeof(int), Mac2));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::AddLocationSignature Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::EstimateLocation(int Mac1, int Mac2, unsigned int signalstrength, int & locationId) 
{
	if(!connected) 
		return dbInvalidParam;
	if (Mac1== 0) {
		locationId = NullLocationId;
		return dbSuccess;
	}
      
	// perform a lookup in the DB for a closest match
	try {
		_CommandPtr pCom = NULL;
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "EstimateLocation";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("Mac1", adInteger, adParamInput, sizeof(int), Mac1));
		pCom->Parameters->Append(
			pCom->CreateParameter("Mac2", adInteger, adParamInput, sizeof(int), Mac2));
		pCom->Parameters->Append(
			pCom->CreateParameter("strength", adInteger, adParamInput, sizeof(int), signalstrength));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);

		if(pRps->GetRecordCount()==0){
			locationId = NullLocationId;
			return dbSuccess;
		}

		locationId = pRps->Fields->GetItem("LocationId")->Value.iVal;
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::EstimateLocation Exception: %s\n",x.ErrorMessage());
		return dbInvalidParam;
	}

}

int BridgeDB::SetUserLogin(int userId, int loggedin)
{
	VARIANT vtID;
	vtID.vt = VT_UI4;
	vtID.uintVal = userId;
	VARIANT vtLoggedIn;
	vtLoggedIn.vt = VT_BOOL;
	vtLoggedIn.boolVal = loggedin;

	UserRecord * r = CachedUser(userId);
	if(r){
		r->LoggedIn = loggedin;
		r->LoggedInSince = COleDateTime::GetCurrentTime();
	}

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetUserLogin";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("LoggedIn", adBoolean, adParamInput, sizeof(int), vtLoggedIn));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetUserLogin Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::SetPassword(int userId, const TCHAR * password)
{

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetUserPassword";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("Password", adBSTR, adParamInput, _tcslen(password), password));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetPassword Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::SetUserAway(int userId, int away, const TCHAR * msg)
{
	VARIANT vtAway;
	vtAway.vt = VT_BOOL;
	vtAway.boolVal = away;

	UserRecord * r = CachedUser(userId);
	if(r){
		r->Away = away;
		r->AwayMessage = msg;
	}

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetUserAway";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("Away", adBoolean, adParamInput, sizeof(int), vtAway));
		pCom->Parameters->Append(
			pCom->CreateParameter("AwayMessage", adBSTR, adParamInput, _tcslen(msg), msg));
		
		ExecuteStoredProcedure(pCom);	

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetUserAway Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::SetUserPrivacyLevel(int userId, int privacy)
{
	UserRecord * r = CachedUser(userId);
	if(r){
		r->PrivacyLevel = privacy;
	}

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetUserPrivacyLevel";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("PrivacyLevel", adBoolean, adParamInput, sizeof(int), privacy));
		
		ExecuteStoredProcedure(pCom);	

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetUserPrivacyLevel Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::SetUserIdle(int userId, int idle, int secs)
{

	UserRecord * r = CachedUser(userId);
	if(r){
		r->Idle = idle;
		COleDateTime dt = COleDateTime::GetCurrentTime();
		dt -= COleDateTimeSpan(0,0,0,secs);
		r->IdleSince = dt;
	}

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetUserIdle";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("Idle", adBoolean, adParamInput, sizeof(int), idle));
		pCom->Parameters->Append(
			pCom->CreateParameter("Secs", adInteger, adParamInput, sizeof(int), -secs));

		ExecuteStoredProcedure(pCom);	

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetUserIdle Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::SetLocationEventCount(int locationId, int nEvents)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetLocationEventCount";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), locationId));
		pCom->Parameters->Append(
			pCom->CreateParameter("nEvents", adInteger, adParamInput, sizeof(int), nEvents));
		
		ExecuteStoredProcedure(pCom);	

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetLocationEventCount Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::SetGroupIdle(int groupId, int idle)
{
	VARIANT vtIdle;
	vtIdle.vt = VT_BOOL;
	vtIdle.boolVal = idle;
	
	GroupRecord * r = CachedGroup(groupId);
	if(r){
		r->Idle = idle;
		COleDateTime dt = COleDateTime::GetCurrentTime();
		r->IdleSince = dt;
	}

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetGroupIdle";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), groupId));
		pCom->Parameters->Append(
			pCom->CreateParameter("Idle", adBoolean, adParamInput, sizeof(int), vtIdle));
		
		ExecuteStoredProcedure(pCom);	

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetGroupIdle Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::EnterGroupMeeting(int userId, int groupId)
{
	GroupRecord * r = CachedGroup(groupId);
	if(r){
		r->update = 1;
	}

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "EnterGroupMeeting";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), groupId));
		
		ExecuteStoredProcedure(pCom);	

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::EnterGroupMeeting Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::LeaveGroupMeeting(int userId, int groupId)
{
	GroupRecord * r = CachedGroup(groupId);
	if(r){
		r->update = 1;
	}
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "LeaveGroupMeeting";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), groupId));
		
		ExecuteStoredProcedure(pCom);	

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::LeaveGroupMeeting Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::SetUserLocation(int userId, int locationId)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = locationId;

	UserRecord * r = CachedUser(userId);
	if(r){
		r->LocationId = locationId;
	}

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetUserLocation";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("Location", adInteger, adParamInput, sizeof(int), vtID));
		
		ExecuteStoredProcedure(pCom);	

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetUserLocation Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetUsersAtLocation(int locationId, Vector<int> & userIds) 
{

	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = locationId;

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetUsersAtLocation";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			// no users at this location
			userIds.deallocate();
			return dbSuccess;
		}

		userIds.allocate(n);

		for(i=0;i<n;i++){
			// Convert variant string to convertable string type.
			userIds[i] = pRps->Fields->GetItem("UserId")->Value.iVal;
			pRps->MoveNext();
		}

		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetUsersAtLocation Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetSubscribedLocations(int userId, Vector<int>& locationIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetSubscribedLocations";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i,n = pRps->GetRecordCount();
		if(n==0){
			locationIds.deallocate();
			return dbSuccess;
		}
		locationIds.allocate(n);
		for(i=0;i<n;i++){
			locationIds[i] = pRps->Fields->GetItem("LocationId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetSubscribedLocations Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetAllLocations(Vector<int>& locationIds, int build)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetAllLocations";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("Build", adInteger, adParamInput, sizeof(int), build));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			locationIds.deallocate();
			return dbSuccess;
		}
		locationIds.allocate(n);
		for(i=0;i<n;i++){
			locationIds[i] = pRps->Fields->GetItem("LocationId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetAllLocations Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetVisibleLocations(Vector<int>& locationIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetVisibleLocations";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			locationIds.deallocate();
			return dbSuccess;
		}
		locationIds.allocate(n);
		for(i=0;i<n;i++){
			locationIds[i] = pRps->Fields->GetItem("LocationId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetVisibleLocations Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetSubscribedEvents(int userId, Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetSubscribedEvents";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetSubscribedEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetTrackedEvents(int userId, Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetTrackedEvents";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetActiveSubscribedEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetActiveSubscribedPublicEvents(int userId, Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetActiveSubscribedPublicEvents";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetActiveSubscribedPublicEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}


int BridgeDB::GetActiveGroupEvents(int groupId, Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetActiveGroupEvents";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), groupId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetActiveGroupEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}

}

int BridgeDB::GetEventsByLocation(int locationId, Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetEventsByLocation";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), locationId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetEventsByLocation Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetActiveEventsByLocation(int locationId, Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetActiveEventsByLocation";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), locationId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetActiveEventsByLocation Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetPublicEvents(Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetPublicEvents";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetPublicEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetPrivateEvents(int userId, Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetPrivateEvents";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));

		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetPrivateEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetSubscribableEvents(int userId, Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetSubscribableEvents";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));

		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetSubscribableEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetSubscribableGroups(int userId, Vector<int>& groupIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetSubscribableGroups";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));

		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			groupIds.deallocate();
			return dbSuccess;
		}
		groupIds.allocate(n);
		for(i=0;i<n;i++){
			groupIds[i] = pRps->Fields->GetItem("GroupId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetSubscribableGroups Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}


int BridgeDB::GetAllEvents(Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetAllEvents";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetAllEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetAllActiveEvents(Vector<int>& eventIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetAllActiveEvents";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			eventIds.deallocate();
			return dbSuccess;
		}
		eventIds.allocate(n);
		for(i=0;i<n;i++){
			eventIds[i] = pRps->Fields->GetItem("EventId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetAllActiveEvents Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetAllEventCategories(Vector<int>& categoryIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetAllEventCategories";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			categoryIds.deallocate();
			return dbSuccess;
		}
		categoryIds.allocate(n);
		for(i=0;i<n;i++){
			categoryIds[i] = pRps->Fields->GetItem("CategoryId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetAllEventCategories Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetEventCategory(int categoryId, EventCategoryRecord& record)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = categoryId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetEventCategory";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("CategoryId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if ((pRps->EndOfFile)){
			record.SetDefault();
			return dbInvalidParam;
		} else {
			record.CategoryId = categoryId;
			record.Category = pRps->Fields->GetItem("Category")->Value.bstrVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetEventCategory Exception: %s\n",x.ErrorMessage());
		record.SetDefault();
		return dbException;
	}
}

int BridgeDB::GetSubscribedGroups(int userId, Vector<int>& groupIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetSubscribedGroups";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			groupIds.deallocate();
			return dbSuccess;
		}
		groupIds.allocate(n);
		for(i=0;i<n;i++){
			groupIds[i] = pRps->Fields->GetItem("GroupId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetSubscribedGroups Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetActiveSubscribedGroups(int userId, Vector<int>& groupIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetActiveSubscribedGroups";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			groupIds.deallocate();
			return dbSuccess;
		}
		groupIds.allocate(n);
		for(i=0;i<n;i++){
			groupIds[i] = pRps->Fields->GetItem("GroupId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetActiveSubscribedGroups Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetAllGroups(Vector<int>& groupIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetAllGroups";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			groupIds.deallocate();
			return dbSuccess;
		}
		groupIds.allocate(n);
		for(i=0;i<n;i++){
			groupIds[i] = pRps->Fields->GetItem("GroupId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetAllGroups Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetYears(Vector<YearRecord>& years)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetYears";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			years.deallocate();
			return dbSuccess;
		}
		years.allocate(n);
		for(i=0;i<n;i++){
			years[i].YearId = pRps->Fields->GetItem("YearId")->Value.iVal;
			years[i].DegreeYear = pRps->Fields->GetItem("DegreeYear")->Value.bstrVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetYears Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetAllUsers(Vector<int>& userIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetAllUsers";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			userIds.deallocate();
			return dbSuccess;
		}
		userIds.allocate(n);
		for(i=0;i<n;i++){
			userIds[i] = pRps->Fields->GetItem("UserId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetAllUsers Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetOnlineUsers(Vector<int>& userIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetOnlineUsers";
		pCom->CommandType = adCmdStoredProc;
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			userIds.deallocate();
			return dbSuccess;
		}
		userIds.allocate(n);
		for(i=0;i<n;i++){
			userIds[i] = pRps->Fields->GetItem("UserId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetOnlineUsers Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetOnlineBuddyList(int userId, Vector<int>& buddies)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetOnlineBuddyList";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			buddies.deallocate();
			return dbSuccess;
		}
		buddies.allocate(n);
		for(i=0;i<n;i++){
			buddies[i] = pRps->Fields->GetItem("BuddyId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetOnlineBuddyList Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetUsersThatWatchMe(int buddyId, Vector<int>& userIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetUsersThatWatchMe";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("BuddyId", adInteger, adParamInput, sizeof(int), buddyId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			userIds.deallocate();
			return dbSuccess;
		}
		userIds.allocate(n);
		for(i=0;i<n;i++){
			userIds[i] = pRps->Fields->GetItem("UserId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetUsersThatWatchMe Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetBuddyList(int userId, Vector<int>& buddyIds)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetBuddyList";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			buddyIds.deallocate();
			return dbSuccess;
		}
		buddyIds.allocate(n);
		for(i=0;i<n;i++){
			buddyIds[i] = pRps->Fields->GetItem("BuddyId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetBuddyList Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetGroupMembers(int groupId, Vector<int>& userIds)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = groupId;

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetGroupMembers";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			userIds.deallocate();
			return dbSuccess;
		}
		userIds.allocate(n);
		for(i=0;i<n;i++){
			userIds[i] = pRps->Fields->GetItem("MemberId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetGroupMembers Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetAttendingGroupMembers(int groupId, Vector<int>& userIds)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = groupId;

	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetAttendingGroupMembers";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n==0){
			userIds.deallocate();
			return dbSuccess;
		}
		userIds.allocate(n);
		for(i=0;i<n;i++){
			userIds[i] = pRps->Fields->GetItem("MemberId")->Value.iVal;
			pRps->MoveNext();
		}
		pRps->Close();
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetAttendingGroupMembers Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetEventMembers(int eventId, Vector<int>& userIds)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = eventId;

	try {

		// first get the users directly subscribed to the event
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetEventMembers";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n>0){
			userIds.allocate(n);
			for(i=0;i<n;i++){
				userIds[i] = pRps->Fields->GetItem("UserId")->Value.iVal;
				pRps->MoveNext();
			}
			pRps->Close();
		} else
			userIds.deallocate();

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetEventMembers Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::GetEventCanViews(int eventId, Vector<int>& userIds)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = eventId;

	try {

		// first get the users directly subscribed to the event
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetEventCanViews";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		int i, n = pRps->GetRecordCount();
		if(n>0){
			userIds.allocate(n);
			for(i=0;i<n;i++){
				userIds[i] = pRps->Fields->GetItem("UserId")->Value.iVal;
				pRps->MoveNext();
			}
			pRps->Close();
		} else
			userIds.deallocate();

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::GetEventCanViews Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::AddToBuddyList(int userId, int buddyId)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "AddToBuddyList";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("BuddyId", adInteger, adParamInput, sizeof(int), buddyId));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::AddToBuddyList Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
		
}

int BridgeDB::SubscribeToLocation(int userId, int locationId)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = locationId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SubscribeToLocation";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), vtID));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SubscribeToLocation Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
		
}

int BridgeDB::SubscribeToEvent(int userId, int eventId, DATE& TrackingStart, DATE& TrackingEnd, int Eternal)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = eventId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SubscribeToEvent";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), vtID));
		pCom->Parameters->Append(
			pCom->CreateParameter("TrackingStart", adDate, adParamInput, sizeof(DATE), TrackingStart));
		pCom->Parameters->Append(
			pCom->CreateParameter("TrackingEnd", adDate, adParamInput, sizeof(DATE), TrackingEnd));
		pCom->Parameters->Append(
			pCom->CreateParameter("Eternal", adInteger, adParamInput, sizeof(int), Eternal));

		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SubscribeToEvent Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}

int BridgeDB::SetEventPermission(int userId, int eventId, int CanEdit, int CanView)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = eventId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SetEventPermission";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), vtID));
		pCom->Parameters->Append(
			pCom->CreateParameter("CanEdit", adInteger, adParamInput, sizeof(int), CanEdit));
		pCom->Parameters->Append(
			pCom->CreateParameter("CanView", adInteger, adParamInput, sizeof(int), CanView));

		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SetEventPermission Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}

int BridgeDB::SubscribeToGroup(int userId, int groupId)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = groupId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "SubscribeToGroup";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), vtID));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::SubscribeToGroup Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}

int BridgeDB::RemoveFromBuddyList(int userId, int buddyId)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "RemoveFromBuddyList";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("BuddyId",  adInteger, adParamInput, sizeof(int), buddyId));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::RemoveFromBuddyList Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}

int BridgeDB::UnsubscribeFromLocation(int userId, int locationId)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = locationId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "UnsubscribeFromLocation";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), vtID));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::UnsubscribeFromLocation Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}


int BridgeDB::UnsubscribeFromEvent(int userId, int eventId)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = eventId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "UnsubscribeFromEvent";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), vtID));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::UnsubscribeFromEvent Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}

int BridgeDB::DeleteEventPermission(int userId, int eventId)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = eventId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "DeleteEventPermission";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), vtID));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::DeleteEventPermission Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}

int BridgeDB::UnsubscribeGroupFromEvent(int groupId, int eventId)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = eventId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "UnsubscribeGroupFromEvent";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), groupId));
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), vtID));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::UnsubscribeGroupFromEvent Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}

int BridgeDB::UnsubscribeFromGroup(int userId, int groupId)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = groupId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "UnsubscribeFromGroup";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), vtID));
		
		ExecuteStoredProcedure(pCom);

		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::UnsubscribeFromGroup Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	
}

// access
int BridgeDB::GetUser(int userId, UserRecord & record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetUser";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if (!(pRps->EndOfFile)){
			record.UserId = pRps->Fields->GetItem("UserId")->Value.iVal;
			record.UserLogin = pRps->Fields->GetItem("UserLogin")->Value.bstrVal;
			record.Password = pRps->Fields->GetItem("Password")->Value.bstrVal;
			record.FirstName = pRps->Fields->GetItem("FirstName")->Value.bstrVal;
			record.LastName = pRps->Fields->GetItem("LastName")->Value.bstrVal;
			record.Email = pRps->Fields->GetItem("Email")->Value.bstrVal;
			record.YearId = pRps->Fields->GetItem("YearId")->Value.iVal;
			record.LoggedIn = pRps->Fields->GetItem("LoggedIn")->Value.iVal;
			record.LoggedInSince = pRps->Fields->GetItem("LoggedInSince")->Value.date;
			record.Idle = pRps->Fields->GetItem("Idle")->Value.iVal;
			record.IdleSince = pRps->Fields->GetItem("IdleSince")->Value.date;
			record.LocationId = pRps->Fields->GetItem("LocationId")->Value.iVal;
			record.LastLocationId = pRps->Fields->GetItem("LastLocationId")->Value.iVal;
			record.Away = pRps->Fields->GetItem("Away")->Value.iVal;
			record.AwayMessage = pRps->Fields->GetItem("AwayMessage")->Value.bstrVal;
			record.PrivacyLevel = pRps->Fields->GetItem("PrivacyLevel")->Value.iVal;
			record.SecretWeapon = pRps->Fields->GetItem("SecretWeapon")->Value.bstrVal;
			record.Interest = pRps->Fields->GetItem("Interest")->Value.bstrVal;
			record.Background = pRps->Fields->GetItem("Background")->Value.bstrVal;
			print(L"BridgeDB::GetUser %s\n",(TCHAR*)record.UserLogin);
			return dbSuccess;
		} else {
			record.SetDefault();
			return dbInvalidParam;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetUser Exception: %s\n",x.ErrorMessage());
		record.SetDefault();
		return dbException;
	}
}

// this is a more minimal version of GetUser
// only gets info about the user's location, idleness, awayness
int BridgeDB::GetUserState(int userId, UserRecord & record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetUserState";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GetUserState", adInteger, adParamInput, sizeof(int), userId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if ((pRps->EndOfFile)){
			return dbInvalidParam;
		} else {
			record.LoggedIn = pRps->Fields->GetItem("LoggedIn")->Value.iVal;
			record.LoggedInSince = pRps->Fields->GetItem("LoggedInSince")->Value.date;
			record.Idle = pRps->Fields->GetItem("Idle")->Value.iVal;
			record.IdleSince = pRps->Fields->GetItem("IdleSince")->Value.date;
			record.LocationId = pRps->Fields->GetItem("LocationId")->Value.iVal;
			record.LastLocationId = pRps->Fields->GetItem("LastLocationId")->Value.iVal;;
			record.Away = pRps->Fields->GetItem("Away")->Value.iVal;
			record.AwayMessage = pRps->Fields->GetItem("AwayMessage")->Value.bstrVal;
			record.PrivacyLevel = pRps->Fields->GetItem("PrivacyLevel")->Value.iVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetUser Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}


int BridgeDB::GetLocation(int locationId, LocationRecord& record)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = locationId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetLocation";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if ((pRps->EndOfFile)){
			record.SetDefault();
			return dbInvalidParam;
		} else {
			record.LocationId = locationId;
			record.LocationName = pRps->Fields->GetItem("LocationName")->Value.bstrVal;
			record.ParentId = pRps->Fields->GetItem("ParentId")->Value.iVal;
			record.nEvents = pRps->Fields->GetItem("nEvents")->Value.iVal;
			record.nUsers = pRps->Fields->GetItem("nUsers")->Value.iVal;
			record.Wireless = pRps->Fields->GetItem("Wireless")->Value.iVal;
			record.Visible = pRps->Fields->GetItem("Visible")->Value.iVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetLocation Exception: %s\n",x.ErrorMessage());
		record.SetDefault();
		return dbException;
	}
}

int BridgeDB::GetGroup(int groupId, GroupRecord& record)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = groupId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetGroup";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if ((pRps->EndOfFile)){
			record.SetDefault();
			return dbInvalidParam;
		} else {
			record.GroupId = groupId;
			record.GroupName = pRps->Fields->GetItem("GroupName")->Value.bstrVal;
			record.Description = pRps->Fields->GetItem("Description")->Value.bstrVal;
			record.OwnerId = pRps->Fields->GetItem("OwnerId")->Value.iVal;
			record.Idle = pRps->Fields->GetItem("Idle")->Value.iVal;
			record.IdleSince = pRps->Fields->GetItem("IdleSince")->Value.date;
			record.LocationId = pRps->Fields->GetItem("LocationId")->Value.iVal;
			record.PublicView = pRps->Fields->GetItem("PublicView")->Value.iVal;
			record.PublicEdit = pRps->Fields->GetItem("PublicEdit")->Value.iVal;
			print(L"BridgeDB::GetGroup %s\n",(TCHAR*)record.GroupName);
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetGroup Exception: %s\n",x.ErrorMessage());
		record.SetDefault();
		return dbException;
	}
}

int BridgeDB::GetEventPermission(int userId, int eventId, EventPermissionRecord& record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetEventPermission";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), eventId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if ((pRps->EndOfFile)){
			record.SetDefault();
			return dbInvalidParam;
		} else {
			record.CanEdit = pRps->Fields->GetItem("CanEdit")->Value.iVal;
			record.CanView = pRps->Fields->GetItem("CanView")->Value.iVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetEventPermission Exception: %s\n",x.ErrorMessage());
		record.SetDefault();
		return dbException;
	}
}

int BridgeDB::GetEventSubscription(int userId, int eventId, EventSubscriptionRecord& record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetEventSubscription";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), eventId));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if ((pRps->EndOfFile)){
			record.SetDefault();
			return dbInvalidParam;
		} else {
			record.TrackingStart = pRps->Fields->GetItem("TrackingStart")->Value.date;
			record.TrackingEnd = pRps->Fields->GetItem("TrackingEnd")->Value.date;
			record.Eternal = pRps->Fields->GetItem("Eternal")->Value.iVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetEventSubscription Exception: %s\n",x.ErrorMessage());
		record.SetDefault();
		return dbException;
	}
}

int BridgeDB::GetEvent(int eventId, EventRecord& record)
{
	VARIANT vtID;
	vtID.vt = VT_I4;
	vtID.lVal = eventId;
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetEvent";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), vtID));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if ((pRps->EndOfFile)){
			record.SetDefault();
			return dbInvalidParam;
		} else {
			record.EventId = eventId;
			record.EventName = pRps->Fields->GetItem("EventName")->Value.bstrVal;
			record.Description = pRps->Fields->GetItem("Description")->Value.bstrVal;
			record.OwnerId = pRps->Fields->GetItem("OwnerId")->Value.iVal;
			record.GroupId = pRps->Fields->GetItem("GroupId")->Value.iVal;
			record.LocationId = pRps->Fields->GetItem("LocationId")->Value.iVal;
			record.OtherLocation = pRps->Fields->GetItem("OtherLocation")->Value.bstrVal;
			record.CategoryId = pRps->Fields->GetItem("CategoryId")->Value.iVal;
			record.CreatedTime = pRps->Fields->GetItem("CreatedTime")->Value.date;
			record.StartTime = pRps->Fields->GetItem("StartTime")->Value.date;
			record.EndTime = pRps->Fields->GetItem("EndTime")->Value.date;
			record.Eternal = pRps->Fields->GetItem("Eternal")->Value.iVal;
			record.Private = pRps->Fields->GetItem("Private")->Value.iVal;
			record.Keywords = pRps->Fields->GetItem("Keywords")->Value.bstrVal;
			print(L"BridgeDB::GetEvent %s\n",(TCHAR*)record.EventName);
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetEvent Exception: %s\n",x.ErrorMessage());
		record.SetDefault();
		return dbException;
	}
}

int BridgeDB::GetVersionInfo(int build, VersionRecord& record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "GetVersionInfo";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("Build", adInteger, adParamInput, sizeof(int), build));
		
		_RecordsetPtr pRps = ExecuteStoredProcedure(pCom);
		
		if ((pRps->EndOfFile)){
			record.SetDefault();
			return dbInvalidParam;
		} else {
			record.Build = build;
			record.URL = pRps->Fields->GetItem("URL")->Value.bstrVal;
			record.ShowURL = pRps->Fields->GetItem("ShowURL")->Value.iVal;
			record.AllowLogin = pRps->Fields->GetItem("AllowLogin")->Value.iVal;
			return dbSuccess;
		}
	} catch (_com_error & x) {
		print(L"BridgeDB::GetVersionInfo Exception: %s\n",x.ErrorMessage());
		record.SetDefault();
		return dbException;
	}
}


// creation
int BridgeDB::CreateUser(UserRecord& record)
{
	try {
		_CommandPtr pCom = NULL;

	
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "CreateUser";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserLogin", adBSTR, adParamInput, record.UserLogin.length(), record.UserLogin));
		pCom->Parameters->Append(
			pCom->CreateParameter("Password", adBSTR, adParamInput, record.Password.length(), record.Password));
		pCom->Parameters->Append(
			pCom->CreateParameter("FirstName", adBSTR, adParamInput, record.FirstName.length(), record.FirstName));
		pCom->Parameters->Append(
			pCom->CreateParameter("LastName", adBSTR, adParamInput, record.LastName.length(), record.LastName));
		pCom->Parameters->Append(
			pCom->CreateParameter("Email", adBSTR, adParamInput, record.Email.length(), record.Email));
		pCom->Parameters->Append(
			pCom->CreateParameter("YearId", adInteger, adParamInput, sizeof(int), record.YearId));
		pCom->Parameters->Append(
			pCom->CreateParameter("SecretWeapon", adBSTR, adParamInput, record.SecretWeapon.length(), record.SecretWeapon));
		pCom->Parameters->Append(
			pCom->CreateParameter("Interest", adBSTR, adParamInput, record.Interest.length(), record.Interest));
		ExecuteStoredProcedure(pCom);	

	} catch (_com_error & x) {
		print(L"BridgeDB::CreateUser Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	int result = GetUserId(record.UserLogin, record.UserId);
	if(result==dbSuccess)
		result = GetCachedUser(record.UserId,record,1);
	return result;
}

int BridgeDB::CreateGroup(GroupRecord& record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "CreateGroup";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupName", adBSTR, adParamInput, record.GroupName.length(), (TCHAR*)record.GroupName));
		pCom->Parameters->Append(
			pCom->CreateParameter("Description", adBSTR, adParamInput, record.Description.length(), (TCHAR*)record.Description));
		pCom->Parameters->Append(
			pCom->CreateParameter("OwnerId", adInteger, adParamInput, sizeof(int), record.OwnerId));
		pCom->Parameters->Append(
			pCom->CreateParameter("PublicView", adInteger, adParamInput, sizeof(int), record.PublicView));
		pCom->Parameters->Append(
			pCom->CreateParameter("PublicEdit", adInteger, adParamInput, sizeof(int), record.PublicEdit));

		ExecuteStoredProcedure(pCom);	
	} catch (_com_error & x) {
		print(L"BridgeDB::CreateGroup Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	int result = GetGroupId(record.GroupName, record.GroupId);
	if(result==dbSuccess)
		result = GetCachedGroup(record.GroupId,record,1);
	return result;
}

int BridgeDB::UpdateUser(UserRecord& record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "UpdateUser";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), record.UserId));
		pCom->Parameters->Append(
			pCom->CreateParameter("FirstName", adBSTR, adParamInput, record.FirstName.length(), (TCHAR*)record.FirstName));
		pCom->Parameters->Append(
			pCom->CreateParameter("LastName", adBSTR, adParamInput, record.LastName.length(), (TCHAR*)record.LastName));
		pCom->Parameters->Append(
			pCom->CreateParameter("Email", adBSTR, adParamInput, record.Email.length(), (TCHAR*)record.Email));
		pCom->Parameters->Append(
			pCom->CreateParameter("YearId", adInteger, adParamInput, sizeof(int), record.YearId));
		pCom->Parameters->Append(
			pCom->CreateParameter("SecretWeapon", adBSTR, adParamInput, record.SecretWeapon.length(), (TCHAR*)record.SecretWeapon));
		pCom->Parameters->Append(
			pCom->CreateParameter("Interest", adBSTR, adParamInput, record.Interest.length(), (TCHAR*)record.Interest));
		pCom->Parameters->Append(
			pCom->CreateParameter("Background", adBSTR, adParamInput, record.Background.length(), (TCHAR*)record.Background));

		ExecuteStoredProcedure(pCom);	
	} catch (_com_error & x) {
		print(L"BridgeDB::UpdateUser Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	return GetCachedUser(record.UserId,record,1);
}

int BridgeDB::UpdateGroup(GroupRecord& record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "UpdateGroup";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), record.GroupId));
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupName", adBSTR, adParamInput, record.GroupName.length(), (TCHAR*)record.GroupName));
		pCom->Parameters->Append(
			pCom->CreateParameter("Description", adBSTR, adParamInput, record.Description.length(), (TCHAR*)record.Description));
		pCom->Parameters->Append(
			pCom->CreateParameter("OwnerId", adInteger, adParamInput, sizeof(int), record.OwnerId));
		pCom->Parameters->Append(
			pCom->CreateParameter("PublicView", adInteger, adParamInput, sizeof(int), record.PublicView));
		pCom->Parameters->Append(
			pCom->CreateParameter("PublicEdit", adInteger, adParamInput, sizeof(int), record.PublicEdit));

		ExecuteStoredProcedure(pCom);	
	} catch (_com_error & x) {
		print(L"BridgeDB::UpdateGroup Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	return GetCachedGroup(record.GroupId,record,1);
}

int BridgeDB::LogNotification(int originator, int operant, TCHAR * type, TCHAR * reason, int optional)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "LogNotification";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("OriginatorId", adInteger, adParamInput, sizeof(int), originator));
		pCom->Parameters->Append(
			pCom->CreateParameter("OperantId", adInteger, adParamInput, sizeof(int), operant));
		pCom->Parameters->Append(
			pCom->CreateParameter("Type", adBSTR, adParamInput, _tcslen(type), type));
		pCom->Parameters->Append(
			pCom->CreateParameter("Reason", adBSTR, adParamInput, _tcslen(reason), reason));
		pCom->Parameters->Append(
			pCom->CreateParameter("OptionalId", adInteger, adParamInput, sizeof(int), optional));

		ExecuteStoredProcedure(pCom);

		return dbSuccess;

	} catch (_com_error & x) {
		print(L"BridgeDB::LogNotification Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::CreateEvent(EventRecord& record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "CreateEvent";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("EventName", adBSTR, adParamInput, record.EventName.length(), record.EventName));
		pCom->Parameters->Append(
			pCom->CreateParameter("Description", adBSTR, adParamInput, record.Description.length(), record.Description));
		pCom->Parameters->Append(
			pCom->CreateParameter("Keywords", adBSTR, adParamInput, record.Keywords.length(), record.Keywords));
		pCom->Parameters->Append(
			pCom->CreateParameter("OwnerId", adInteger, adParamInput, sizeof(int), record.OwnerId));
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), record.LocationId));
		pCom->Parameters->Append(
			pCom->CreateParameter("OtherLocation", adBSTR, adParamInput, record.OtherLocation.length(), record.OtherLocation));
		pCom->Parameters->Append(
			pCom->CreateParameter("CategoryId", adInteger, adParamInput, sizeof(int), record.CategoryId));
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), record.GroupId));
		pCom->Parameters->Append(
			pCom->CreateParameter("Eternal", adInteger, adParamInput, sizeof(int), record.Eternal));
		pCom->Parameters->Append(
			pCom->CreateParameter("StartTime", adDate, adParamInput, sizeof(DATE), record.StartTime));
		pCom->Parameters->Append(
			pCom->CreateParameter("EndTime", adDate, adParamInput, sizeof(DATE), record.EndTime));
		pCom->Parameters->Append(
			pCom->CreateParameter("Private", adInteger, adParamInput, sizeof(int), record.Private));

		ExecuteStoredProcedure(pCom);

	} catch (_com_error & x) {
		print(L"BridgeDB::CreateEvent Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	int result = GetEventId(record.EventName,record.EventId);
	if(result==dbSuccess)
		result = GetCachedEvent(record.EventId,record,1);
	return result;
}

int BridgeDB::UpdateEvent(EventRecord& record)
{
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));	
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "UpdateEvent";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(	
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), record.EventId));
		pCom->Parameters->Append(
			pCom->CreateParameter("EventName", adBSTR, adParamInput, record.EventName.length(), record.EventName));
		pCom->Parameters->Append(
			pCom->CreateParameter("Description", adBSTR, adParamInput, record.Description.length(), record.Description));
		pCom->Parameters->Append(
			pCom->CreateParameter("Keywords", adBSTR, adParamInput, record.Keywords.length(), record.Keywords));
		pCom->Parameters->Append(
			pCom->CreateParameter("OwnerId", adInteger, adParamInput, sizeof(int), record.OwnerId));
		pCom->Parameters->Append(
			pCom->CreateParameter("LocationId", adInteger, adParamInput, sizeof(int), record.LocationId));
		pCom->Parameters->Append(
			pCom->CreateParameter("OtherLocation", adBSTR, adParamInput, record.OtherLocation.length(), record.OtherLocation));
		pCom->Parameters->Append(
			pCom->CreateParameter("CategoryId", adInteger, adParamInput, sizeof(int), record.CategoryId));
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), record.GroupId));
		pCom->Parameters->Append(
			pCom->CreateParameter("StartTime", adDate, adParamInput, sizeof(DATE), record.StartTime));
		pCom->Parameters->Append(
			pCom->CreateParameter("EndTime", adDate, adParamInput, sizeof(DATE), record.EndTime));
		pCom->Parameters->Append(
			pCom->CreateParameter("Eternal", adInteger, adParamInput, sizeof(int), record.Eternal));
		pCom->Parameters->Append(
			pCom->CreateParameter("Private", adInteger, adParamInput, sizeof(int), record.Private));

		ExecuteStoredProcedure(pCom);

	} catch (_com_error & x) {
		print(L"BridgeDB::UpdateEvent Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
	return GetCachedEvent(record.EventId,record,1);
}

int BridgeDB::CreateLocation(LocationRecord& record)
{
	return dbSuccess;
}

// deletion
int BridgeDB::DeleteUser(int userId)
{
	DeleteCachedUser(userId);
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "DeleteUser";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("UserId", adInteger, adParamInput, sizeof(int), userId));
		
		ExecuteStoredProcedure(pCom);
		DeleteCachedUser(userId);
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::DeleteUser Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::DeleteGroup(int groupId)
{
	DeleteCachedGroup(groupId);
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "DeleteGroup";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("GroupId", adInteger, adParamInput, sizeof(int), groupId));
		
		ExecuteStoredProcedure(pCom);
		DeleteCachedGroup(groupId);
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::DeleteGroup Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::DeleteEvent(int eventId)
{
	DeleteCachedEvent(eventId);
	try {
		_CommandPtr pCom = NULL;
	
		pCom.CreateInstance(__uuidof(Command));
		
		// Use client cursor to enable AbsolutePosition property.
		pCom->ActiveConnection = GetConnection();
		pCom->CommandText = "DeleteEvent";
		pCom->CommandType = adCmdStoredProc;
		pCom->Parameters->Append(
			pCom->CreateParameter("EventId", adInteger, adParamInput, sizeof(int), eventId));
		
		ExecuteStoredProcedure(pCom);
		DeleteCachedEvent(eventId);
		return dbSuccess;
	} catch (_com_error & x) {
		print(L"BridgeDB::DeleteEvent Exception: %s\n",x.ErrorMessage());
		return dbException;
	}
}

int BridgeDB::DeleteLocation(int locationId)
{
	DeleteCachedLocation(locationId);
	return dbSuccess;
}
