Leaked source code of windows server 2003
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
30 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Client.cpp
  5. Abstract:
  6. This file contains the implementation of the MPCClient class,
  7. that describes a client's state.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 04/20/99
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. #define BUFFER_SIZE_FILECOPY (512)
  14. /////////////////////////////////////////////////////////////////////////////
  15. /////////////////////////////////////////////////////////////////////////////
  16. //
  17. // Construction/Destruction
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. /////////////////////////////////////////////////////////////////////////////
  21. /////////////////////////////////////////////////////////////////////////////
  22. //
  23. // Method Name : MPCClient::MPCClient
  24. //
  25. // Parameters : MPCServer* mpcsServer: callback for getting information about the current request.
  26. // const Sig& sigID : a reference to the ID for this client.
  27. //
  28. // Synopsis : Initializes the MPCClient object with the ID of a client.
  29. //
  30. /////////////////////////////////////////////////////////////////////////////
  31. MPCClient::MPCClient( /*[in]*/ MPCServer* mpcsServer ,
  32. /*[in]*/ const Sig& sigID )
  33. {
  34. __ULT_FUNC_ENTRY("MPCClient::MPCClient");
  35. m_mpcsServer = mpcsServer; // MPCServer* m_mpcsServer;
  36. // MPC::wstring m_szFile;
  37. //
  38. m_sigID = sigID; // Sig m_sigID;
  39. // List m_lstActiveSessions;
  40. // SYSTEMTIME m_stLastUsed;
  41. m_dwLastSession = 0; // DWORD m_dwLastSession;
  42. //
  43. m_fDirty = false; // mutable bool m_fDirty;
  44. m_hfFile = NULL; // mutable HANDLE m_hfFile;
  45. }
  46. /////////////////////////////////////////////////////////////////////////////
  47. //
  48. // Method Name : MPCClient::MPCClient
  49. //
  50. // Parameters : MPCServer* mpcsServer : callback for getting information about the current request.
  51. // const MPC::wstring& szFile : the file holding the DB.
  52. //
  53. // Synopsis : Initializes the MPCClient object suppling the filename of the DB of a client.
  54. //
  55. /////////////////////////////////////////////////////////////////////////////
  56. MPCClient::MPCClient( /*[in]*/ MPCServer* mpcsServer ,
  57. /*[in]*/ const MPC::wstring& szFile )
  58. {
  59. __ULT_FUNC_ENTRY("MPCClient::MPCClient");
  60. MPC::wstring::size_type iPos;
  61. m_mpcsServer = mpcsServer; // MPCServer* m_mpcsServer;
  62. m_szFile = szFile; // MPC::wstring m_szFile;
  63. //
  64. // Sig m_sigID;
  65. // List m_lstActiveSessions;
  66. // SYSTEMTIME m_stLastUsed;
  67. m_dwLastSession = 0; // DWORD m_dwLastSession;
  68. //
  69. m_fDirty = false; // mutable bool m_fDirty;
  70. m_hfFile = NULL; // mutable HANDLE m_hfFile;
  71. if((iPos = szFile.find( CLIENT_CONST__DB_EXTENSION, 0 )) != MPC::wstring::npos)
  72. {
  73. m_szFile = MPC::wstring( &szFile[0], &szFile[iPos] );
  74. }
  75. }
  76. /////////////////////////////////////////////////////////////////////////////
  77. //
  78. // Method Name : MPCClient::~MPCClient
  79. //
  80. // Synopsis : Before destructing the object, ensures its state is updated
  81. // to disk.
  82. //
  83. /////////////////////////////////////////////////////////////////////////////
  84. MPCClient::~MPCClient()
  85. {
  86. __ULT_FUNC_ENTRY("MPCClient::~MPCClient");
  87. if(m_hfFile)
  88. {
  89. (void)SyncToDisk();
  90. ::CloseHandle( m_hfFile ); m_hfFile = NULL;
  91. }
  92. }
  93. MPCServer* MPCClient::GetServer() { return m_mpcsServer; }
  94. /////////////////////////////////////////////////////////////////////////////
  95. /////////////////////////////////////////////////////////////////////////////
  96. //
  97. // Persistence
  98. //
  99. /////////////////////////////////////////////////////////////////////////////
  100. /////////////////////////////////////////////////////////////////////////////
  101. /////////////////////////////////////////////////////////////////////////////
  102. //
  103. // Method Name : MPCClient::IsDirty
  104. //
  105. // Return : bool : 'true' is the object is out-of-sync with the disk.
  106. //
  107. // Synopsis : Checks if the object needs to be written to disk.
  108. //
  109. /////////////////////////////////////////////////////////////////////////////
  110. bool MPCClient::IsDirty() const
  111. {
  112. __ULT_FUNC_ENTRY("MPCClient::IsDirty");
  113. bool fRes = true; // Default result.
  114. if(m_fDirty)
  115. {
  116. __ULT_FUNC_LEAVE;
  117. }
  118. else
  119. {
  120. //
  121. // Recursively check the 'Dirty' state of each session.
  122. //
  123. for(IterConst it = m_lstActiveSessions.begin(); it != m_lstActiveSessions.end(); it++)
  124. {
  125. if(it->IsDirty()) __ULT_FUNC_LEAVE;
  126. }
  127. }
  128. fRes = false;
  129. __ULT_FUNC_CLEANUP;
  130. __ULT_FUNC_EXIT(fRes);
  131. }
  132. /////////////////////////////////////////////////////////////////////////////
  133. //
  134. // Method Name : MPCClient::Load
  135. //
  136. // Parameters : MPC::Serializer& in : the stream used to initialize the object.
  137. //
  138. // Return : HRESULT : S_OK on success, failed otherwise.
  139. //
  140. // Synopsis : Loads the state of this object from the stream.
  141. //
  142. /////////////////////////////////////////////////////////////////////////////
  143. HRESULT MPCClient::Load( /*[in]*/ MPC::Serializer& streamIn )
  144. {
  145. __ULT_FUNC_ENTRY("MPCClient::Load");
  146. HRESULT hr;
  147. DWORD dwVer;
  148. Sig sigID;
  149. MPCSession mpcsSession(this);
  150. //
  151. // Clean up the previous state of the object.
  152. //
  153. m_lstActiveSessions.clear();
  154. __MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> dwVer);
  155. if(dwVer != c_dwVersion)
  156. {
  157. m_fDirty = true; // Force rewrite...
  158. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  159. }
  160. __MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> sigID );
  161. __MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> m_stLastUsed );
  162. __MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> m_dwLastSession);
  163. if(m_szFile.length())
  164. {
  165. //
  166. // In case of direct access (m_szFile != ""), initialize the sigID from disk.
  167. //
  168. m_sigID = sigID;
  169. }
  170. else if(m_sigID == sigID)
  171. {
  172. //
  173. // IDs match...
  174. //
  175. }
  176. else
  177. {
  178. //
  179. // IDs don't match, fail.
  180. //
  181. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  182. }
  183. //
  184. // While it's successful to read MPCSession objects from the stream,
  185. // keep adding them to the list of active sessions.
  186. //
  187. while(SUCCEEDED(mpcsSession.Load( streamIn )))
  188. {
  189. m_lstActiveSessions.push_back( mpcsSession );
  190. }
  191. m_fDirty = false;
  192. hr = S_OK;
  193. __ULT_FUNC_CLEANUP;
  194. __ULT_FUNC_EXIT(hr);
  195. }
  196. /////////////////////////////////////////////////////////////////////////////
  197. //
  198. // Method Name : MPCClient::Save
  199. //
  200. // Parameters : MPC::Serializer& out : the stream used to persist the state of the object.
  201. //
  202. // Return : HRESULT : S_OK on success, failed otherwise.
  203. //
  204. // Synopsis : Saves the state of this object to the stream.
  205. //
  206. /////////////////////////////////////////////////////////////////////////////
  207. HRESULT MPCClient::Save( /*[in]*/ MPC::Serializer& streamOut ) const
  208. {
  209. __ULT_FUNC_ENTRY("MPCClient::Save");
  210. HRESULT hr;
  211. __MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << c_dwVersion );
  212. __MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << m_sigID );
  213. __MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << m_stLastUsed );
  214. __MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << m_dwLastSession);
  215. //
  216. // Recursively save each session.
  217. //
  218. {
  219. for(IterConst it = m_lstActiveSessions.begin(); it != m_lstActiveSessions.end(); it++)
  220. {
  221. __MPC_EXIT_IF_METHOD_FAILS(hr, it->Save( streamOut ));
  222. }
  223. }
  224. m_fDirty = false;
  225. hr = S_OK;
  226. __ULT_FUNC_CLEANUP;
  227. __ULT_FUNC_EXIT(hr);
  228. }
  229. //////////////////////////////////////////////////////////////////////
  230. // Operators
  231. //////////////////////////////////////////////////////////////////////
  232. bool MPCClient::operator==( /*[in]*/ const UploadLibrary::Signature& rhs )
  233. {
  234. __ULT_FUNC_ENTRY("MPCClient::operator==");
  235. bool fRes = (m_sigID == rhs);
  236. __ULT_FUNC_EXIT(fRes);
  237. }
  238. bool MPCClient::Find( /*[in] */ const MPC::wstring& szJobID ,
  239. /*[out]*/ Iter& it )
  240. {
  241. __ULT_FUNC_ENTRY("MPCClient::Find");
  242. bool fRes;
  243. it = std::find( m_lstActiveSessions.begin(), m_lstActiveSessions.end(), szJobID );
  244. fRes = (it != m_lstActiveSessions.end());
  245. __ULT_FUNC_EXIT(fRes);
  246. }
  247. void MPCClient::Erase( /*[in]*/ Iter& it )
  248. {
  249. __ULT_FUNC_ENTRY("MPCClient::Erase");
  250. m_lstActiveSessions.erase( it );
  251. m_fDirty = true;
  252. }
  253. /////////////////////////////////////////////////////////////////////////////
  254. /////////////////////////////////////////////////////////////////////////////
  255. //
  256. // Methods
  257. //
  258. /////////////////////////////////////////////////////////////////////////////
  259. /////////////////////////////////////////////////////////////////////////////
  260. /////////////////////////////////////////////////////////////////////////////
  261. //
  262. // Method Name : MPCClient::GetInstance
  263. //
  264. // Parameters : CISAPIistance*& isapiInstance : instance of this request.
  265. // bool& fFound : true if instance exists.
  266. //
  267. // Return : HRESULT : S_OK on success, failed otherwise.
  268. //
  269. // Synopsis : Locates the configuration settings for the server
  270. // associated with this client.
  271. //
  272. /////////////////////////////////////////////////////////////////////////////
  273. HRESULT MPCClient::GetInstance( /*[out]*/ CISAPIinstance*& isapiInstance ,
  274. /*[out]*/ bool& fFound ) const
  275. {
  276. __ULT_FUNC_ENTRY("MPCClient::GetInstance");
  277. HRESULT hr;
  278. isapiInstance = m_mpcsServer->getInstance();
  279. fFound = (isapiInstance != NULL);
  280. hr = S_OK;
  281. __ULT_FUNC_EXIT(hr);
  282. }
  283. /////////////////////////////////////////////////////////////////////////////
  284. //
  285. // Method Name : MPCClient::GetInstance
  286. //
  287. // Parameters : MPC::wstring& szURL : variable where to store the server name.
  288. //
  289. // Return : HRESULT : S_OK on success, failed otherwise.
  290. //
  291. // Synopsis : Returns the URL associated with this client.
  292. //
  293. /////////////////////////////////////////////////////////////////////////////
  294. HRESULT MPCClient::GetInstance( /*[out]*/ MPC::wstring& szURL ) const
  295. {
  296. __ULT_FUNC_ENTRY("MPCClient::GetInstance");
  297. HRESULT hr;
  298. m_mpcsServer->getURL( szURL );
  299. hr = S_OK;
  300. __ULT_FUNC_EXIT(hr);
  301. }
  302. /////////////////////////////////////////////////////////////////////////////
  303. /////////////////////////////////////////////////////////////////////////////
  304. //
  305. // Method Name : MPCClient::IDtoPath
  306. //
  307. // Parameters : MPC::wstring& szStr : output buffer for the path.
  308. //
  309. // Synopsis : Hashing algorithm, to transform from the client ID to the
  310. // temporary queue location.
  311. //
  312. /////////////////////////////////////////////////////////////////////////////
  313. HRESULT MPCClient::IDtoPath( /*[out]*/ MPC::wstring& szStr ) const
  314. {
  315. __ULT_FUNC_ENTRY("MPCClient::IDtoPath");
  316. HRESULT hr;
  317. WCHAR rgBuf1[4*2+1];
  318. WCHAR rgBuf2[2*2+1];
  319. WCHAR rgBuf3[2*2+1];
  320. WCHAR rgBuf4[8*2+1];
  321. swprintf( rgBuf1, L"%08lx", m_sigID.guidMachineID.Data1 );
  322. swprintf( rgBuf2, L"%04x" , (int)m_sigID.guidMachineID.Data2 );
  323. swprintf( rgBuf3, L"%04x" , (int)m_sigID.guidMachineID.Data3 );
  324. for(int i=0; i<8; i++)
  325. {
  326. swprintf( &rgBuf4[i*2], L"%02x", (int)m_sigID.guidMachineID.Data4[i] );
  327. }
  328. //
  329. // Debug Format: XXYYYZZZ-AAAA-BBBB-CCCCCCCC
  330. //
  331. szStr.append( L"\\" );
  332. szStr.append( rgBuf1 );
  333. szStr.append( L"-" );
  334. szStr.append( rgBuf2 );
  335. szStr.append( L"-" );
  336. szStr.append( rgBuf3 );
  337. szStr.append( L"-" );
  338. szStr.append( rgBuf4 );
  339. //
  340. // Format: XX\YYY\ZZZ\AAAA-BBBB-CCCCCCCC
  341. //
  342. /*
  343. szStr.append( &rgBuf1[0], &rgBuf1[2] );
  344. szStr.append( L"\\" );
  345. szStr.append( &rgBuf1[2], &rgBuf1[5] );
  346. szStr.append( L"\\" );
  347. szStr.append( &rgBuf1[5], &rgBuf1[8] );
  348. szStr.append( L"\\" );
  349. szStr.append( rgBuf2 );
  350. szStr.append( L"-" );
  351. szStr.append( rgBuf3 );
  352. szStr.append( L"-" );
  353. szStr.append( rgBuf4 );
  354. */
  355. hr = S_OK;
  356. __ULT_FUNC_EXIT(hr);
  357. }
  358. /////////////////////////////////////////////////////////////////////////////
  359. //
  360. // Method Name : MPCClient::BuildClientPath
  361. //
  362. // Parameters : MPC::wstring& szPath : output buffer for the path.
  363. //
  364. // Synopsis : Returns in 'szPath' the location of this client's data.
  365. //
  366. /////////////////////////////////////////////////////////////////////////////
  367. HRESULT MPCClient::BuildClientPath( /*[out]*/ MPC::wstring& szPath ) const
  368. {
  369. __ULT_FUNC_ENTRY("MPCClient::BuildClientPath");
  370. HRESULT hr;
  371. if(m_szFile.length())
  372. {
  373. szPath = m_szFile;
  374. }
  375. else
  376. {
  377. CISAPIinstance* isapiInstance;
  378. bool fFound;
  379. __MPC_EXIT_IF_METHOD_FAILS(hr, GetInstance( isapiInstance, fFound ));
  380. if(fFound == false)
  381. {
  382. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  383. }
  384. else
  385. {
  386. CISAPIinstance::PathIter itBegin;
  387. CISAPIinstance::PathIter itEnd;
  388. __MPC_EXIT_IF_METHOD_FAILS(hr, isapiInstance->GetLocations( itBegin, itEnd ));
  389. if(itBegin == itEnd)
  390. {
  391. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  392. }
  393. szPath = *itBegin; IDtoPath( szPath );
  394. }
  395. }
  396. hr = S_OK;
  397. __ULT_FUNC_CLEANUP;
  398. __ULT_FUNC_EXIT(hr);
  399. }
  400. /////////////////////////////////////////////////////////////////////////////
  401. //
  402. // Method Name : MPCClient::GetFileName
  403. //
  404. // Parameters : MPC::wstring& szFile : output buffer for the path.
  405. //
  406. // Synopsis : Returns the filename of the directory file.
  407. //
  408. /////////////////////////////////////////////////////////////////////////////
  409. HRESULT MPCClient::GetFileName( /*[out]*/ MPC::wstring& szFile ) const
  410. {
  411. __ULT_FUNC_ENTRY("MPCClient::GetFileName");
  412. //
  413. // The filename for the Directory File is "<ID>.db"
  414. //
  415. BuildClientPath( szFile );
  416. szFile.append( CLIENT_CONST__DB_EXTENSION );
  417. __ULT_FUNC_EXIT(S_OK);
  418. }
  419. /////////////////////////////////////////////////////////////////////////////
  420. //
  421. // Method Name : MPCClient::GetFileSize
  422. //
  423. // Parameters : DWORD& dwSize : size of the Directory File.
  424. //
  425. // Synopsis : Returns the size of the directory file, if opened.
  426. //
  427. /////////////////////////////////////////////////////////////////////////////
  428. HRESULT MPCClient::GetFileSize( /*[out]*/ DWORD& dwSize ) const
  429. {
  430. __ULT_FUNC_ENTRY("MPCClient::GetFileSize");
  431. HRESULT hr;
  432. if(m_hfFile)
  433. {
  434. BY_HANDLE_FILE_INFORMATION info;
  435. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetFileInformationByHandle( m_hfFile, &info ));
  436. dwSize = info.nFileSizeLow;
  437. }
  438. else
  439. {
  440. __MPC_SET_WIN32_ERROR_AND_EXIT( hr, ERROR_INVALID_HANDLE );
  441. }
  442. hr = S_OK;
  443. __ULT_FUNC_CLEANUP;
  444. __ULT_FUNC_EXIT(hr);
  445. }
  446. /////////////////////////////////////////////////////////////////////////////
  447. //
  448. // Method Name : MPCClient::FormatID
  449. //
  450. // Parameters : MPC::wstring& szID : output buffer for the ID.
  451. //
  452. // Synopsis : Returns a textual representation of the client ID.
  453. //
  454. /////////////////////////////////////////////////////////////////////////////
  455. HRESULT MPCClient::FormatID( /*[out]*/ MPC::wstring& szID ) const
  456. {
  457. __ULT_FUNC_ENTRY("MPCClient::FormatID");
  458. HRESULT hr;
  459. CComBSTR bstrSig;
  460. bstrSig = m_sigID.guidMachineID;
  461. szID = bstrSig;
  462. hr = S_OK;
  463. __ULT_FUNC_EXIT(hr);
  464. }
  465. /////////////////////////////////////////////////////////////////////////////
  466. //
  467. // Method Name : MPCClient::CheckSignature
  468. //
  469. // Return : bool : 'true' on success.
  470. //
  471. // Synopsis : Validates the ID of this client, to ensure it's not a fake.
  472. //
  473. /////////////////////////////////////////////////////////////////////////////
  474. bool MPCClient::CheckSignature() const
  475. {
  476. __ULT_FUNC_ENTRY("MPCClient::CheckSignature");
  477. bool fRes = true;
  478. __ULT_FUNC_EXIT(fRes);
  479. }
  480. /////////////////////////////////////////////////////////////////////////////
  481. /////////////////////////////////////////////////////////////////////////////
  482. //
  483. // Method Name : MPCClient::OpenStorage
  484. //
  485. // Return : HRESULT : S_OK on success, failed otherwise.
  486. //
  487. // Synopsis : Opens the Directory File for this client, trying to
  488. // lock it for exclusive usage.
  489. // The file is kept open until this object is deleted.
  490. //
  491. /////////////////////////////////////////////////////////////////////////////
  492. HRESULT MPCClient::OpenStorage( /*[in]*/ bool fCheckFreeSpace )
  493. {
  494. __ULT_FUNC_ENTRY("MPCClient::OpenStorage");
  495. HRESULT hr;
  496. MPC::wstring szFile;
  497. bool fLocked = false;
  498. __MPC_EXIT_IF_METHOD_FAILS(hr, GetFileName( szFile ));
  499. //
  500. // If requested, make sure there's enough free space before opening the file.
  501. //
  502. if(fCheckFreeSpace)
  503. {
  504. bool fEnough;
  505. __MPC_EXIT_IF_METHOD_FAILS(hr, ::Util_CheckDiskSpace( szFile, DISKSPACE_SAFETYMARGIN, fEnough ));
  506. if(fEnough == false)
  507. {
  508. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_DISK_FULL );
  509. }
  510. }
  511. if(m_hfFile == NULL)
  512. {
  513. // Ensure the directory exists.
  514. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( szFile ) );
  515. m_hfFile = ::CreateFileW( szFile.c_str(), GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  516. if(m_hfFile == INVALID_HANDLE_VALUE)
  517. {
  518. m_hfFile = NULL;
  519. DWORD dwRes = ::GetLastError();
  520. if(dwRes == ERROR_SHARING_VIOLATION)
  521. {
  522. fLocked = true;
  523. }
  524. __MPC_SET_WIN32_ERROR_AND_EXIT( hr, dwRes );
  525. }
  526. }
  527. hr = S_OK;
  528. __ULT_FUNC_CLEANUP;
  529. if(FAILED(hr))
  530. {
  531. MPC::wstring szURL; m_mpcsServer->getURL( szURL );
  532. MPC::wstring szID; (void)FormatID ( szID );
  533. if(fLocked)
  534. {
  535. (void)g_NTEvents.LogEvent( EVENTLOG_INFORMATION_TYPE, PCHUL_WARN_COLLISION,
  536. szURL .c_str(), // %1 = SERVER
  537. szID .c_str(), // %2 = CLIENT
  538. szFile.c_str(), // %3 = FILE
  539. NULL );
  540. }
  541. else
  542. {
  543. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, PCHUL_ERR_CLIENT_DB,
  544. szURL .c_str(), // %1 = SERVER
  545. szID .c_str(), // %2 = CLIENT
  546. szFile.c_str(), // %3 = FILE
  547. NULL );
  548. }
  549. }
  550. __ULT_FUNC_EXIT(hr);
  551. }
  552. /////////////////////////////////////////////////////////////////////////////
  553. //
  554. // Method Name : MPCClient::InitFromDisk
  555. //
  556. // Return : HRESULT : S_OK on success, failed otherwise.
  557. //
  558. // Synopsis : Opens the Directory File (if not already opened) and reads
  559. // the state of the client from disk.
  560. //
  561. /////////////////////////////////////////////////////////////////////////////
  562. HRESULT MPCClient::InitFromDisk( /*[in]*/ bool fCheckFreeSpace )
  563. {
  564. __ULT_FUNC_ENTRY("MPCClient::InitFromDisk");
  565. HRESULT hr;
  566. __MPC_EXIT_IF_METHOD_FAILS(hr, OpenStorage( fCheckFreeSpace ));
  567. __MPC_EXIT_IF_METHOD_FAILS(hr, Load( MPC::Serializer_File( m_hfFile ) ));
  568. //
  569. // Now check that all the files exist.
  570. //
  571. {
  572. Iter it = m_lstActiveSessions.begin();
  573. while(it != m_lstActiveSessions.end())
  574. {
  575. bool fPassed;
  576. HRESULT hr2 = it->Validate( true, fPassed );
  577. if(FAILED(hr2) || fPassed == false)
  578. {
  579. m_lstActiveSessions.erase( it ); // Remove session.
  580. m_fDirty = true;
  581. it = m_lstActiveSessions.begin(); // Iterator corrupted, restart from beginning.
  582. }
  583. else
  584. {
  585. it++;
  586. }
  587. }
  588. }
  589. hr = S_OK;
  590. __ULT_FUNC_CLEANUP;
  591. //
  592. // If the file is not correctly loaded, try to recreate it.
  593. //
  594. if(hr == HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ))
  595. {
  596. hr = SaveToDisk();
  597. }
  598. __ULT_FUNC_EXIT(hr);
  599. }
  600. /////////////////////////////////////////////////////////////////////////////
  601. //
  602. // Method Name : MPCClient::SaveToDisk
  603. //
  604. // Return : HRESULT : S_OK on success, failed otherwise.
  605. //
  606. // Synopsis : Opens the Directory File (if not already opened) and writes
  607. // the state of the client to disk.
  608. //
  609. /////////////////////////////////////////////////////////////////////////////
  610. HRESULT MPCClient::SaveToDisk()
  611. {
  612. __ULT_FUNC_ENTRY("MPCClient::SaveToDisk");
  613. HRESULT hr;
  614. DWORD dwRes;
  615. __MPC_EXIT_IF_METHOD_FAILS(hr, OpenStorage( false ));
  616. //
  617. // Move to the beginning of the file and truncate it.
  618. //
  619. __MPC_EXIT_IF_CALL_RETURNS_THISVALUE(hr, ::SetFilePointer( m_hfFile, 0, NULL, FILE_BEGIN ), INVALID_SET_FILE_POINTER);
  620. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetEndOfFile( m_hfFile ));
  621. __MPC_EXIT_IF_METHOD_FAILS(hr, Save( MPC::Serializer_File( m_hfFile ) ));
  622. hr = S_OK;
  623. __ULT_FUNC_CLEANUP;
  624. __ULT_FUNC_EXIT(hr);
  625. }
  626. /////////////////////////////////////////////////////////////////////////////
  627. //
  628. // Method Name : MPCClient::SyncToDisk
  629. //
  630. // Return : HRESULT : S_OK on success, failed otherwise.
  631. //
  632. // Synopsis : If the Directory File has been read and modified, update it to disk.
  633. //
  634. /////////////////////////////////////////////////////////////////////////////
  635. HRESULT MPCClient::SyncToDisk()
  636. {
  637. __ULT_FUNC_ENTRY("MPCClient::SyncToDisk");
  638. HRESULT hr;
  639. if(m_hfFile && IsDirty())
  640. {
  641. __MPC_EXIT_IF_METHOD_FAILS(hr, SaveToDisk());
  642. }
  643. hr = S_OK;
  644. __ULT_FUNC_CLEANUP;
  645. __ULT_FUNC_EXIT(hr);
  646. }
  647. /////////////////////////////////////////////////////////////////////////////
  648. /////////////////////////////////////////////////////////////////////////////
  649. //
  650. // Method Name : MPCClient::GetSessions
  651. //
  652. // Parameters : Iter& itBegin : first session.
  653. // Iter& itEnd : end session marker.
  654. //
  655. // Return : HRESULT : S_OK on success, failed otherwise.
  656. //
  657. // Synopsis : Returns two iterators to access the sessions.
  658. //
  659. /////////////////////////////////////////////////////////////////////////////
  660. HRESULT MPCClient::GetSessions( /*[out]*/ Iter& itBegin ,
  661. /*[out]*/ Iter& itEnd )
  662. {
  663. __ULT_FUNC_ENTRY("MPCClient::GetSessions");
  664. HRESULT hr;
  665. itBegin = m_lstActiveSessions.begin();
  666. itEnd = m_lstActiveSessions.end ();
  667. hr = S_OK;
  668. __ULT_FUNC_EXIT(hr);
  669. }
  670. /////////////////////////////////////////////////////////////////////////////
  671. /////////////////////////////////////////////////////////////////////////////
  672. /////////////////////////////////////////////////////////////////////////////
  673. //
  674. // Method Name : MPCClient::NewSession
  675. //
  676. // Parameters : UploadLibrary::ClientRequest_OpenSession& req :
  677. // holds the information for the new session about to create.
  678. //
  679. // Return : MPCClient::Iter : an iterator pointing to the new session.
  680. //
  681. // Synopsis : Based on the values of 'req', creates a new session.
  682. //
  683. /////////////////////////////////////////////////////////////////////////////
  684. MPCClient::Iter MPCClient::NewSession( /*[in]*/ UploadLibrary::ClientRequest_OpenSession& crosReq )
  685. {
  686. __ULT_FUNC_ENTRY("MPCClient::NewSession");
  687. MPCClient::Iter it;
  688. MPCSession mpcsNewSession( this, crosReq, m_dwLastSession++ );
  689. it = m_lstActiveSessions.insert( m_lstActiveSessions.end(), mpcsNewSession );
  690. ::GetSystemTime( &m_stLastUsed );
  691. m_fDirty = true;
  692. __ULT_FUNC_EXIT(it);
  693. }
  694. /////////////////////////////////////////////////////////////////////////////
  695. //
  696. // Method Name : MPCClient::AppendData
  697. //
  698. // Parameters : UploadLibrary::ClientRequest_OpenSession& req : holds the information for the new session about to create.
  699. //
  700. // Return : MPCClient::Iter : an iterator pointing to the new session.
  701. //
  702. // Synopsis : Based on the values of 'req', creates a new session.
  703. //
  704. /////////////////////////////////////////////////////////////////////////////
  705. HRESULT MPCClient::AppendData( /*[in]*/ MPCSession& mpcsSession ,
  706. /*[in]*/ MPC::Serializer& streamConn ,
  707. /*[in]*/ DWORD dwSize )
  708. {
  709. __ULT_FUNC_ENTRY("MPCClient::AppendData");
  710. HRESULT hr;
  711. __MPC_EXIT_IF_METHOD_FAILS(hr, mpcsSession.AppendData( streamConn, dwSize ));
  712. ::GetSystemTime( &m_stLastUsed );
  713. m_fDirty = true;
  714. hr = S_OK;
  715. __ULT_FUNC_CLEANUP;
  716. __ULT_FUNC_EXIT(hr);
  717. }
  718. /////////////////////////////////////////////////////////////////////////////
  719. HRESULT MPCClient::CheckQuotas( /*[in] */ MPCSession& mpcsSession ,
  720. /*[out]*/ bool& fServerBusy ,
  721. /*[out]*/ bool& fAccessDenied,
  722. /*[out]*/ bool& fExceeded )
  723. {
  724. __ULT_FUNC_ENTRY("MPCClient::CheckQuotas");
  725. HRESULT hr;
  726. DWORD dwError = 0;
  727. DWORD dwJobsPerDay = 0;
  728. DWORD dwBytesPerDay = 0;
  729. DWORD dwJobSize = 0;
  730. DWORD dwMaxJobsPerDay;
  731. DWORD dwMaxBytesPerDay;
  732. DWORD dwMaxJobSize;
  733. DWORD fProcessingMode;
  734. CISAPIprovider* isapiProvider;
  735. IterConst it;
  736. bool fFound;
  737. fServerBusy = false;
  738. fAccessDenied = false;
  739. fExceeded = false;
  740. //
  741. // If the related provider doesn't exist, validation fails.
  742. //
  743. __MPC_EXIT_IF_METHOD_FAILS(hr, mpcsSession.GetProvider( isapiProvider, fFound ));
  744. if(fFound == false)
  745. {
  746. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  747. }
  748. __MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_MaxJobSize ( dwMaxJobSize ));
  749. __MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_MaxJobsPerDay ( dwMaxJobsPerDay ));
  750. __MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_MaxBytesPerDay( dwMaxBytesPerDay ));
  751. __MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_ProcessingMode( fProcessingMode ));
  752. if(fProcessingMode != 0)
  753. {
  754. fServerBusy = true;
  755. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  756. }
  757. mpcsSession.get_TotalSize( dwJobSize );
  758. //
  759. // Find inactive sessions.
  760. //
  761. {
  762. double dblNow = MPC::GetSystemTime();
  763. for(it = m_lstActiveSessions.begin(); it != m_lstActiveSessions.end(); it++)
  764. {
  765. double dblLastModified;
  766. it->get_LastModified( dblLastModified );
  767. if(dblNow - dblLastModified < 1.0) // Within 24 hours.
  768. {
  769. DWORD dwTotalSize; it->get_TotalSize( dwTotalSize );
  770. dwJobsPerDay += 1;
  771. dwBytesPerDay += dwTotalSize;
  772. }
  773. }
  774. }
  775. if(dwMaxJobSize && dwMaxJobSize < dwJobSize)
  776. {
  777. dwError = PCHUL_INFO_QUOTA_JOB_SIZE;
  778. fAccessDenied = true;
  779. }
  780. if(dwMaxJobsPerDay && dwMaxJobsPerDay < dwJobsPerDay)
  781. {
  782. dwError = PCHUL_INFO_QUOTA_DAILY_JOBS;
  783. fExceeded = true;
  784. }
  785. if(dwMaxBytesPerDay && dwMaxBytesPerDay < dwBytesPerDay)
  786. {
  787. dwError = PCHUL_INFO_QUOTA_DAILY_BYTES;
  788. fExceeded = true;
  789. }
  790. //
  791. // Check if enough free space is available.
  792. //
  793. {
  794. MPC::wstring szFile;
  795. bool fEnough;
  796. __MPC_EXIT_IF_METHOD_FAILS(hr, GetFileName( szFile ));
  797. __MPC_EXIT_IF_METHOD_FAILS(hr, ::Util_CheckDiskSpace( szFile, DISKSPACE_SAFETYMARGIN, fEnough ));
  798. if(fEnough == false)
  799. {
  800. dwError = PCHUL_INFO_QUOTA_DAILY_BYTES;
  801. fExceeded = true;
  802. }
  803. }
  804. if(dwError != 0)
  805. {
  806. //
  807. // Quota limits exceeded.
  808. //
  809. MPC::wstring szURL; m_mpcsServer->getURL ( szURL );
  810. MPC::wstring szID; (void)FormatID ( szID );
  811. MPC::wstring szName; (void)isapiProvider->get_Name( szName );
  812. (void)g_NTEvents.LogEvent( EVENTLOG_INFORMATION_TYPE, dwError,
  813. szURL .c_str(), // %1 = SERVER
  814. szID .c_str(), // %2 = CLIENT
  815. szName.c_str(), // %3 = PROVIDER
  816. NULL );
  817. }
  818. hr = S_OK;
  819. __ULT_FUNC_CLEANUP;
  820. __ULT_FUNC_EXIT(hr);
  821. }