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.

887 lines
24 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Server.cpp
  5. Abstract:
  6. This file contains the implementation of the MPCServer class,
  7. that controls the overall interaction between client and server.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 04/20/99
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. //////////////////////////////////////////////////////////////////////
  14. // Construction/Destruction
  15. //////////////////////////////////////////////////////////////////////
  16. MPCServer::MPCServer( /*[in]*/ MPCHttpContext* hcCallback, /*[in]*/ LPCWSTR szURL, /*[in]*/ LPCWSTR szUser )
  17. : m_SelfCOM ( this ),
  18. m_crClientRequest ( 0 ),
  19. m_srServerResponse( UPLOAD_LIBRARY_PROTOCOL_VERSION_SRV ) // Prepare default response protocol.
  20. {
  21. __ULT_FUNC_ENTRY("MPCServer::MPCServer");
  22. bool fFound;
  23. m_szURL = SAFEWSTR( szURL ); // MPC::wstring m_szURL;
  24. m_szUser = SAFEWSTR( szUser ); // MPC::wstring m_szUser;
  25. m_isapiInstance = NULL; // CISAPIinstance* m_isapiInstance;
  26. m_flLogHandle = NULL; // MPC::FileLog* m_flLogHandle;
  27. //
  28. m_hcCallback = hcCallback; // MPCHttpContext* m_hcCallback;
  29. m_mpccClient = NULL; // MPCClient* m_mpccClient;
  30. //
  31. // UploadLibrary::ClientRequest m_crClientRequest;
  32. // UploadLibrary::ServerResponse m_srServerResponse;
  33. //
  34. // MPC::Serializer_Memory m_streamResponseData;
  35. // MPCServerCOMWrapper m_SelfCOM;
  36. m_Session = NULL; // MPCSession* m_Session;
  37. m_customProvider = NULL; // IULProvider* m_customProvider;
  38. m_fTerminated = false; // bool m_fTerminated;
  39. if(SUCCEEDED(::Config_GetInstance( m_szURL, m_isapiInstance, fFound )))
  40. {
  41. if(fFound)
  42. {
  43. m_isapiInstance->get_LogHandle( m_flLogHandle );
  44. }
  45. }
  46. }
  47. MPCServer::~MPCServer()
  48. {
  49. __ULT_FUNC_ENTRY("MPCServer::~MPCServer");
  50. ReleaseClient();
  51. }
  52. IULServer* MPCServer::COM() { return &m_SelfCOM; }
  53. //////////////////////////////////////////////////////////////////////
  54. // Methods.
  55. //////////////////////////////////////////////////////////////////////
  56. void MPCServer::getURL ( MPC::wstring& szURL ) { szURL = m_szURL ; }
  57. void MPCServer::getUser( MPC::wstring& szUser ) { szUser = m_szUser; }
  58. CISAPIinstance* MPCServer::getInstance() { return m_isapiInstance; }
  59. MPC::FileLog* MPCServer::getFileLog () { return m_flLogHandle ; }
  60. //////////////////////////////////////////////////////////////////////
  61. HRESULT MPCServer::Process( BOOL& fKeepAlive )
  62. {
  63. __ULT_FUNC_ENTRY("MPCServer::Process");
  64. MPC::Serializer& streamConn = MPCSerializerHttp( m_hcCallback );
  65. HRESULT hr;
  66. m_fKeepAlive = TRUE;
  67. try
  68. {
  69. #ifdef DEBUG
  70. if(m_hcCallback->m_Debug_FIXED_POINTER_ERROR)
  71. {
  72. m_srServerResponse.dwPosition = m_hcCallback->m_Debug_FIXED_POINTER_ERROR_pos;
  73. SetResponse( UploadLibrary::UL_RESPONSE_SKIPPED, TRUE );
  74. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  75. }
  76. #endif
  77. //
  78. // Enforce maximum request size.
  79. //
  80. {
  81. DWORD dwMaximumPacketSize;
  82. DWORD dwCount;
  83. __MPC_EXIT_IF_METHOD_FAILS(hr, ::Config_GetMaximumPacketSize( m_szURL, dwMaximumPacketSize ));
  84. __MPC_EXIT_IF_METHOD_FAILS(hr, m_hcCallback->GetRequestSize( dwCount ));
  85. if(dwCount > dwMaximumPacketSize)
  86. {
  87. WCHAR rgSize[16]; swprintf( rgSize, L"%d", dwCount );
  88. (void)g_NTEvents.LogEvent( EVENTLOG_WARNING_TYPE, PCHUL_WARN_PACKET_SIZE,
  89. m_szURL.c_str(), // %1 = SERVER
  90. rgSize , // %2 = SIZE
  91. NULL );
  92. if(m_flLogHandle)
  93. {
  94. m_flLogHandle->LogRecord( L"ERROR | Received a packet too large: %ld, limit %ld", dwCount, dwMaximumPacketSize );
  95. }
  96. SetResponse( UploadLibrary::UL_RESPONSE_BAD_REQUEST );
  97. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  98. }
  99. }
  100. //
  101. // Read request.
  102. //
  103. __MPC_EXIT_IF_METHOD_FAILS(hr, streamConn >> m_crClientRequest);
  104. if(m_srServerResponse.MatchVersion( m_crClientRequest ) == false)
  105. {
  106. if(m_flLogHandle)
  107. {
  108. m_flLogHandle->LogRecord( L"ERROR | Received an invalid packet: SIG:%08lx VER:%08lx", m_crClientRequest.rhProlog.dwSignature, m_crClientRequest.rhProlog.dwVersion );
  109. }
  110. SetResponse( UploadLibrary::UL_RESPONSE_BAD_REQUEST );
  111. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  112. }
  113. if(FAILED(hr = GrabClient()))
  114. {
  115. //
  116. // If another process is handling the file, reply with warning BUSY.
  117. //
  118. if(hr == HRESULT_FROM_WIN32( ERROR_SHARING_VIOLATION ))
  119. {
  120. SetResponse( UploadLibrary::UL_RESPONSE_BUSY );
  121. hr = S_OK;
  122. }
  123. __ULT_FUNC_LEAVE;
  124. }
  125. if(m_crClientRequest.dwCommand == UploadLibrary::UL_COMMAND_OPENSESSION)
  126. {
  127. hr = HandleCommand_OpenSession ( streamConn );
  128. }
  129. else if(m_crClientRequest.dwCommand == UploadLibrary::UL_COMMAND_WRITESESSION)
  130. {
  131. hr = HandleCommand_WriteSession( streamConn );
  132. }
  133. else
  134. {
  135. SetResponse( UploadLibrary::UL_RESPONSE_BAD_REQUEST );
  136. }
  137. }
  138. catch(...)
  139. {
  140. __ULT_TRACE_ERROR( UPLOADLIBID, "Upload Server raised an exception. Gracefully exiting..." );
  141. MPC::wstring szID;
  142. if(m_mpccClient)
  143. {
  144. (void)m_mpccClient->FormatID( szID );
  145. }
  146. else
  147. {
  148. szID = L"<UNKNOWN>";
  149. }
  150. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, PCHUL_ERR_EXCEPTION,
  151. m_szURL.c_str(), // %1 = SERVER
  152. szID .c_str(), // %2 = CLIENT
  153. NULL );
  154. //
  155. // Something ugly happened, reply with SERVER_BUSY...
  156. //
  157. SetResponse( UploadLibrary::UL_RESPONSE_BUSY );
  158. }
  159. __ULT_FUNC_CLEANUP;
  160. if(hr != S_FALSE &&
  161. hr != E_PENDING )
  162. {
  163. MPC::Serializer_Memory streamRes;
  164. streamRes << m_srServerResponse;
  165. m_hcCallback->Write( streamRes .GetData(), streamRes .GetSize() );
  166. m_hcCallback->Write( m_streamResponseData.GetData(), m_streamResponseData.GetSize() );
  167. }
  168. //
  169. // Never return a real failure!
  170. //
  171. if(hr != E_PENDING) hr = S_OK;
  172. ReleaseClient();
  173. fKeepAlive = m_fKeepAlive;
  174. __ULT_FUNC_EXIT(hr);
  175. }
  176. //////////////////////////////////////////////////////////////////////
  177. // Helpers.
  178. //////////////////////////////////////////////////////////////////////
  179. HRESULT MPCServer::GrabClient()
  180. {
  181. __ULT_FUNC_ENTRY("MPCServer::GrabClient");
  182. HRESULT hr;
  183. if(m_mpccClient)
  184. {
  185. if(*m_mpccClient == m_crClientRequest.sigClient)
  186. {
  187. //
  188. // It's for the same client, dont' do anything...
  189. //
  190. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  191. }
  192. __MPC_EXIT_IF_METHOD_FAILS(hr, ReleaseClient());
  193. }
  194. //
  195. // Get instance's settings and create client object.
  196. //
  197. m_mpccClient = new MPCClient( this, m_crClientRequest.sigClient );
  198. //
  199. // Check authenticity of ID.
  200. //
  201. if(m_mpccClient->CheckSignature() == false)
  202. {
  203. SetResponse( UploadLibrary::UL_RESPONSE_DENIED );
  204. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  205. }
  206. if(FAILED(hr = m_mpccClient->InitFromDisk( true )))
  207. {
  208. if(hr == HRESULT_FROM_WIN32( ERROR_DISK_FULL ))
  209. {
  210. SetResponse( UploadLibrary::UL_RESPONSE_QUOTA_EXCEEDED );
  211. hr = S_OK;
  212. }
  213. __ULT_FUNC_LEAVE;
  214. }
  215. hr = S_OK;
  216. __ULT_FUNC_CLEANUP;
  217. __ULT_FUNC_EXIT(hr);
  218. }
  219. HRESULT MPCServer::ReleaseClient()
  220. {
  221. __ULT_FUNC_ENTRY("MPCServer::ReleaseClient");
  222. HRESULT hr;
  223. (void)CustomProvider_Release();
  224. if(m_mpccClient)
  225. {
  226. hr = m_mpccClient->SyncToDisk();
  227. delete m_mpccClient; m_mpccClient = NULL;
  228. if(FAILED(hr)) __ULT_FUNC_LEAVE;
  229. }
  230. hr = S_OK;
  231. __ULT_FUNC_CLEANUP;
  232. __ULT_FUNC_EXIT(hr);
  233. }
  234. /////////////////////////////////////////////////////////////////////////////
  235. HRESULT MPCServer::HandleCommand_OpenSession( /*[in] */ MPC::Serializer& streamConn )
  236. {
  237. __ULT_FUNC_ENTRY("MPCServer::HandleCommand_OpenSession");
  238. UploadLibrary::ClientRequest_OpenSession crosReq( 0 );
  239. MPCClient::Iter it;
  240. HRESULT hr;
  241. bool fServerBusy;
  242. bool fAccessDenied;
  243. bool fExceeded;
  244. crosReq.crHeader = m_crClientRequest;
  245. __MPC_EXIT_IF_METHOD_FAILS(hr, streamConn >> crosReq );
  246. #ifdef DEBUG
  247. if(m_hcCallback->m_Debug_NO_RESPONSE_TO_OPEN)
  248. {
  249. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  250. }
  251. if(m_hcCallback->m_Debug_RESPONSE_TO_OPEN)
  252. {
  253. m_srServerResponse.dwPosition = m_hcCallback->m_Debug_RESPONSE_TO_OPEN_position;
  254. m_srServerResponse.rhProlog.dwVersion = m_hcCallback->m_Debug_RESPONSE_TO_OPEN_protocol;
  255. SetResponse( m_hcCallback->m_Debug_RESPONSE_TO_OPEN_response );
  256. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  257. }
  258. #endif
  259. //
  260. // Reject any request whose length is zero.
  261. //
  262. if(crosReq.dwSize == 0 ||
  263. crosReq.dwSizeOriginal == 0 )
  264. {
  265. SetResponse( UploadLibrary::UL_RESPONSE_BAD_REQUEST );
  266. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  267. }
  268. if(m_mpccClient->Find( crosReq.szJobID, it ))
  269. {
  270. if(it->get_Committed() == true)
  271. {
  272. if(it->MatchRequest( crosReq ) == true)
  273. {
  274. SetResponse( UploadLibrary::UL_RESPONSE_COMMITTED, TRUE );
  275. }
  276. else
  277. {
  278. SetResponse( UploadLibrary::UL_RESPONSE_EXISTS );
  279. }
  280. }
  281. else
  282. {
  283. SetResponse( UploadLibrary::UL_RESPONSE_SKIPPED, TRUE );
  284. }
  285. }
  286. else
  287. {
  288. bool fPassed;
  289. if(m_flLogHandle)
  290. {
  291. m_flLogHandle->LogRecord( L"PROGRESS | Created new session: '%s' (%s)", crosReq.szJobID.c_str(), crosReq.szProviderID.c_str() );
  292. }
  293. it = m_mpccClient->NewSession( crosReq );
  294. if(SUCCEEDED(hr = it->Validate( false, fPassed )) && fPassed)
  295. {
  296. if(SUCCEEDED(hr = m_mpccClient->CheckQuotas( *it, fServerBusy, fAccessDenied, fExceeded )))
  297. {
  298. if(fServerBusy == true)
  299. {
  300. SetResponse( UploadLibrary::UL_RESPONSE_BUSY );
  301. }
  302. else if(fAccessDenied == true)
  303. {
  304. SetResponse( UploadLibrary::UL_RESPONSE_DENIED );
  305. }
  306. else if(fExceeded == true)
  307. {
  308. SetResponse( UploadLibrary::UL_RESPONSE_QUOTA_EXCEEDED );
  309. }
  310. else
  311. {
  312. SetResponse( UploadLibrary::UL_RESPONSE_SUCCESS, TRUE );
  313. }
  314. }
  315. }
  316. if(FAILED(hr) ||
  317. fPassed == false ||
  318. fExceeded == true )
  319. {
  320. m_mpccClient->Erase( it );
  321. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  322. }
  323. }
  324. __MPC_EXIT_IF_METHOD_FAILS(hr, CustomProvider_Create( *it ));
  325. __MPC_EXIT_IF_METHOD_FAILS(hr, CustomProvider_ValidateClient());
  326. if(m_fTerminated) __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  327. it->get_CurrentSize( m_srServerResponse.dwPosition );
  328. hr = S_OK;
  329. __ULT_FUNC_CLEANUP;
  330. __ULT_FUNC_EXIT(hr);
  331. }
  332. HRESULT MPCServer::HandleCommand_WriteSession( /*[in] */ MPC::Serializer& streamConn )
  333. {
  334. __ULT_FUNC_ENTRY("MPCServer::HandleCommand_WriteSession");
  335. HRESULT hr;
  336. UploadLibrary::ClientRequest_WriteSession crwsReq( 0 );
  337. MPCClient::Iter it;
  338. DWORD dwCurrentSize;
  339. DWORD dwTotalSize;
  340. bool fServerBusy;
  341. bool fAccessDenied;
  342. bool fExceeded;
  343. bool fAvailable;
  344. crwsReq.crHeader = m_crClientRequest;
  345. __MPC_EXIT_IF_METHOD_FAILS(hr, streamConn >> crwsReq);
  346. #ifdef DEBUG
  347. if(m_hcCallback->m_Debug_NO_RESPONSE_TO_WRITE)
  348. {
  349. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  350. }
  351. if(m_hcCallback->m_Debug_RESPONSE_TO_WRITE)
  352. {
  353. m_srServerResponse.dwPosition = m_hcCallback->m_Debug_RESPONSE_TO_WRITE_position;
  354. m_srServerResponse.rhProlog.dwVersion = m_hcCallback->m_Debug_RESPONSE_TO_WRITE_protocol;
  355. SetResponse( m_hcCallback->m_Debug_RESPONSE_TO_WRITE_response );
  356. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  357. }
  358. #endif
  359. //
  360. // Session couldn't be found, reply with error NOTACTIVE.
  361. //
  362. if(m_mpccClient->Find( crwsReq.szJobID, it ) == false)
  363. {
  364. SetResponse( UploadLibrary::UL_RESPONSE_NOTACTIVE );
  365. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  366. }
  367. __MPC_EXIT_IF_METHOD_FAILS(hr, CustomProvider_Create( *it ));
  368. __MPC_EXIT_IF_METHOD_FAILS(hr, CustomProvider_ValidateClient());
  369. if(m_fTerminated) __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  370. if(SUCCEEDED(hr = m_mpccClient->CheckQuotas( *it, fServerBusy, fAccessDenied, fExceeded )))
  371. {
  372. if(fServerBusy == true)
  373. {
  374. SetResponse( UploadLibrary::UL_RESPONSE_BUSY );
  375. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  376. }
  377. if(fAccessDenied == true)
  378. {
  379. SetResponse( UploadLibrary::UL_RESPONSE_DENIED );
  380. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  381. }
  382. if(fExceeded == true)
  383. {
  384. SetResponse( UploadLibrary::UL_RESPONSE_QUOTA_EXCEEDED );
  385. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  386. }
  387. }
  388. //
  389. // Session has already being finished, reply with warning COMMITTED.
  390. //
  391. if(it->get_Committed())
  392. {
  393. SetResponse( UploadLibrary::UL_RESPONSE_COMMITTED, TRUE );
  394. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  395. }
  396. #ifdef DEBUG
  397. if(m_hcCallback->m_Debug_RANDOM_POINTER_ERROR)
  398. {
  399. double pick = (double)rand() / (double)RAND_MAX;
  400. m_srServerResponse.dwPosition = m_hcCallback->m_Debug_RANDOM_POINTER_ERROR_pos_low +
  401. (m_hcCallback->m_Debug_RANDOM_POINTER_ERROR_pos_high - m_hcCallback->m_Debug_RANDOM_POINTER_ERROR_pos_low) * pick;
  402. SetResponse( UploadLibrary::UL_RESPONSE_SKIPPED, TRUE );
  403. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  404. }
  405. #endif
  406. it->get_CurrentSize( dwCurrentSize );
  407. it->get_TotalSize ( dwTotalSize );
  408. //
  409. // If request offset and file size don't match, reply with warning SKIPPED.
  410. //
  411. if(dwCurrentSize != crwsReq.dwOffset)
  412. {
  413. if(m_flLogHandle)
  414. {
  415. m_flLogHandle->LogRecord( L"WARN | Resync the client to %ld", dwCurrentSize );
  416. }
  417. m_srServerResponse.dwPosition = dwCurrentSize;
  418. SetResponse( UploadLibrary::UL_RESPONSE_SKIPPED, TRUE );
  419. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  420. }
  421. //
  422. // Trim request size (don't overwrite past the declared file size).
  423. //
  424. crwsReq.dwSize = min( dwTotalSize - dwCurrentSize, crwsReq.dwSize );
  425. //
  426. // If data is not all available, wait.
  427. //
  428. __MPC_EXIT_IF_METHOD_FAILS(hr, m_hcCallback->CheckDataAvailable( crwsReq.dwSize, fAvailable ));
  429. if(fAvailable == false)
  430. {
  431. __MPC_SET_ERROR_AND_EXIT(hr, E_PENDING);
  432. }
  433. if(m_flLogHandle)
  434. {
  435. m_flLogHandle->LogRecord( L"PROGRESS | Writing chunk: %ld bytes at %ld", crwsReq.dwSize, crwsReq.dwOffset );
  436. }
  437. //
  438. // Try to add the chunk to the file. If it fails due to low free disk space, reply with QUOTA_EXCEEDED.
  439. //
  440. {
  441. MPC::Serializer_Text streamText( streamConn );
  442. MPC::Serializer* pstream = UploadLibrary::SelectStream( streamConn, streamText );
  443. if(FAILED(hr = m_mpccClient->AppendData( *it, *pstream, crwsReq.dwSize )))
  444. {
  445. if(hr == HRESULT_FROM_WIN32( ERROR_DISK_FULL ))
  446. {
  447. SetResponse( UploadLibrary::UL_RESPONSE_QUOTA_EXCEEDED );
  448. hr = S_OK;
  449. }
  450. __ULT_FUNC_LEAVE;
  451. }
  452. __MPC_EXIT_IF_METHOD_FAILS(hr, CustomProvider_DataAvailable());
  453. if(m_fTerminated) __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  454. }
  455. //
  456. // Check for end of transmission.
  457. //
  458. it->get_CurrentSize( dwCurrentSize );
  459. if(dwCurrentSize >= dwTotalSize)
  460. {
  461. bool fMatch;
  462. __MPC_EXIT_IF_METHOD_FAILS(hr, it->CompareCRC( fMatch ));
  463. if(fMatch == false)
  464. {
  465. if(m_flLogHandle)
  466. {
  467. m_flLogHandle->LogRecord( L"WARN | Wrong CRC, restarting..." );
  468. }
  469. //
  470. // The CRC is wrong, so remove the session completely...
  471. //
  472. (void)it->RemoveFile();
  473. m_mpccClient->Erase( it );
  474. SetResponse( UploadLibrary::UL_RESPONSE_BADCRC );
  475. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  476. }
  477. else
  478. {
  479. if(m_flLogHandle)
  480. {
  481. m_flLogHandle->LogRecord( L"PROGRESS | Transfer complete" );
  482. }
  483. __MPC_EXIT_IF_METHOD_FAILS(hr, CustomProvider_TransferComplete());
  484. if(m_fTerminated) __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  485. }
  486. }
  487. else
  488. {
  489. SetResponse( UploadLibrary::UL_RESPONSE_SUCCESS, TRUE );
  490. }
  491. it->get_CurrentSize( m_srServerResponse.dwPosition );
  492. hr = S_OK;
  493. __ULT_FUNC_CLEANUP;
  494. __ULT_FUNC_EXIT(hr);
  495. }
  496. void MPCServer::SetResponse( /*[in]*/ DWORD fResponse, /*[in]*/ BOOL fKeepAlive )
  497. {
  498. m_srServerResponse.fResponse = fResponse;
  499. m_fKeepAlive = fKeepAlive;
  500. }
  501. ////////////////////////////////////////////////////////////////////////////////
  502. ////////////////////////////////////////////////////////////////////////////////
  503. HRESULT MPCServer::CustomProvider_Create( /*[in]*/ MPCSession& mpcsSession )
  504. {
  505. __ULT_FUNC_ENTRY("MPCServer::CustomProvider_Create");
  506. HRESULT hr;
  507. if(m_customProvider == NULL)
  508. {
  509. CISAPIprovider* isapiProvider;
  510. bool fFound;
  511. __MPC_EXIT_IF_METHOD_FAILS(hr, mpcsSession.GetProvider( isapiProvider, fFound ));
  512. if(fFound)
  513. {
  514. MPC::wstring szProviderGUID;
  515. CLSID guid;
  516. __MPC_EXIT_IF_METHOD_FAILS(hr, isapiProvider->get_ProviderGUID( szProviderGUID ));
  517. if(szProviderGUID.size() && SUCCEEDED(::CLSIDFromString( (LPOLESTR)szProviderGUID.c_str(), &guid )))
  518. {
  519. hr = ::CoCreateInstance( guid, NULL, CLSCTX_INPROC_SERVER, IID_IULProvider, (void**)&m_customProvider );
  520. if(FAILED(hr))
  521. {
  522. m_customProvider = NULL;
  523. }
  524. }
  525. }
  526. }
  527. m_Session = &mpcsSession;
  528. hr = S_OK;
  529. __ULT_FUNC_CLEANUP;
  530. __ULT_FUNC_EXIT(hr);
  531. }
  532. HRESULT MPCServer::CustomProvider_ValidateClient()
  533. {
  534. __ULT_FUNC_ENTRY("MPCServer::CustomProvider_ValidateClient");
  535. HRESULT hr;
  536. bool fMatch;
  537. //
  538. // Before doing anything, check client identity.
  539. //
  540. __MPC_EXIT_IF_METHOD_FAILS(hr, m_Session->CheckUser( m_szUser, fMatch ))
  541. if(fMatch == false)
  542. {
  543. SetResponse( UploadLibrary::UL_RESPONSE_NOT_AUTHORIZED );
  544. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  545. }
  546. if(m_customProvider)
  547. {
  548. hr = m_customProvider->ValidateClient( COM(), m_Session->COM() );
  549. if(FAILED(hr) && hr != E_NOTIMPL) __ULT_FUNC_LEAVE;
  550. }
  551. hr = S_OK;
  552. __ULT_FUNC_CLEANUP;
  553. __ULT_FUNC_EXIT(hr);
  554. }
  555. HRESULT MPCServer::CustomProvider_DataAvailable()
  556. {
  557. __ULT_FUNC_ENTRY("MPCServer::CustomProvider_DataAvailable");
  558. HRESULT hr;
  559. if(m_customProvider)
  560. {
  561. hr = m_customProvider->DataAvailable( COM(), m_Session->COM() );
  562. if(FAILED(hr) && hr != E_NOTIMPL) __ULT_FUNC_LEAVE;
  563. }
  564. hr = S_OK;
  565. __ULT_FUNC_CLEANUP;
  566. __ULT_FUNC_EXIT(hr);
  567. }
  568. HRESULT MPCServer::CustomProvider_TransferComplete()
  569. {
  570. __ULT_FUNC_ENTRY("MPCServer::CustomProvider_TransferComplete");
  571. HRESULT hr;
  572. //
  573. // Set the commit flag, but only move the file if we don't have a custom provider.
  574. //
  575. if(FAILED(hr = m_Session->put_Committed( true, m_customProvider ? false : true )))
  576. {
  577. if(hr == HRESULT_FROM_WIN32( ERROR_DISK_FULL ))
  578. {
  579. SetResponse( UploadLibrary::UL_RESPONSE_QUOTA_EXCEEDED );
  580. hr = S_OK;
  581. }
  582. __ULT_FUNC_LEAVE;
  583. }
  584. SetResponse( UploadLibrary::UL_RESPONSE_COMMITTED, TRUE );
  585. if(m_customProvider)
  586. {
  587. hr = m_customProvider->TransferComplete( COM(), m_Session->COM() );
  588. if(FAILED(hr) && hr != E_NOTIMPL) __ULT_FUNC_LEAVE;
  589. }
  590. hr = S_OK;
  591. __ULT_FUNC_CLEANUP;
  592. __ULT_FUNC_EXIT(hr);
  593. }
  594. HRESULT MPCServer::CustomProvider_SetResponse( /*[in]*/ IStream* data )
  595. {
  596. __ULT_FUNC_ENTRY("MPCServer::CustomProvider_SetResponse");
  597. HRESULT hr;
  598. //
  599. // Set the commit flag, but only move the file if we don't have a custom provider.
  600. //
  601. if(FAILED(hr = m_Session->put_Committed( true, m_customProvider ? false : true )))
  602. {
  603. if(hr == HRESULT_FROM_WIN32( ERROR_DISK_FULL ))
  604. {
  605. SetResponse( UploadLibrary::UL_RESPONSE_QUOTA_EXCEEDED );
  606. hr = S_OK;
  607. }
  608. __ULT_FUNC_LEAVE;
  609. }
  610. SetResponse( UploadLibrary::UL_RESPONSE_COMMITTED, TRUE );
  611. if(data)
  612. {
  613. BYTE buf[512];
  614. DWORD dwRead;
  615. while(1)
  616. {
  617. __MPC_EXIT_IF_METHOD_FAILS(hr, data->Read( buf, sizeof(buf), &dwRead ));
  618. if(dwRead == 0) break;
  619. __MPC_EXIT_IF_METHOD_FAILS(hr, m_streamResponseData.write( buf, dwRead ));
  620. }
  621. }
  622. hr = S_OK;
  623. __ULT_FUNC_CLEANUP;
  624. __ULT_FUNC_EXIT(hr);
  625. }
  626. HRESULT MPCServer::CustomProvider_Release()
  627. {
  628. __ULT_FUNC_ENTRY("MPCServer::CustomProvider_Release");
  629. HRESULT hr;
  630. if(m_customProvider)
  631. {
  632. if(m_fTerminated)
  633. {
  634. if(m_Session) m_Session->RemoveFile();
  635. }
  636. m_customProvider->Release();
  637. m_customProvider = NULL;
  638. }
  639. m_Session = NULL;
  640. hr = S_OK;
  641. __ULT_FUNC_EXIT(hr);
  642. }