Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1068 lines
29 KiB

/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name:
Client.cpp
Abstract:
This file contains the implementation of the MPCClient class,
that describes a client's state.
Revision History:
Davide Massarenti (Dmassare) 04/20/99
created
******************************************************************************/
#include "stdafx.h"
#define BUFFER_SIZE_FILECOPY (512)
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Construction/Destruction
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::MPCClient
//
// Parameters : MPCServer* mpcsServer: callback for getting information about the current request.
// const Sig& sigID : a reference to the ID for this client.
//
// Synopsis : Initializes the MPCClient object with the ID of a client.
//
/////////////////////////////////////////////////////////////////////////////
MPCClient::MPCClient( /*[in]*/ MPCServer* mpcsServer ,
/*[in]*/ const Sig& sigID )
{
__ULT_FUNC_ENTRY("MPCClient::MPCClient");
m_mpcsServer = mpcsServer; // MPCServer* m_mpcsServer;
// MPC::wstring m_szFile;
//
m_sigID = sigID; // Sig m_sigID;
// List m_lstActiveSessions;
// SYSTEMTIME m_stLastUsed;
m_dwLastSession = 0; // DWORD m_dwLastSession;
//
m_fDirty = false; // mutable bool m_fDirty;
m_hfFile = NULL; // mutable HANDLE m_hfFile;
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::MPCClient
//
// Parameters : MPCServer* mpcsServer : callback for getting information about the current request.
// const MPC::wstring& szFile : the file holding the DB.
//
// Synopsis : Initializes the MPCClient object suppling the filename of the DB of a client.
//
/////////////////////////////////////////////////////////////////////////////
MPCClient::MPCClient( /*[in]*/ MPCServer* mpcsServer ,
/*[in]*/ const MPC::wstring& szFile )
{
__ULT_FUNC_ENTRY("MPCClient::MPCClient");
MPC::wstring::size_type iPos;
m_mpcsServer = mpcsServer; // MPCServer* m_mpcsServer;
m_szFile = szFile; // MPC::wstring m_szFile;
//
// Sig m_sigID;
// List m_lstActiveSessions;
// SYSTEMTIME m_stLastUsed;
m_dwLastSession = 0; // DWORD m_dwLastSession;
//
m_fDirty = false; // mutable bool m_fDirty;
m_hfFile = NULL; // mutable HANDLE m_hfFile;
if((iPos = szFile.find( CLIENT_CONST__DB_EXTENSION, 0 )) != MPC::wstring::npos)
{
m_szFile = MPC::wstring( &szFile[0], &szFile[iPos] );
}
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::~MPCClient
//
// Synopsis : Before destructing the object, ensures its state is updated
// to disk.
//
/////////////////////////////////////////////////////////////////////////////
MPCClient::~MPCClient()
{
__ULT_FUNC_ENTRY("MPCClient::~MPCClient");
if(m_hfFile)
{
(void)SyncToDisk();
::CloseHandle( m_hfFile ); m_hfFile = NULL;
}
}
MPCServer* MPCClient::GetServer() { return m_mpcsServer; }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Persistence
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::IsDirty
//
// Return : bool : 'true' is the object is out-of-sync with the disk.
//
// Synopsis : Checks if the object needs to be written to disk.
//
/////////////////////////////////////////////////////////////////////////////
bool MPCClient::IsDirty() const
{
__ULT_FUNC_ENTRY("MPCClient::IsDirty");
bool fRes = true; // Default result.
if(m_fDirty)
{
__ULT_FUNC_LEAVE;
}
else
{
//
// Recursively check the 'Dirty' state of each session.
//
for(IterConst it = m_lstActiveSessions.begin(); it != m_lstActiveSessions.end(); it++)
{
if(it->IsDirty()) __ULT_FUNC_LEAVE;
}
}
fRes = false;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(fRes);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::Load
//
// Parameters : MPC::Serializer& in : the stream used to initialize the object.
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : Loads the state of this object from the stream.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::Load( /*[in]*/ MPC::Serializer& streamIn )
{
__ULT_FUNC_ENTRY("MPCClient::Load");
HRESULT hr;
DWORD dwVer;
Sig sigID;
MPCSession mpcsSession(this);
//
// Clean up the previous state of the object.
//
m_lstActiveSessions.clear();
__MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> dwVer);
if(dwVer != c_dwVersion)
{
m_fDirty = true; // Force rewrite...
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
}
__MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> sigID );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> m_stLastUsed );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> m_dwLastSession);
if(m_szFile.length())
{
//
// In case of direct access (m_szFile != ""), initialize the sigID from disk.
//
m_sigID = sigID;
}
else if(m_sigID == sigID)
{
//
// IDs match...
//
}
else
{
//
// IDs don't match, fail.
//
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
}
//
// While it's successful to read MPCSession objects from the stream,
// keep adding them to the list of active sessions.
//
while(SUCCEEDED(mpcsSession.Load( streamIn )))
{
m_lstActiveSessions.push_back( mpcsSession );
}
m_fDirty = false;
hr = S_OK;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::Save
//
// Parameters : MPC::Serializer& out : the stream used to persist the state of the object.
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : Saves the state of this object to the stream.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::Save( /*[in]*/ MPC::Serializer& streamOut ) const
{
__ULT_FUNC_ENTRY("MPCClient::Save");
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << c_dwVersion );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << m_sigID );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << m_stLastUsed );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << m_dwLastSession);
//
// Recursively save each session.
//
{
for(IterConst it = m_lstActiveSessions.begin(); it != m_lstActiveSessions.end(); it++)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, it->Save( streamOut ));
}
}
m_fDirty = false;
hr = S_OK;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(hr);
}
//////////////////////////////////////////////////////////////////////
// Operators
//////////////////////////////////////////////////////////////////////
bool MPCClient::operator==( /*[in]*/ const UploadLibrary::Signature& rhs )
{
__ULT_FUNC_ENTRY("MPCClient::operator==");
bool fRes = (m_sigID == rhs);
__ULT_FUNC_EXIT(fRes);
}
bool MPCClient::Find( /*[in] */ const MPC::wstring& szJobID ,
/*[out]*/ Iter& it )
{
__ULT_FUNC_ENTRY("MPCClient::Find");
bool fRes;
it = std::find( m_lstActiveSessions.begin(), m_lstActiveSessions.end(), szJobID );
fRes = (it != m_lstActiveSessions.end());
__ULT_FUNC_EXIT(fRes);
}
void MPCClient::Erase( /*[in]*/ Iter& it )
{
__ULT_FUNC_ENTRY("MPCClient::Erase");
m_lstActiveSessions.erase( it );
m_fDirty = true;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Methods
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::GetInstance
//
// Parameters : CISAPIistance*& isapiInstance : instance of this request.
// bool& fFound : true if instance exists.
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : Locates the configuration settings for the server
// associated with this client.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::GetInstance( /*[out]*/ CISAPIinstance*& isapiInstance ,
/*[out]*/ bool& fFound ) const
{
__ULT_FUNC_ENTRY("MPCClient::GetInstance");
HRESULT hr;
isapiInstance = m_mpcsServer->getInstance();
fFound = (isapiInstance != NULL);
hr = S_OK;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::GetInstance
//
// Parameters : MPC::wstring& szURL : variable where to store the server name.
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : Returns the URL associated with this client.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::GetInstance( /*[out]*/ MPC::wstring& szURL ) const
{
__ULT_FUNC_ENTRY("MPCClient::GetInstance");
HRESULT hr;
m_mpcsServer->getURL( szURL );
hr = S_OK;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::IDtoPath
//
// Parameters : MPC::wstring& szStr : output buffer for the path.
//
// Synopsis : Hashing algorithm, to transform from the client ID to the
// temporary queue location.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::IDtoPath( /*[out]*/ MPC::wstring& szStr ) const
{
__ULT_FUNC_ENTRY("MPCClient::IDtoPath");
HRESULT hr;
WCHAR rgBuf1[4*2+1];
WCHAR rgBuf2[2*2+1];
WCHAR rgBuf3[2*2+1];
WCHAR rgBuf4[8*2+1];
swprintf( rgBuf1, L"%08lx", m_sigID.guidMachineID.Data1 );
swprintf( rgBuf2, L"%04x" , (int)m_sigID.guidMachineID.Data2 );
swprintf( rgBuf3, L"%04x" , (int)m_sigID.guidMachineID.Data3 );
for(int i=0; i<8; i++)
{
swprintf( &rgBuf4[i*2], L"%02x", (int)m_sigID.guidMachineID.Data4[i] );
}
//
// Debug Format: XXYYYZZZ-AAAA-BBBB-CCCCCCCC
//
szStr.append( L"\\" );
szStr.append( rgBuf1 );
szStr.append( L"-" );
szStr.append( rgBuf2 );
szStr.append( L"-" );
szStr.append( rgBuf3 );
szStr.append( L"-" );
szStr.append( rgBuf4 );
//
// Format: XX\YYY\ZZZ\AAAA-BBBB-CCCCCCCC
//
/*
szStr.append( &rgBuf1[0], &rgBuf1[2] );
szStr.append( L"\\" );
szStr.append( &rgBuf1[2], &rgBuf1[5] );
szStr.append( L"\\" );
szStr.append( &rgBuf1[5], &rgBuf1[8] );
szStr.append( L"\\" );
szStr.append( rgBuf2 );
szStr.append( L"-" );
szStr.append( rgBuf3 );
szStr.append( L"-" );
szStr.append( rgBuf4 );
*/
hr = S_OK;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::BuildClientPath
//
// Parameters : MPC::wstring& szPath : output buffer for the path.
//
// Synopsis : Returns in 'szPath' the location of this client's data.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::BuildClientPath( /*[out]*/ MPC::wstring& szPath ) const
{
__ULT_FUNC_ENTRY("MPCClient::BuildClientPath");
HRESULT hr;
if(m_szFile.length())
{
szPath = m_szFile;
}
else
{
CISAPIinstance* isapiInstance;
bool fFound;
__MPC_EXIT_IF_METHOD_FAILS(hr, GetInstance( isapiInstance, fFound ));
if(fFound == false)
{
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
}
else
{
CISAPIinstance::PathIter itBegin;
CISAPIinstance::PathIter itEnd;
__MPC_EXIT_IF_METHOD_FAILS(hr, isapiInstance->GetLocations( itBegin, itEnd ));
if(itBegin == itEnd)
{
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
}
szPath = *itBegin; IDtoPath( szPath );
}
}
hr = S_OK;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::GetFileName
//
// Parameters : MPC::wstring& szFile : output buffer for the path.
//
// Synopsis : Returns the filename of the directory file.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::GetFileName( /*[out]*/ MPC::wstring& szFile ) const
{
__ULT_FUNC_ENTRY("MPCClient::GetFileName");
//
// The filename for the Directory File is "<ID>.db"
//
BuildClientPath( szFile );
szFile.append( CLIENT_CONST__DB_EXTENSION );
__ULT_FUNC_EXIT(S_OK);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::GetFileSize
//
// Parameters : DWORD& dwSize : size of the Directory File.
//
// Synopsis : Returns the size of the directory file, if opened.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::GetFileSize( /*[out]*/ DWORD& dwSize ) const
{
__ULT_FUNC_ENTRY("MPCClient::GetFileSize");
HRESULT hr;
if(m_hfFile)
{
BY_HANDLE_FILE_INFORMATION info;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetFileInformationByHandle( m_hfFile, &info ));
dwSize = info.nFileSizeLow;
}
else
{
__MPC_SET_WIN32_ERROR_AND_EXIT( hr, ERROR_INVALID_HANDLE );
}
hr = S_OK;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::FormatID
//
// Parameters : MPC::wstring& szID : output buffer for the ID.
//
// Synopsis : Returns a textual representation of the client ID.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::FormatID( /*[out]*/ MPC::wstring& szID ) const
{
__ULT_FUNC_ENTRY("MPCClient::FormatID");
HRESULT hr;
CComBSTR bstrSig;
bstrSig = m_sigID.guidMachineID;
szID = bstrSig;
hr = S_OK;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::CheckSignature
//
// Return : bool : 'true' on success.
//
// Synopsis : Validates the ID of this client, to ensure it's not a fake.
//
/////////////////////////////////////////////////////////////////////////////
bool MPCClient::CheckSignature() const
{
__ULT_FUNC_ENTRY("MPCClient::CheckSignature");
bool fRes = true;
__ULT_FUNC_EXIT(fRes);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::OpenStorage
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : Opens the Directory File for this client, trying to
// lock it for exclusive usage.
// The file is kept open until this object is deleted.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::OpenStorage( /*[in]*/ bool fCheckFreeSpace )
{
__ULT_FUNC_ENTRY("MPCClient::OpenStorage");
HRESULT hr;
MPC::wstring szFile;
bool fLocked = false;
__MPC_EXIT_IF_METHOD_FAILS(hr, GetFileName( szFile ));
//
// If requested, make sure there's enough free space before opening the file.
//
if(fCheckFreeSpace)
{
bool fEnough;
__MPC_EXIT_IF_METHOD_FAILS(hr, ::Util_CheckDiskSpace( szFile, DISKSPACE_SAFETYMARGIN, fEnough ));
if(fEnough == false)
{
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_DISK_FULL );
}
}
if(m_hfFile == NULL)
{
// Ensure the directory exists.
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( szFile ) );
m_hfFile = ::CreateFileW( szFile.c_str(), GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if(m_hfFile == INVALID_HANDLE_VALUE)
{
m_hfFile = NULL;
DWORD dwRes = ::GetLastError();
if(dwRes == ERROR_SHARING_VIOLATION)
{
fLocked = true;
}
__MPC_SET_WIN32_ERROR_AND_EXIT( hr, dwRes );
}
}
hr = S_OK;
__ULT_FUNC_CLEANUP;
if(FAILED(hr))
{
MPC::wstring szURL; m_mpcsServer->getURL( szURL );
MPC::wstring szID; (void)FormatID ( szID );
if(fLocked)
{
(void)g_NTEvents.LogEvent( EVENTLOG_INFORMATION_TYPE, PCHUL_WARN_COLLISION,
szURL .c_str(), // %1 = SERVER
szID .c_str(), // %2 = CLIENT
szFile.c_str(), // %3 = FILE
NULL );
}
else
{
(void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, PCHUL_ERR_CLIENT_DB,
szURL .c_str(), // %1 = SERVER
szID .c_str(), // %2 = CLIENT
szFile.c_str(), // %3 = FILE
NULL );
}
}
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::InitFromDisk
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : Opens the Directory File (if not already opened) and reads
// the state of the client from disk.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::InitFromDisk( /*[in]*/ bool fCheckFreeSpace )
{
__ULT_FUNC_ENTRY("MPCClient::InitFromDisk");
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, OpenStorage( fCheckFreeSpace ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Load( MPC::Serializer_File( m_hfFile ) ));
//
// Now check that all the files exist.
//
{
Iter it = m_lstActiveSessions.begin();
while(it != m_lstActiveSessions.end())
{
bool fPassed;
HRESULT hr2 = it->Validate( true, fPassed );
if(FAILED(hr2) || fPassed == false)
{
m_lstActiveSessions.erase( it ); // Remove session.
m_fDirty = true;
it = m_lstActiveSessions.begin(); // Iterator corrupted, restart from beginning.
}
else
{
it++;
}
}
}
hr = S_OK;
__ULT_FUNC_CLEANUP;
//
// If the file is not correctly loaded, try to recreate it.
//
if(hr == HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ))
{
hr = SaveToDisk();
}
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::SaveToDisk
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : Opens the Directory File (if not already opened) and writes
// the state of the client to disk.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::SaveToDisk()
{
__ULT_FUNC_ENTRY("MPCClient::SaveToDisk");
HRESULT hr;
DWORD dwRes;
__MPC_EXIT_IF_METHOD_FAILS(hr, OpenStorage( false ));
//
// Move to the beginning of the file and truncate it.
//
__MPC_EXIT_IF_CALL_RETURNS_THISVALUE(hr, ::SetFilePointer( m_hfFile, 0, NULL, FILE_BEGIN ), INVALID_SET_FILE_POINTER);
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetEndOfFile( m_hfFile ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Save( MPC::Serializer_File( m_hfFile ) ));
hr = S_OK;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::SyncToDisk
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : If the Directory File has been read and modified, update it to disk.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::SyncToDisk()
{
__ULT_FUNC_ENTRY("MPCClient::SyncToDisk");
HRESULT hr;
if(m_hfFile && IsDirty())
{
__MPC_EXIT_IF_METHOD_FAILS(hr, SaveToDisk());
}
hr = S_OK;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::GetSessions
//
// Parameters : Iter& itBegin : first session.
// Iter& itEnd : end session marker.
//
// Return : HRESULT : S_OK on success, failed otherwise.
//
// Synopsis : Returns two iterators to access the sessions.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::GetSessions( /*[out]*/ Iter& itBegin ,
/*[out]*/ Iter& itEnd )
{
__ULT_FUNC_ENTRY("MPCClient::GetSessions");
HRESULT hr;
itBegin = m_lstActiveSessions.begin();
itEnd = m_lstActiveSessions.end ();
hr = S_OK;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::NewSession
//
// Parameters : UploadLibrary::ClientRequest_OpenSession& req :
// holds the information for the new session about to create.
//
// Return : MPCClient::Iter : an iterator pointing to the new session.
//
// Synopsis : Based on the values of 'req', creates a new session.
//
/////////////////////////////////////////////////////////////////////////////
MPCClient::Iter MPCClient::NewSession( /*[in]*/ UploadLibrary::ClientRequest_OpenSession& crosReq )
{
__ULT_FUNC_ENTRY("MPCClient::NewSession");
MPCClient::Iter it;
MPCSession mpcsNewSession( this, crosReq, m_dwLastSession++ );
it = m_lstActiveSessions.insert( m_lstActiveSessions.end(), mpcsNewSession );
::GetSystemTime( &m_stLastUsed );
m_fDirty = true;
__ULT_FUNC_EXIT(it);
}
/////////////////////////////////////////////////////////////////////////////
//
// Method Name : MPCClient::AppendData
//
// Parameters : UploadLibrary::ClientRequest_OpenSession& req : holds the information for the new session about to create.
//
// Return : MPCClient::Iter : an iterator pointing to the new session.
//
// Synopsis : Based on the values of 'req', creates a new session.
//
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::AppendData( /*[in]*/ MPCSession& mpcsSession ,
/*[in]*/ MPC::Serializer& streamConn ,
/*[in]*/ DWORD dwSize )
{
__ULT_FUNC_ENTRY("MPCClient::AppendData");
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, mpcsSession.AppendData( streamConn, dwSize ));
::GetSystemTime( &m_stLastUsed );
m_fDirty = true;
hr = S_OK;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
HRESULT MPCClient::CheckQuotas( /*[in] */ MPCSession& mpcsSession ,
/*[out]*/ bool& fServerBusy ,
/*[out]*/ bool& fAccessDenied,
/*[out]*/ bool& fExceeded )
{
__ULT_FUNC_ENTRY("MPCClient::CheckQuotas");
HRESULT hr;
DWORD dwError = 0;
DWORD dwJobsPerDay = 0;
DWORD dwBytesPerDay = 0;
DWORD dwJobSize = 0;
DWORD dwMaxJobsPerDay;
DWORD dwMaxBytesPerDay;
DWORD dwMaxJobSize;
DWORD fProcessingMode;
CISAPIprovider* isapiProvider;
IterConst it;
bool fFound;
fServerBusy = false;
fAccessDenied = false;
fExceeded = false;
//
// If the related provider doesn't exist, validation fails.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, mpcsSession.GetProvider( isapiProvider, fFound ));
if(fFound == false)
{
__MPC_SET_ERROR_AND_EXIT(hr, S_OK);
}
__MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_MaxJobSize ( dwMaxJobSize ));
__MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_MaxJobsPerDay ( dwMaxJobsPerDay ));
__MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_MaxBytesPerDay( dwMaxBytesPerDay ));
__MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_ProcessingMode( fProcessingMode ));
if(fProcessingMode != 0)
{
fServerBusy = true;
__MPC_SET_ERROR_AND_EXIT(hr, S_OK);
}
mpcsSession.get_TotalSize( dwJobSize );
//
// Find inactive sessions.
//
{
double dblNow = MPC::GetSystemTime();
for(it = m_lstActiveSessions.begin(); it != m_lstActiveSessions.end(); it++)
{
double dblLastModified;
it->get_LastModified( dblLastModified );
if(dblNow - dblLastModified < 1.0) // Within 24 hours.
{
DWORD dwTotalSize; it->get_TotalSize( dwTotalSize );
dwJobsPerDay += 1;
dwBytesPerDay += dwTotalSize;
}
}
}
if(dwMaxJobSize && dwMaxJobSize < dwJobSize)
{
dwError = PCHUL_INFO_QUOTA_JOB_SIZE;
fAccessDenied = true;
}
if(dwMaxJobsPerDay && dwMaxJobsPerDay < dwJobsPerDay)
{
dwError = PCHUL_INFO_QUOTA_DAILY_JOBS;
fExceeded = true;
}
if(dwMaxBytesPerDay && dwMaxBytesPerDay < dwBytesPerDay)
{
dwError = PCHUL_INFO_QUOTA_DAILY_BYTES;
fExceeded = true;
}
//
// Check if enough free space is available.
//
{
MPC::wstring szFile;
bool fEnough;
__MPC_EXIT_IF_METHOD_FAILS(hr, GetFileName( szFile ));
__MPC_EXIT_IF_METHOD_FAILS(hr, ::Util_CheckDiskSpace( szFile, DISKSPACE_SAFETYMARGIN, fEnough ));
if(fEnough == false)
{
dwError = PCHUL_INFO_QUOTA_DAILY_BYTES;
fExceeded = true;
}
}
if(dwError != 0)
{
//
// Quota limits exceeded.
//
MPC::wstring szURL; m_mpcsServer->getURL ( szURL );
MPC::wstring szID; (void)FormatID ( szID );
MPC::wstring szName; (void)isapiProvider->get_Name( szName );
(void)g_NTEvents.LogEvent( EVENTLOG_INFORMATION_TYPE, dwError,
szURL .c_str(), // %1 = SERVER
szID .c_str(), // %2 = CLIENT
szName.c_str(), // %3 = PROVIDER
NULL );
}
hr = S_OK;
__ULT_FUNC_CLEANUP;
__ULT_FUNC_EXIT(hr);
}