/****************************************************************************** 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 ".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); }