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.

2710 lines
74 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: transdata.cxx
  7. //
  8. // Contents: Contains the module which provide data passed on in OnDataAvailable
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 12-07-95 JohannP (Johann Posch) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <trans.h>
  18. #ifndef unix
  19. #include "..\stg\rostmdir.hxx"
  20. #include "..\stg\rostmfil.hxx"
  21. #else
  22. #include "../stg/rostmdir.hxx"
  23. #include "../stg/rostmfil.hxx"
  24. #endif /* unix */
  25. PerfDbgTag(tagCTransData, "Urlmon", "Log CTransData", DEB_DATA);
  26. DbgTag(tagCTransDataErr, "Urlmon", "Log CTransData Errors", DEB_DATA|DEB_ERROR);
  27. HRESULT FindMediaType(LPCSTR pszType, CLIPFORMAT *cfType);
  28. HRESULT FindMediaTypeW(LPCWSTR pwzType, CLIPFORMAT *cfType);
  29. static LPSTR g_szCF_NULL = "*/*";
  30. char szContent[] = "Content Type";
  31. char szClassID[] = "CLSID";
  32. char szFlags[] = "Flags";
  33. char szExtension[] = "Extension";
  34. char szMimeKey[] = "MIME\\Database\\Content Type\\";
  35. const ULONG ulMimeKeyLen = ((sizeof(szMimeKey)/sizeof(char))-1);
  36. // The byte combination that identifies that a file is a storage of
  37. // some kind
  38. const BYTE SIGSTG[] = {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1};
  39. const BYTE CBSIGSTG = sizeof(SIGSTG);
  40. #define CBSNIFFDATA_MAX 256
  41. #ifdef DBG
  42. char *szDataSinkName[] =
  43. {
  44. "Unknown"
  45. ,"StreamNoCopyData"
  46. ,"File"
  47. ,"Storage"
  48. ,"StreamOnFile"
  49. ,"StreamBindToObject"
  50. ,"GenericStream"
  51. };
  52. #define GetDataSinkName(ds) szDataSinkName[ds]
  53. #else
  54. #define GetDataSinkName(ds) ""
  55. #endif
  56. //+---------------------------------------------------------------------------
  57. //
  58. // Method: CTransData::CTransData
  59. //
  60. // Synopsis:
  61. //
  62. // Arguments: [pTrans] --
  63. // [DWORD] --
  64. // [dwSizeBuffer] --
  65. // [fBindToObject] --
  66. //
  67. // Returns:
  68. //
  69. // History: 1-27-96 JohannP (Johann Posch) Created
  70. //
  71. // Notes:
  72. //
  73. //----------------------------------------------------------------------------
  74. CTransData::CTransData(CTransaction *pTrans, LPBYTE pByte,DWORD dwSizeBuffer, BOOL fBindToObject) : _CRefs()
  75. {
  76. DEBUG_ENTER((DBG_TRANSDAT,
  77. None,
  78. "CTransData::CTransData",
  79. "this=%#x, %#x, %#x, %#x, %B",
  80. this, pTrans, pByte, dwSizeBuffer, fBindToObject
  81. ));
  82. _TransDataState = TransData_Initialized;
  83. _wzMime[0] = '\0';
  84. _wzFileName[0]= 0;
  85. _pwzUrl = 0;
  86. _pwzRedirectUrl = 0;
  87. _pStgMed = 0;
  88. _lpBuffer = pByte;
  89. _cbBufferSize = dwSizeBuffer;
  90. _cbDataSize = 0;
  91. _cbTotalBytesRead = 0;
  92. _cbReadReturn = 0;
  93. _cbBufferFilled = 0;
  94. _cbDataSniffMin = DATASNIFSIZE_MIN;
  95. _pEnumFE = 0;
  96. _pStgMed = NULL;
  97. _pProt = NULL;
  98. _fBindToObject = fBindToObject; //Flag changes on attachment.. Use sparingly.
  99. _fMimeTypeVerified = TRUE;
  100. _fDocFile = FALSE;
  101. _fInitialized = FALSE;
  102. _fRemoteReady = FALSE;
  103. _fCache = FALSE;
  104. _fLocked = FALSE;
  105. _fFileAsStmOnFile = FALSE;
  106. _fEOFOnSwitchSink = FALSE;
  107. _hFile = NULL;
  108. _cbBytesReported = 0;
  109. _dwAttached = 0;
  110. _grfBindF = 0;
  111. _grfBSC = 0;
  112. DEBUG_LEAVE(0);
  113. }
  114. //+---------------------------------------------------------------------------
  115. //
  116. // Method: CTransData::~CTransData
  117. //
  118. // Synopsis:
  119. //
  120. // Arguments: (none)
  121. //
  122. // Returns:
  123. //
  124. // History: 1-27-96 JohannP (Johann Posch) Created
  125. //
  126. // Notes:
  127. //
  128. //----------------------------------------------------------------------------
  129. CTransData::~CTransData()
  130. {
  131. DEBUG_ENTER((DBG_TRANSDAT,
  132. None,
  133. "CTransData::~CTransData",
  134. "this=%#x",
  135. this
  136. ));
  137. PerfDbgLog(tagCTransData, this, "+CTransData::~CTransData");
  138. if (_pwzUrl)
  139. {
  140. delete [] _pwzUrl;
  141. }
  142. if (_pwzRedirectUrl)
  143. {
  144. delete [] _pwzRedirectUrl;
  145. }
  146. if (_pProt)
  147. {
  148. if (_fLocked)
  149. {
  150. _pProt->UnlockRequest();
  151. }
  152. _pProt->Release();
  153. _pProt = NULL;
  154. }
  155. if (_pBndCtx)
  156. {
  157. _pBndCtx->Release();
  158. }
  159. if (_pStgMed)
  160. {
  161. TransAssert(( (_pStgMed->pUnkForRelease == NULL)
  162. || (_pStgMed->pUnkForRelease == this)));
  163. if (_pStgMed->tymed == TYMED_ISTREAM)
  164. {
  165. _pStgMed->pstm->Release();
  166. }
  167. else if (_pStgMed->tymed == TYMED_FILE)
  168. {
  169. if (_pStgMed->lpszFileName)
  170. {
  171. delete _pStgMed->lpszFileName;
  172. }
  173. }
  174. else if (_pStgMed->tymed == TYMED_ISTORAGE)
  175. {
  176. _pStgMed->pstg->Release();
  177. }
  178. DbgLog1(tagCTransData, this, "=== CTransData::~CTransData: (pStgMed:%lx)", _pStgMed);
  179. delete _pStgMed;
  180. _pStgMed = NULL;
  181. }
  182. if (_hFile)
  183. {
  184. DbgLog1(tagCTransData, this, "=== CTransData::~CTransData (CloseHandle(%lx)", _hFile);
  185. CloseHandle(_hFile);
  186. _hFile = NULL;
  187. }
  188. if (_lpBuffer)
  189. {
  190. delete _lpBuffer;
  191. }
  192. PerfDbgLog(tagCTransData, this, "-CTransData::~CTransData");
  193. DEBUG_LEAVE(0);
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Method: CTransData::QueryInterface
  198. //
  199. // Synopsis:
  200. //
  201. // Arguments: [riid] --
  202. // [ppvObj] --
  203. //
  204. // Returns:
  205. //
  206. // History: 1-27-96 JohannP (Johann Posch) Created
  207. //
  208. // Notes:
  209. //
  210. //----------------------------------------------------------------------------
  211. STDMETHODIMP CTransData::QueryInterface(REFIID riid, void **ppvObj)
  212. {
  213. DEBUG_ENTER((DBG_TRANSDAT,
  214. Hresult,
  215. "CTransData::IUnknown::QueryInterface",
  216. "this=%#x, %#x, %#x",
  217. this, &riid, ppvObj
  218. ));
  219. VDATEPTROUT(ppvObj, void *);
  220. VDATETHIS(this);
  221. HRESULT hr = NOERROR;
  222. PerfDbgLog(tagCTransData, this, "+CTransData::QueryInterface");
  223. *ppvObj = NULL;
  224. if ((riid == IID_IUnknown) || (riid == IID_ITransactionData))
  225. {
  226. *ppvObj = this;
  227. AddRef();
  228. }
  229. else
  230. {
  231. hr = E_NOINTERFACE;
  232. }
  233. PerfDbgLog1(tagCTransData, this, "-CTransData::QueryInterface (hr:%lx)", hr);
  234. DEBUG_LEAVE(hr);
  235. return hr;
  236. }
  237. //+---------------------------------------------------------------------------
  238. //
  239. // Function: CTransData::AddRef
  240. //
  241. // Synopsis:
  242. //
  243. // Arguments: [ULONG] --
  244. //
  245. // Returns:
  246. //
  247. // History: 1-27-96 JohannP (Johann Posch) Created
  248. //
  249. // Notes:
  250. //
  251. //----------------------------------------------------------------------------
  252. STDMETHODIMP_(ULONG) CTransData::AddRef(void)
  253. {
  254. DEBUG_ENTER((DBG_TRANSDAT,
  255. Dword,
  256. "CTransData::IUnknown::AddRef",
  257. "this=%#x",
  258. this
  259. ));
  260. LONG lRet = ++_CRefs;
  261. PerfDbgLog1(tagCTransData, this, "CTransData::AddRef (cRefs:%ld)", lRet);
  262. DEBUG_LEAVE(lRet);
  263. return lRet;
  264. }
  265. //+---------------------------------------------------------------------------
  266. //
  267. // Function: CTransData::Release
  268. //
  269. // Synopsis:
  270. //
  271. // Arguments: [ULONG] --
  272. //
  273. // Returns:
  274. //
  275. // History: 1-27-96 JohannP (Johann Posch) Created
  276. //
  277. // Notes:
  278. //
  279. //----------------------------------------------------------------------------
  280. STDMETHODIMP_(ULONG) CTransData::Release(void)
  281. {
  282. DEBUG_ENTER((DBG_TRANSDAT,
  283. Dword,
  284. "CTransData::IUnknown::Release",
  285. "this=%#x",
  286. this
  287. ));
  288. PerfDbgLog(tagCTransData, this, "+CTransData::Release");
  289. LONG lRet = --_CRefs;
  290. if (_CRefs == 0)
  291. {
  292. delete this;
  293. }
  294. PerfDbgLog1(tagCTransData, this, "-CTransData::Release (cRefs:%ld)", lRet);
  295. DEBUG_LEAVE(lRet);
  296. return lRet;
  297. }
  298. //+---------------------------------------------------------------------------
  299. //
  300. // Method: CTransData::GetTransactionData
  301. //
  302. // Synopsis:
  303. //
  304. // Arguments: [pwzUrl] --
  305. // [ppwzFilename] --
  306. // [ppwzMime] --
  307. // [pdwSizeTotal] --
  308. // [pdwSizeAvailable] --
  309. // [dwReserved] --
  310. //
  311. // Returns:
  312. //
  313. // History: 9-09-96 JohannP (Johann Posch) Created
  314. //
  315. // Notes:
  316. //
  317. //----------------------------------------------------------------------------
  318. STDMETHODIMP CTransData::GetTransactionData(LPCWSTR pwzUrl, LPOLESTR *ppwzFilename, LPOLESTR *ppwzMime,
  319. DWORD *pdwSizeTotal, DWORD *pdwSizeAvailable, DWORD dwReserved)
  320. {
  321. DEBUG_ENTER((DBG_TRANSDAT,
  322. Hresult,
  323. "CTransData::GetTransactionData",
  324. "this=%#x, %.80wq, %#x, %#x, %#x, %#x, %#x",
  325. this, pwzUrl, ppwzFilename, ppwzMime, pdwSizeTotal, pdwSizeAvailable, dwReserved
  326. ));
  327. PerfDbgLog(tagCTransData, this, "+CTransData::GetTransactionData");
  328. HRESULT hr = NOERROR;
  329. TransAssert((pwzUrl && ppwzFilename && ppwzMime && pdwSizeTotal && pdwSizeAvailable ));
  330. TransAssert((_wzFileName[0] != 0));
  331. if (ppwzFilename && ppwzMime && pdwSizeTotal && pdwSizeAvailable)
  332. {
  333. LPWSTR pwzUrlLocal = GetUrl();
  334. TransAssert((pwzUrlLocal));
  335. DbgLog2(tagCTransData, this, "=== CTransData::GetTransactionData (pwzUrlLocal:%ws, pwzUrl:%ws)", pwzUrlLocal, pwzUrl);
  336. if (!wcscmp(pwzUrl, _pwzUrl) || (_pwzRedirectUrl && !wcscmp(pwzUrl, _pwzRedirectUrl)))
  337. {
  338. *ppwzFilename = OLESTRDuplicate(_wzFileName);
  339. *ppwzMime = OLESTRDuplicate(_wzMime);
  340. if (_cbDataSize)
  341. {
  342. *pdwSizeTotal = _cbDataSize;
  343. }
  344. else
  345. {
  346. *pdwSizeTotal = _cbTotalBytesRead;
  347. }
  348. *pdwSizeAvailable = _cbTotalBytesRead;
  349. }
  350. else
  351. {
  352. *ppwzFilename = 0;
  353. *ppwzMime = NULL;
  354. *pdwSizeTotal = 0;
  355. *pdwSizeAvailable = 0;
  356. hr = E_INVALIDARG;
  357. }
  358. }
  359. else
  360. {
  361. hr = E_INVALIDARG;
  362. }
  363. PerfDbgLog5(tagCTransData, this, "-CTransData::GetTransactionData (hr:%lx, Filename:%ws, Mime:%ws, _cbDataSize:%ld, _cbTotalBytesRead:%ld)",
  364. hr, XDBG(*ppwzFilename,L""), XDBG(*ppwzMime,L""), _cbDataSize, _cbTotalBytesRead);
  365. DEBUG_LEAVE(hr);
  366. return hr;
  367. }
  368. //+---------------------------------------------------------------------------
  369. //
  370. // Method: CTransData::Create
  371. //
  372. // Synopsis: Set up the transaction data object.
  373. //
  374. // Arguments: [pTrans] -- pointer to transaction
  375. // [riid] -- riid the users passed in
  376. // [ppCTD] -- the transdata object passed back
  377. //
  378. // Returns:
  379. //
  380. // History: 1-18-96 JohannP (Johann Posch) Created
  381. //
  382. // Notes:
  383. //
  384. //----------------------------------------------------------------------------
  385. STDMETHODIMP CTransData::Create(LPCWSTR pwUrl, DWORD grfBindF, REFIID riid, IBindCtx *pBndCtx,
  386. BOOL fBindToObject, CTransData **ppCTD)
  387. {
  388. DEBUG_ENTER((DBG_TRANSDAT,
  389. Hresult,
  390. "CTransData::Create",
  391. "%.80wq, %#x, %#x, %#x, %B, %#x",
  392. pwUrl, grfBindF, &riid, pBndCtx, fBindToObject, ppCTD
  393. ));
  394. HRESULT hr = NOERROR;
  395. PerfDbgLog1(tagCTransData, NULL, "+CTransData::Create(fBindToObject:%d)", fBindToObject);
  396. CTransData *pCTData;
  397. LPBYTE lpBuffer;
  398. ULONG cbBufferSize;
  399. cbBufferSize = DNLD_BUFFER_SIZE;
  400. TransAssert((DATASNIFSIZEDOCFILE_MIN <= cbBufferSize));
  401. lpBuffer = (LPBYTE) new BYTE[cbBufferSize];
  402. pCTData = new CTransData(NULL,lpBuffer,cbBufferSize, fBindToObject);
  403. if (lpBuffer && pCTData)
  404. {
  405. *ppCTD = pCTData;
  406. pCTData->Initialize(pwUrl, grfBindF, riid, pBndCtx);
  407. // Try to get an IEnumFORMATETC pointer from the bind context
  408. //hr = GetObjectParam(pbc, REG_ENUMFORMATETC, IID_IEnumFORMATETC, (IUnknown**)&_pEnumFE);
  409. }
  410. else
  411. {
  412. if (pCTData)
  413. {
  414. delete pCTData;
  415. }
  416. else if (lpBuffer)
  417. {
  418. delete lpBuffer;
  419. }
  420. hr = E_OUTOFMEMORY;
  421. *ppCTD = 0;
  422. }
  423. PerfDbgLog2(tagCTransData, NULL, "-CTransData::Create (out:%lx,hr:%lx)", *ppCTD, hr);
  424. DEBUG_LEAVE(hr);
  425. return hr;
  426. }
  427. //+---------------------------------------------------------------------------
  428. //
  429. // Method: CTransData::Initialize
  430. //
  431. // Synopsis:
  432. //
  433. // Arguments: [riid] --
  434. //
  435. // Returns:
  436. //
  437. // History: 1-27-96 JohannP (Johann Posch) Created
  438. //
  439. // Notes:
  440. //
  441. //----------------------------------------------------------------------------
  442. STDMETHODIMP CTransData::Initialize(LPCWSTR pwzUrl, DWORD grfBindF, REFIID riid, IBindCtx *pBndCtx, BOOL fBindToObject)
  443. {
  444. DEBUG_ENTER((DBG_TRANSDAT,
  445. Hresult,
  446. "CTransData::Initialize",
  447. "this=%#x, %.80wq, %#x, %#x, %#x, %B",
  448. this, pwzUrl, grfBindF, &riid, pBndCtx, fBindToObject
  449. ));
  450. PerfDbgLog(tagCTransData, this, "+CTransData::Initialize");
  451. HRESULT hr = NOERROR;
  452. if (_fInitialized == FALSE)
  453. {
  454. _ds = DataSink_Unknown;
  455. _formatetc.tymed = TYMED_NULL;
  456. _grfBindF = grfBindF;
  457. _pBndCtx = pBndCtx;
  458. _pBndCtx->AddRef();
  459. _pwzUrl = OLESTRDuplicate((LPWSTR)pwzUrl);
  460. if (!_pwzUrl)
  461. {
  462. hr = E_OUTOFMEMORY;
  463. }
  464. if (SUCCEEDED(hr))
  465. {
  466. if (_fBindToObject)
  467. {
  468. _formatetc.tymed = TYMED_ISTREAM;
  469. _ds = DataSink_Unknown;
  470. }
  471. else if (riid == IID_IUnknown)
  472. {
  473. // this is the BindToStorage
  474. _formatetc.tymed = TYMED_FILE;
  475. _ds = DataSink_File;
  476. }
  477. else if (riid == IID_IStream)
  478. {
  479. // We do not know yet which kind of stream
  480. // SetDataSink will determine this.
  481. _formatetc.tymed = TYMED_ISTREAM;
  482. _ds = DataSink_StreamOnFile;
  483. }
  484. else if (riid == IID_IStorage)
  485. {
  486. BIND_OPTS bindopts;
  487. bindopts.cbStruct = sizeof(BIND_OPTS);
  488. hr = pBndCtx->GetBindOptions(&bindopts);
  489. _grfMode = bindopts.grfMode;
  490. _formatetc.tymed = TYMED_ISTORAGE;
  491. _ds = DataSink_Storage;
  492. }
  493. else
  494. {
  495. // this call should fail
  496. hr = E_INVALIDARG;
  497. TransAssert((FALSE && "Unknown data sink for this request!"));
  498. }
  499. }
  500. if (SUCCEEDED(hr))
  501. {
  502. HRESULT hr1;
  503. ITransactionData *pCTransData = NULL;
  504. LPWSTR pwzFilename = NULL;
  505. LPWSTR pwzMime = NULL;
  506. hr1 = GetObjectParam(pBndCtx, SZ_TRANSACTIONDATA, IID_ITransactionData, (IUnknown **)&pCTransData);
  507. DbgLog2(tagCTransData, this, "=== CTransData::Initialize GetObjectParam: pbndctx:%lx, hr:%lx)", pBndCtx, hr1);
  508. if (SUCCEEDED(hr1))
  509. {
  510. TransAssert((pCTransData));
  511. hr1 = pCTransData->GetTransactionData(_pwzUrl,&pwzFilename, &pwzMime, &_cbDataSize, &_cbTotalBytesRead, 0);
  512. DbgLog5(tagCTransData, this, "=== CTransData::Initialize GetTransactionData (hr:%lx, Filename:%ws, Mime:%ws, _cbDataSize:%ld, _cbTotalBytesRead:%ld)", hr1, pwzFilename, pwzMime, _cbDataSize, _cbTotalBytesRead);
  513. pCTransData->Release();
  514. }
  515. if (SUCCEEDED(hr1) )
  516. {
  517. // set the url filename
  518. SetFileName(pwzFilename);
  519. if (pwzMime)
  520. {
  521. SetMimeType(pwzMime);
  522. _fMimeTypeVerified = TRUE;
  523. }
  524. _fRemoteReady = TRUE;
  525. if (pwzMime)
  526. {
  527. delete pwzMime;
  528. }
  529. if (pwzFilename)
  530. {
  531. delete pwzFilename;
  532. }
  533. }
  534. }
  535. _fInitialized = TRUE;
  536. }
  537. else
  538. {
  539. _dwAttached++;
  540. if (_pBndCtx)
  541. {
  542. _pBndCtx->Release();
  543. }
  544. _pBndCtx = pBndCtx;
  545. if (_pBndCtx)
  546. {
  547. _pBndCtx->AddRef();
  548. }
  549. // no set up the righte datasink
  550. if (fBindToObject)
  551. {
  552. _fBindToObject = TRUE;
  553. SwitchDataSink(DataSink_StreamBindToObject);
  554. }
  555. else if (riid == IID_IUnknown)
  556. {
  557. SwitchDataSink(DataSink_File);
  558. }
  559. else if ( (riid == IID_IStream)
  560. && (grfBindF & BINDF_NEEDFILE))
  561. {
  562. SwitchDataSink(DataSink_StreamOnFile);
  563. }
  564. }
  565. PerfDbgLog3(tagCTransData, this, "-CTransData::Initialize (_formatetc.tymed:%ld, _ds:%lx, hr:%lx)", _formatetc.tymed,_ds, hr);
  566. DEBUG_LEAVE(hr);
  567. return hr;
  568. }
  569. //+---------------------------------------------------------------------------
  570. //
  571. // Method: CTransData::PrepareThreadTransfer
  572. //
  573. // Synopsis:
  574. //
  575. // Arguments:
  576. //
  577. // Returns:
  578. //
  579. // History: 10-09-1996 JohannP (Johann Posch) Created
  580. //
  581. // Notes:
  582. //
  583. //----------------------------------------------------------------------------
  584. STDMETHODIMP CTransData::PrepareThreadTransfer()
  585. {
  586. DEBUG_ENTER((DBG_TRANSDAT,
  587. Hresult,
  588. "CTransData::PrepareThreadTransfer",
  589. "this=%#x",
  590. this
  591. ));
  592. PerfDbgLog(tagCTransData, this, "+CTransData::PrepareThreadTransfer");
  593. HRESULT hr = NOERROR;
  594. if (_pBndCtx)
  595. {
  596. _pBndCtx->Release();
  597. _pBndCtx = NULL;
  598. }
  599. PerfDbgLog1(tagCTransData, this, "-CTransData::PrepareThreadTransfer (hr:%lx)", hr);
  600. DEBUG_LEAVE(hr);
  601. return hr;
  602. }
  603. //+---------------------------------------------------------------------------
  604. //
  605. // Method: CTransData::GetDataSink
  606. //
  607. // Synopsis:
  608. //
  609. // Arguments: (none)
  610. //
  611. // Returns:
  612. //
  613. // History: 2-22-96 JohannP (Johann Posch) Created
  614. //
  615. // Notes:
  616. //
  617. //----------------------------------------------------------------------------
  618. DataSink CTransData::GetDataSink()
  619. {
  620. DEBUG_ENTER((DBG_TRANSDAT,
  621. Pointer,
  622. "CTransData::GetDataSink",
  623. "this=%#x",
  624. this
  625. ));
  626. PerfDbgLog(tagCTransData, this, "+CTransData::GetDataSink");
  627. DataSink dsRet = DataSink_Unknown;
  628. if (_ds == DataSink_Unknown)
  629. {
  630. DWORD dwBindF = GetBindFlags();
  631. if ( (dwBindF & BINDF_ASYNCSTORAGE)
  632. && (dwBindF & BINDF_PULLDATA)
  633. && (_formatetc.tymed == TYMED_ISTREAM))
  634. {
  635. dsRet = _ds = DataSink_StreamNoCopyData;
  636. }
  637. }
  638. else
  639. {
  640. dsRet = _ds;
  641. }
  642. PerfDbgLog1(tagCTransData, this, "-CTransData::GetDataSink (dsRet:%lx)", dsRet);
  643. DEBUG_LEAVE(dsRet);
  644. return dsRet;
  645. }
  646. //+---------------------------------------------------------------------------
  647. //
  648. // Method: CTransData::SetDataSink
  649. //
  650. // Synopsis:
  651. //
  652. // Arguments: [dwBindF] --
  653. //
  654. // Returns:
  655. //
  656. // History: 2-25-96 JohannP (Johann Posch) Created
  657. //
  658. // Notes:
  659. //
  660. //----------------------------------------------------------------------------
  661. DataSink CTransData::SetDataSink(DWORD dwBindF)
  662. {
  663. DEBUG_ENTER((DBG_TRANSDAT,
  664. Pointer,
  665. "CTransData::SetDataSink",
  666. "this=%#x, %#x",
  667. this, dwBindF
  668. ));
  669. PerfDbgLog1(tagCTransData, this, "+CTransData::SetDataSink (_ds:%lx)", _ds);
  670. TransAssert((_formatetc.tymed != TYMED_NULL));
  671. _grfBindF = dwBindF;
  672. switch (_ds)
  673. {
  674. case DataSink_Unknown:
  675. {
  676. if (_fBindToObject)
  677. {
  678. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  679. _ds = DataSink_StreamBindToObject;
  680. }
  681. }
  682. break;
  683. case DataSink_File:
  684. {
  685. TransAssert((_formatetc.tymed == TYMED_FILE));
  686. }
  687. break;
  688. case DataSink_StreamOnFile:
  689. {
  690. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  691. if ((dwBindF & BINDF_ASYNCSTORAGE) && (dwBindF & BINDF_PULLDATA))
  692. {
  693. _ds = DataSink_StreamNoCopyData;
  694. }
  695. }
  696. break;
  697. case DataSink_StreamBindToObject:
  698. {
  699. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  700. TransAssert((_fBindToObject == TRUE));
  701. if (IsObjectReady() == NOERROR)
  702. {
  703. //
  704. // change it to file - stream on file will be opened
  705. //
  706. _ds = DataSink_StreamOnFile;
  707. }
  708. else if ((dwBindF & BINDF_ASYNCSTORAGE) && (dwBindF & BINDF_PULLDATA))
  709. {
  710. _ds = DataSink_StreamNoCopyData;
  711. }
  712. }
  713. break;
  714. case DataSink_Storage:
  715. {
  716. TransAssert((_formatetc.tymed == TYMED_ISTORAGE));
  717. }
  718. break;
  719. case DataSink_GenericStream:
  720. {
  721. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  722. }
  723. break;
  724. default:
  725. TransAssert((FALSE && "CTransData::SetDataSink -- Invalid data location"));
  726. break;
  727. }
  728. PerfDbgLog1(tagCTransData, this, "-CTransData::SetDataSink (_ds:%lx)", _ds);
  729. DEBUG_LEAVE(_ds);
  730. return _ds;
  731. }
  732. //+---------------------------------------------------------------------------
  733. //
  734. // Method: CTransData::SwitchDataSink
  735. //
  736. // Synopsis:
  737. //
  738. // Arguments: [dwBindF] --
  739. //
  740. // Returns:
  741. //
  742. // History: 2-25-96 JohannP (Johann Posch) Created
  743. //
  744. // Notes:
  745. //
  746. //----------------------------------------------------------------------------
  747. DataSink CTransData::SwitchDataSink(DataSink dsNew)
  748. {
  749. DEBUG_ENTER((DBG_TRANSDAT,
  750. Pointer,
  751. "CTransData::SwitchDataSink",
  752. "this=%#x, %#x",
  753. this, dsNew
  754. ));
  755. PerfDbgLog2(tagCTransData, this, "+CTransData::SwitchDataSink (_ds:%lx, dsNew:%lx)", _ds, dsNew);
  756. TransAssert((_ds != DataSink_Unknown));
  757. TransAssert((_formatetc.tymed != TYMED_NULL));
  758. HRESULT hr = NOERROR;
  759. switch (_ds)
  760. {
  761. case DataSink_File:
  762. {
  763. TransAssert((_formatetc.tymed == TYMED_FILE));
  764. }
  765. break;
  766. case DataSink_StreamOnFile:
  767. {
  768. TransAssert((_wzFileName[0] != 0));
  769. _formatetc.tymed = TYMED_ISTREAM;
  770. }
  771. break;
  772. case DataSink_GenericStream:
  773. {
  774. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  775. }
  776. break;
  777. case DataSink_StreamNoCopyData:
  778. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  779. if ( dsNew == DataSink_StreamOnFile
  780. || dsNew == DataSink_GenericStream
  781. || dsNew == DataSink_StreamBindToObject)
  782. {
  783. _ds = dsNew;
  784. DWORD dwNew = 0;
  785. hr = OnDataReceived(_grfBSC, 0, 0, &dwNew);
  786. if( hr == S_FALSE)
  787. {
  788. _fEOFOnSwitchSink = TRUE;
  789. }
  790. }
  791. break;
  792. case DataSink_StreamBindToObject:
  793. {
  794. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  795. TransAssert((_fBindToObject == TRUE));
  796. _ds = dsNew;
  797. if (_ds == DataSink_File)
  798. {
  799. _formatetc.tymed = TYMED_FILE;
  800. DWORD dwNew = 0;
  801. hr = OnDataReceived(_grfBSC, 0, 0, &dwNew);
  802. if( hr == S_FALSE)
  803. {
  804. _fEOFOnSwitchSink = TRUE;
  805. }
  806. }
  807. }
  808. break;
  809. case DataSink_Storage:
  810. {
  811. TransAssert((_formatetc.tymed == TYMED_ISTORAGE));
  812. }
  813. break;
  814. default:
  815. TransAssert((FALSE && "CTransData::SwitchDataSink -- Invalid data location"));
  816. break;
  817. }
  818. PerfDbgLog2(tagCTransData, this, "-CTransData::SwitchDataSink (_ds:%lx, dsNew:%lx)", _ds, dsNew);
  819. DEBUG_LEAVE(_ds);
  820. return _ds;
  821. }
  822. //+---------------------------------------------------------------------------
  823. //
  824. // Method: CTransData::IsFileRequired()
  825. //
  826. // Synopsis:
  827. //
  828. // Arguments: (none)
  829. //
  830. // Returns:
  831. //
  832. // History: 2-22-96 JohannP (Johann Posch) Created
  833. //
  834. // Notes:
  835. //
  836. //----------------------------------------------------------------------------
  837. BOOL CTransData::IsFileRequired()
  838. {
  839. DEBUG_ENTER((DBG_TRANSDAT,
  840. Bool,
  841. "CTransData::IsFileRequired",
  842. "this=%#x",
  843. this
  844. ));
  845. PerfDbgLog(tagCTransData, this, "+CTransData::IsFileRequired()");
  846. BOOL fRet = FALSE;
  847. TransAssert((_ds != DataSink_Unknown));
  848. switch (_ds)
  849. {
  850. case DataSink_File:
  851. case DataSink_StreamOnFile:
  852. fRet = TRUE;
  853. }
  854. PerfDbgLog1(tagCTransData, this, "-CTransData::IsFileRequired() (fRet:%d)", fRet);
  855. DEBUG_LEAVE(fRet);
  856. return fRet;
  857. }
  858. //+---------------------------------------------------------------------------
  859. //
  860. // Method: CTransData::GetData
  861. //
  862. // Synopsis:
  863. //
  864. // Arguments: [ppformatetc] --
  865. // [ppStgMed] --
  866. // [grfBSCF] --
  867. //
  868. // Returns:
  869. //
  870. // History: 1-27-96 JohannP (Johann Posch) Created
  871. //
  872. // Notes:
  873. //
  874. //----------------------------------------------------------------------------
  875. STDMETHODIMP CTransData::GetData(FORMATETC **ppformatetc, STGMEDIUM **ppStgMed, DWORD grfBSCF)
  876. {
  877. DEBUG_ENTER((DBG_TRANSDAT,
  878. Hresult,
  879. "CTransData::GetData",
  880. "this=%#x, %#x, %#x, %#x",
  881. this, ppformatetc, ppStgMed, grfBSCF
  882. ));
  883. PerfDbgLog1(tagCTransData, this, "+CTransData::GetData (_ds:%ld)", _ds);
  884. HRESULT hr = INET_E_DATA_NOT_AVAILABLE;
  885. BOOL fNewStgMed = FALSE;
  886. DataSink ds;
  887. *ppStgMed = 0;
  888. *ppformatetc = 0;
  889. if (_pStgMed == NULL)
  890. {
  891. // first find the formatETC based on
  892. // clipformat and the EnumFormatETC
  893. FindFormatETC();
  894. _pStgMed = new STGMEDIUM;
  895. if (_pStgMed == NULL)
  896. {
  897. hr = E_OUTOFMEMORY;
  898. goto End;
  899. }
  900. *ppformatetc = &_formatetc;
  901. _pStgMed->tymed = TYMED_NULL;
  902. _pStgMed->hGlobal = NULL;
  903. _pStgMed->pUnkForRelease = 0;
  904. _pStgMed->pstm = NULL;
  905. fNewStgMed = TRUE;
  906. }
  907. ds = _ds;
  908. if( _fFileAsStmOnFile && _ds == DataSink_File )
  909. {
  910. ds = DataSink_StreamOnFile;
  911. }
  912. switch (ds)
  913. {
  914. case DataSink_File:
  915. {
  916. //TransAssert(( (grfBSCF & ~BSCF_LASTDATANOTIFICATION)
  917. // || ((grfBSCF & BSCF_LASTDATANOTIFICATION) && (_formatetc.tymed == TYMED_FILE)) ));
  918. if (_wzFileName[0] != 0)
  919. {
  920. TransAssert((_wzFileName[0] != 0));
  921. if (_pStgMed->tymed == TYMED_FILE)
  922. {
  923. if (_pStgMed->lpszFileName == NULL)
  924. {
  925. _pStgMed->lpszFileName = (LPWSTR) new WCHAR [wcslen(_wzFileName)+2];
  926. if (_pStgMed->lpszFileName)
  927. {
  928. wcscpy(_pStgMed->lpszFileName, _wzFileName);
  929. }
  930. else
  931. {
  932. hr = E_OUTOFMEMORY;
  933. goto End;
  934. }
  935. }
  936. }
  937. else
  938. {
  939. ASSERT(_pStgMed->tymed == TYMED_NULL);
  940. _pStgMed->tymed = TYMED_FILE;
  941. _pStgMed->lpszFileName = (LPWSTR) new WCHAR [wcslen(_wzFileName)+2];
  942. if (_pStgMed->lpszFileName)
  943. {
  944. wcscpy(_pStgMed->lpszFileName, _wzFileName);
  945. }
  946. else
  947. {
  948. hr = E_OUTOFMEMORY;
  949. goto End;
  950. }
  951. }
  952. if (_pStgMed->pUnkForRelease == NULL)
  953. {
  954. _pStgMed->pUnkForRelease = this;
  955. }
  956. hr = NOERROR;
  957. DbgLog1(tagCTransData, this, "+CTransData::GetData -> TYMED_FILE: %ws", _wzFileName);
  958. }
  959. else
  960. {
  961. // filename is not available yet
  962. hr = INET_E_DATA_NOT_AVAILABLE;
  963. }
  964. }
  965. break;
  966. case DataSink_GenericStream:
  967. case DataSink_StreamBindToObject:
  968. case DataSink_StreamNoCopyData:
  969. {
  970. DbgLog1(tagCTransData, this, "=== CTransData::GetData (_ds:%lx)", _ds);
  971. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  972. if (_pStgMed->tymed == TYMED_NULL)
  973. {
  974. CReadOnlyStreamDirect *pCRoStm = new CReadOnlyStreamDirect( this, _grfBindF);
  975. if (pCRoStm)
  976. {
  977. _pStgMed->tymed = TYMED_ISTREAM;
  978. _pStgMed->pstm = pCRoStm;
  979. _pStgMed->pUnkForRelease = this;
  980. hr = NOERROR;
  981. }
  982. else
  983. {
  984. hr = E_OUTOFMEMORY;
  985. }
  986. DbgLog1(tagCTransData, this, "+CTransData::GetData -> TYMED_ISTREAM: %lx", pCRoStm);
  987. }
  988. else
  989. {
  990. hr = NOERROR;
  991. }
  992. DbgLog2(tagCTransData, this, "=== CTransData::GetData (_ds:%lx,pstm:%lx)", _ds,_pStgMed->pstm);
  993. DbgLog2(tagCTransData, this, "=== (_cbBufferFilled:%ld, _cbBufferSize:%ld)", _cbBufferFilled,_cbBufferSize);
  994. }
  995. break;
  996. case DataSink_StreamOnFile:
  997. {
  998. DbgLog1(tagCTransData, this, "=== CTransData::GetData (_ds:%lx)", _ds);
  999. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  1000. if (_wzFileName[0] != 0)
  1001. {
  1002. if (_pStgMed->tymed == TYMED_NULL)
  1003. {
  1004. if( _pStgMed->pstm )
  1005. {
  1006. //BUG-BUG : relying on undocumented behavior of ReleaseStgMedium..
  1007. // may or may not zero this out in future.
  1008. _pStgMed->tymed = TYMED_ISTREAM;
  1009. _pStgMed->pUnkForRelease = this;
  1010. // When pStm gets created, the ctor set the ref count
  1011. // to 1, so no need any additional AddRef.
  1012. //
  1013. // Here we are not create a new pStm, we need to do an
  1014. // AddRef on the pStm because
  1015. // CBinding::OnDataNotification (the only caller of this)
  1016. // will call ReleaseStgMedia() which will call
  1017. // _pStgMeg->pstm->Release()
  1018. _pStgMed->pstm->AddRef();
  1019. hr = NOERROR;
  1020. }
  1021. else
  1022. {
  1023. char szTempFile[MAX_PATH];
  1024. CReadOnlyStreamFile *pCRoStm = NULL;
  1025. W2A(_wzFileName, szTempFile, MAX_PATH);
  1026. hr = CReadOnlyStreamFile::Create(szTempFile, &pCRoStm, _pwzUrl);
  1027. if (pCRoStm)
  1028. {
  1029. _pStgMed->tymed = TYMED_ISTREAM;
  1030. _pStgMed->pstm = pCRoStm;
  1031. _pStgMed->pUnkForRelease = this;
  1032. hr = NOERROR;
  1033. }
  1034. else
  1035. {
  1036. // filename is not available yet
  1037. hr = INET_E_DATA_NOT_AVAILABLE;
  1038. }
  1039. DbgLog2(tagCTransData, this, "+CTransData::GetData -> TYMED_ISTREAM: %lx (hr:%lx)", pCRoStm,hr);
  1040. }
  1041. }
  1042. else
  1043. {
  1044. TransAssert((_pStgMed->tymed == TYMED_ISTREAM));
  1045. hr = NOERROR;
  1046. }
  1047. }
  1048. else
  1049. {
  1050. DbgLog(tagCTransDataErr, this, "+CTransData::GetData ->StreamOnFile: no filename!");
  1051. // filename is not available yet
  1052. hr = INET_E_DATA_NOT_AVAILABLE;
  1053. }
  1054. }
  1055. break;
  1056. case DataSink_Storage:
  1057. {
  1058. DbgLog2(tagCTransData, this, "=== CTransData::GetData (_ds:%lx, _wzFileName:%ws)", _ds, _wzFileName);
  1059. TransAssert((_formatetc.tymed == TYMED_ISTORAGE));
  1060. TransAssert((_wzFileName != NULL));
  1061. if (_wzFileName[0] != 0)
  1062. {
  1063. if (_pStgMed->tymed == TYMED_NULL)
  1064. {
  1065. IStorage *pStg = NULL;
  1066. hr = StgOpenStorage(_wzFileName, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &pStg );
  1067. DbgLog1(tagCTransData, this, "+CTransData::GetData -> TYMED_ISTORAGE: %ws", _wzFileName);
  1068. if (pStg)
  1069. {
  1070. _pStgMed->tymed = TYMED_ISTORAGE;
  1071. _pStgMed->pstg = pStg;
  1072. _pStgMed->pUnkForRelease = this;
  1073. hr = NOERROR;
  1074. }
  1075. DbgLog2(tagCTransData, this, "+CTransData::GetData -> TYMED_ISTORAGE: %lx (hr:%lx)", pStg,hr);
  1076. }
  1077. else
  1078. {
  1079. TransAssert((_pStgMed->tymed == TYMED_ISTORAGE));
  1080. hr = NOERROR;
  1081. }
  1082. }
  1083. // else return default error
  1084. }
  1085. break;
  1086. default:
  1087. // this needs to be implemented
  1088. TransAssert((FALSE && "CTransData::GetData -- Invalid data location"));
  1089. break;
  1090. }
  1091. if (SUCCEEDED(hr) && _pStgMed)
  1092. {
  1093. // this object was addref on punkforrelease
  1094. *ppStgMed = _pStgMed;
  1095. *ppformatetc = &_formatetc;
  1096. // Use ourselves as the unknown for release, so that the temp file
  1097. // doesn't get removed when ReleaseStgMedium() is called. We need
  1098. // to AddRef ourselves to balance the Release that will occur.
  1099. if (_pStgMed->pUnkForRelease)
  1100. {
  1101. AddRef();
  1102. if ( _pProt
  1103. && fNewStgMed
  1104. && SUCCEEDED(_pProt->LockRequest(0)) )
  1105. {
  1106. _fLocked = TRUE;
  1107. }
  1108. }
  1109. hr = NOERROR;
  1110. TransAssert((_pStgMed->pUnkForRelease != NULL));
  1111. }
  1112. End:
  1113. PerfDbgLog1(tagCTransData, this, "-CTransData::GetData (hr:%lx)", hr);
  1114. DEBUG_LEAVE(hr);
  1115. return hr;
  1116. }
  1117. //+---------------------------------------------------------------------------
  1118. //
  1119. // Method: CTransData::ReadHere
  1120. //
  1121. // Synopsis:
  1122. //
  1123. // Arguments: [pBuffer] --
  1124. // [cbBuffer] --
  1125. // [pdwRead] --
  1126. //
  1127. // Returns:
  1128. //
  1129. // History: 1-27-96 JohannP (Johann Posch) Created
  1130. //
  1131. // Notes:
  1132. //
  1133. //----------------------------------------------------------------------------
  1134. STDMETHODIMP CTransData::ReadHere(LPBYTE pBuffer, DWORD cbBuffer, DWORD *pdwRead)
  1135. {
  1136. DEBUG_ENTER((DBG_TRANSDAT,
  1137. Hresult,
  1138. "CTransData::ReadHere",
  1139. "this=%#x, %#x, %#x, %#x",
  1140. this, pBuffer, cbBuffer, pdwRead
  1141. ));
  1142. PerfDbgLog2(tagCTransData, this, "+CTransData::ReadHere (_ds:%lx,cbBuffer:%ld)", _ds,cbBuffer);
  1143. HRESULT hr = NOERROR;
  1144. switch (_ds)
  1145. {
  1146. case DataSink_StreamNoCopyData:
  1147. case DataSink_StreamBindToObject:
  1148. {
  1149. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  1150. BOOL fRead = TRUE;
  1151. DWORD dwCopy = 0;
  1152. DWORD dwCopyNew = 0;
  1153. if (_cbBufferFilled)
  1154. {
  1155. fRead = FALSE;
  1156. // copy data form the local buffer to the provide buffer
  1157. if (cbBuffer < _cbBufferFilled)
  1158. {
  1159. dwCopy = cbBuffer;
  1160. memcpy(pBuffer, _lpBuffer, cbBuffer);
  1161. // move the memory to the front
  1162. memcpy(_lpBuffer, _lpBuffer + cbBuffer, _cbBufferFilled - cbBuffer);
  1163. _cbBufferFilled -= cbBuffer;
  1164. hr = S_OK;
  1165. }
  1166. else if (cbBuffer == _cbBufferFilled)
  1167. {
  1168. dwCopy = _cbBufferFilled;
  1169. memcpy(pBuffer, _lpBuffer, _cbBufferFilled);
  1170. _cbBufferFilled = 0;
  1171. hr = S_OK;
  1172. }
  1173. else
  1174. {
  1175. //
  1176. // user buffer is greater than what is available in
  1177. //
  1178. dwCopy = _cbBufferFilled;
  1179. memcpy(pBuffer, _lpBuffer, _cbBufferFilled);
  1180. _cbBufferFilled = 0;
  1181. fRead = TRUE;
  1182. hr = E_PENDING;
  1183. }
  1184. }
  1185. // now read from the wire
  1186. if ((_cbBufferFilled == 0) && (fRead == TRUE))
  1187. {
  1188. // read data from our buffer
  1189. if (_TransDataState == TransData_ProtoTerminated)
  1190. {
  1191. // download completed
  1192. hr = (dwCopy) ? S_OK : S_FALSE;
  1193. }
  1194. else if (pBuffer && cbBuffer)
  1195. {
  1196. hr = _pProt->Read(pBuffer + dwCopy, cbBuffer - dwCopy, &dwCopyNew);
  1197. _cbTotalBytesRead += dwCopyNew;
  1198. }
  1199. else
  1200. {
  1201. hr = E_INVALIDARG;
  1202. }
  1203. }
  1204. if (pdwRead)
  1205. {
  1206. *pdwRead = dwCopy + dwCopyNew;
  1207. if (*pdwRead && (hr != E_PENDING))
  1208. // some data in buffer
  1209. {
  1210. hr = S_OK;
  1211. }
  1212. }
  1213. }
  1214. break;
  1215. case DataSink_StreamOnFile:
  1216. {
  1217. DbgLog(tagCTransData, this, "=== CTransData::ReadHere (_ds:DataSink_StreamNoCopyData)");
  1218. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  1219. TransAssert((pdwRead != NULL));
  1220. // read data from our buffer
  1221. if (_TransDataState == TransData_ProtoTerminated)
  1222. {
  1223. // download completed
  1224. hr = S_FALSE;
  1225. }
  1226. else if (pBuffer && cbBuffer)
  1227. {
  1228. hr = _pProt->Read(pBuffer, cbBuffer, pdwRead);
  1229. }
  1230. else
  1231. {
  1232. hr = E_INVALIDARG;
  1233. }
  1234. }
  1235. break;
  1236. case DataSink_File:
  1237. {
  1238. TransAssert((_formatetc.tymed == TYMED_FILE));
  1239. }
  1240. break;
  1241. default:
  1242. // this needs to be implemented
  1243. hr = E_FAIL;
  1244. TransAssert((FALSE && "CTransData::ReadHere -- Invalid data location"));
  1245. break;
  1246. }
  1247. TransAssert(( ( (hr == S_FALSE && *pdwRead == 0)
  1248. || (hr == S_OK && *pdwRead != 0)
  1249. || (hr == E_PENDING)
  1250. || (hr == E_INVALIDARG)
  1251. || (hr == INET_E_DATA_NOT_AVAILABLE)
  1252. || (hr == INET_E_DOWNLOAD_FAILURE)
  1253. )
  1254. && "CTransData::ReadHere -- Invalid return code"));
  1255. PerfDbgLog3(tagCTransData, this, "-CTransData::ReadHere (hr:%lx,cbBuffer:%ld,pdwRead:%ld)", hr,cbBuffer,*pdwRead);
  1256. DEBUG_LEAVE(hr);
  1257. return hr;
  1258. }
  1259. //+---------------------------------------------------------------------------
  1260. //
  1261. // Method: CTransData::Seek
  1262. //
  1263. // Synopsis:
  1264. //
  1265. // Arguments: [DWORD] --
  1266. // [ULARGE_INTEGER] --
  1267. // [plibNewPosition] --
  1268. //
  1269. // Returns:
  1270. //
  1271. // History: 10-30-1996 JohannP (Johann Posch) Created
  1272. //
  1273. // Notes:
  1274. //
  1275. //----------------------------------------------------------------------------
  1276. STDMETHODIMP CTransData::Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition)
  1277. {
  1278. DEBUG_ENTER((DBG_TRANSDAT,
  1279. Hresult,
  1280. "CTransData::Seek",
  1281. "this=%#x, %#x, %#x, %#x",
  1282. this, dlibMove, dwOrigin, plibNewPosition
  1283. ));
  1284. PerfDbgLog(tagCTransData, this, "+CTransData::Seek");
  1285. HRESULT hr;
  1286. hr = _pProt->Seek(dlibMove, dwOrigin,plibNewPosition);
  1287. PerfDbgLog1(tagCTransData, this, "-CTransData::Seek (hr:%lx)", hr);
  1288. DEBUG_LEAVE(hr);
  1289. return hr;
  1290. }
  1291. //+---------------------------------------------------------------------------
  1292. //
  1293. // Method: CTransData::GetReadBuffer
  1294. //
  1295. // Synopsis:
  1296. //
  1297. // Arguments: [ppBuffer] --
  1298. // [pcbBytes] --
  1299. //
  1300. // Returns:
  1301. //
  1302. // History: 1-27-96 JohannP (Johann Posch) Created
  1303. //
  1304. // Notes:
  1305. //
  1306. //----------------------------------------------------------------------------
  1307. STDMETHODIMP CTransData::GetReadBuffer(BYTE **ppBuffer, DWORD *pcbBytes)
  1308. {
  1309. DEBUG_ENTER((DBG_TRANSDAT,
  1310. Hresult,
  1311. "CTransData::GetReadBuffer",
  1312. "this=%#x, %#x, %#x",
  1313. this, ppBuffer, pcbBytes
  1314. ));
  1315. PerfDbgLog(tagCTransData, this, "+CTransData::GetReadBuffer");
  1316. HRESULT hr;
  1317. TransAssert((_cbBufferSize >= _cbBufferFilled));
  1318. *ppBuffer = _lpBuffer + _cbBufferFilled;
  1319. *pcbBytes = _cbBufferSize - _cbBufferFilled;
  1320. hr = ((_cbBufferSize - _cbBufferFilled) > 0) ? NOERROR : E_FAIL;
  1321. PerfDbgLog3(tagCTransData, this, "-CTransData::GetReadBuffer (pBuffer:%lx,size:%ld,hr:%lx)",
  1322. *ppBuffer, *pcbBytes, hr);
  1323. DEBUG_LEAVE(hr);
  1324. return hr;
  1325. }
  1326. //+---------------------------------------------------------------------------
  1327. //
  1328. // Method: CTransData::OnDataInBuffer
  1329. //
  1330. // Synopsis:
  1331. //
  1332. // Arguments: [pBuffer] --
  1333. // [cbBytesAvailable] --
  1334. // [dwBytesTotal] --
  1335. //
  1336. // Returns:
  1337. //
  1338. // History: 1-27-96 JohannP (Johann Posch) Created
  1339. //
  1340. // Notes:
  1341. //
  1342. //----------------------------------------------------------------------------
  1343. STDMETHODIMP CTransData::OnDataInBuffer(BYTE *pBuffer, DWORD cbBytesRead, DWORD dwBytesTotal)
  1344. {
  1345. DEBUG_ENTER((DBG_TRANSDAT,
  1346. Hresult,
  1347. "CTransData::OnDataInBuffer",
  1348. "this=%#x, %#x, %#x, %#x",
  1349. this, pBuffer, cbBytesRead, dwBytesTotal
  1350. ));
  1351. PerfDbgLog(tagCTransData, this, "+CTransData::OnDataInBuffer");
  1352. HRESULT hr = NOERROR;
  1353. _cbTotalBytesRead += cbBytesRead;
  1354. _cbBufferFilled += cbBytesRead;
  1355. PerfDbgLog1(tagCTransData, this, "-CTransData::OnDataInBuffer (hr:%lx)", hr);
  1356. DEBUG_LEAVE(hr);
  1357. return hr;
  1358. }
  1359. //+---------------------------------------------------------------------------
  1360. //
  1361. // Method: CTransData::OnDataReceived
  1362. //
  1363. // Synopsis:
  1364. //
  1365. // Arguments: [cbBytesAvailable] --
  1366. // [dwBytesTotalRead] --
  1367. // [dwTotalSize] --
  1368. //
  1369. // Returns:
  1370. //
  1371. // History: 2-23-96 JohannP (Johann Posch) Created
  1372. //
  1373. // Notes:
  1374. //
  1375. //----------------------------------------------------------------------------
  1376. STDMETHODIMP CTransData::OnDataReceived(DWORD grfBSC, DWORD cbBytesAvailable, DWORD dwTotalSize, DWORD *pcbNewAvailable)
  1377. {
  1378. DEBUG_ENTER((DBG_TRANSDAT,
  1379. Hresult,
  1380. "CTransData::OnDataReceived",
  1381. "this=%#x, %#x, %#x, %#x, %#x",
  1382. this, grfBSC, cbBytesAvailable, dwTotalSize, pcbNewAvailable
  1383. ));
  1384. PerfDbgLog4(tagCTransData, this, "+CTransData::OnDataReceived (_ds:%s, grfBSC:%lx, cbBytesAvailable:%ld, _cbTotalBytesRead:%ld)",
  1385. GetDataSinkName(_ds), grfBSC, cbBytesAvailable, _cbTotalBytesRead);
  1386. HRESULT hr = NOERROR;
  1387. *pcbNewAvailable = cbBytesAvailable;
  1388. _grfBSC |= grfBSC;
  1389. switch (_ds)
  1390. {
  1391. case DataSink_StreamNoCopyData:
  1392. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  1393. case DataSink_StreamBindToObject:
  1394. {
  1395. DWORD dwNewData = 0;
  1396. TransAssert((_pProt && _cbDataSniffMin));
  1397. // _cbTotalBytesRead = # of bytes read so far
  1398. if (_cbTotalBytesRead < _cbDataSniffMin)
  1399. {
  1400. // no bytes read so far
  1401. TransAssert((_cbTotalBytesRead < _cbDataSniffMin));
  1402. // read data into buffer and report progess
  1403. hr = _pProt->Read(_lpBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData);
  1404. _cbTotalBytesRead += dwNewData;
  1405. _cbBufferFilled += dwNewData;
  1406. // now check if this is docfile
  1407. // if so download at least 2k
  1408. if (!_fDocFile && _cbBufferFilled && (IsDocFile(_lpBuffer, _cbBufferFilled) == S_OK))
  1409. {
  1410. _fDocFile = TRUE;
  1411. _cbDataSniffMin = (dwTotalSize && dwTotalSize < DATASNIFSIZEDOCFILE_MIN) ? dwTotalSize : DATASNIFSIZEDOCFILE_MIN;
  1412. }
  1413. if ((hr == E_PENDING) && (_cbTotalBytesRead < _cbDataSniffMin))
  1414. {
  1415. // do not report anything - wait until we get more data
  1416. // a request is pending at this time
  1417. // need more data to sniff properly
  1418. hr = S_NEEDMOREDATA;
  1419. }
  1420. else if (hr == NOERROR || hr == E_PENDING)
  1421. {
  1422. TransAssert((_cbTotalBytesRead != 0));
  1423. // report the data we have in the buffer or
  1424. // the available #
  1425. DWORD cbBytesReport = (cbBytesAvailable > _cbTotalBytesRead) ? cbBytesAvailable : _cbTotalBytesRead + 1;
  1426. if (dwTotalSize && ((cbBytesReport > dwTotalSize)))
  1427. {
  1428. cbBytesReport = dwTotalSize;
  1429. }
  1430. *pcbNewAvailable = cbBytesReport;
  1431. }
  1432. }
  1433. }
  1434. break;
  1435. case DataSink_File:
  1436. case DataSink_Storage:
  1437. case DataSink_StreamOnFile:
  1438. {
  1439. DWORD dwNewData = 0;
  1440. TransAssert((_pProt));
  1441. if (_cbTotalBytesRead < _cbDataSniffMin)
  1442. {
  1443. _cbDataSniffMin = (dwTotalSize && dwTotalSize < DATASNIFSIZEDOCFILE_MIN) ? dwTotalSize : DATASNIFSIZEDOCFILE_MIN;
  1444. // read data into buffer and report progess
  1445. hr = _pProt->Read(_lpBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData);
  1446. _cbTotalBytesRead += dwNewData;
  1447. _cbBufferFilled += dwNewData;
  1448. if ((hr == E_PENDING) && (_cbTotalBytesRead < _cbDataSniffMin))
  1449. {
  1450. // do not report anything - wait until we get more data
  1451. // a request is pending at this time
  1452. // need more data to sniff properly
  1453. hr = S_NEEDMOREDATA;
  1454. }
  1455. else if (hr == NOERROR || hr == E_PENDING)
  1456. {
  1457. TransAssert((_cbTotalBytesRead != 0));
  1458. }
  1459. *pcbNewAvailable = _cbTotalBytesRead;
  1460. }
  1461. // Note: read until pending or eof and report progress
  1462. // this is important to keep the download going
  1463. if (hr == NOERROR)
  1464. {
  1465. // reset the buffer - don't overwrite sniffing data
  1466. _cbBufferFilled = (_fMimeTypeVerified) ? 0 : _cbDataSniffMin;
  1467. // bugbug: need special flag which indicates not to read if fully available
  1468. //if (!(grfBSC & BSCF_DATAFULLYAVAILABLE))
  1469. if (1)
  1470. {
  1471. //read as much data until S_OK or E_PENDING or error
  1472. do
  1473. {
  1474. hr = _pProt->Read(_lpBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData);
  1475. _cbTotalBytesRead += dwNewData;
  1476. } while (hr == NOERROR);
  1477. // report available data
  1478. if (hr == NOERROR || hr == E_PENDING)
  1479. {
  1480. TransAssert((_cbTotalBytesRead != 0));
  1481. }
  1482. *pcbNewAvailable = (cbBytesAvailable > _cbTotalBytesRead) ? _cbTotalBytesRead : _cbTotalBytesRead;
  1483. }
  1484. else
  1485. {
  1486. TransAssert((dwTotalSize == cbBytesAvailable));
  1487. *pcbNewAvailable = dwTotalSize;
  1488. }
  1489. }
  1490. }
  1491. break;
  1492. default:
  1493. TransAssert((FALSE && "CTransData::OnDataReceived -- Invalid data location"));
  1494. break;
  1495. }
  1496. // cbBytesAvailable might be off be 1
  1497. //TransAssert((cbBytesAvailable <= *pcbNewAvailable));
  1498. PerfDbgLog1(tagCTransData, this, "-CTransData::OnDataReceived (hr:%lx)", hr);
  1499. DEBUG_LEAVE(hr);
  1500. return hr;
  1501. }
  1502. //+---------------------------------------------------------------------------
  1503. //
  1504. // Method: CTransData::OnStart
  1505. //
  1506. // Synopsis:
  1507. //
  1508. // Arguments: (none)
  1509. //
  1510. // Returns:
  1511. //
  1512. // History: 2-23-96 JohannP (Johann Posch) Created
  1513. //
  1514. // Notes: TransData does not keep CINet alive
  1515. // and will NOT call delete on it!
  1516. //
  1517. //----------------------------------------------------------------------------
  1518. STDMETHODIMP CTransData::OnStart(IOInetProtocol *pCINet)
  1519. {
  1520. DEBUG_ENTER((DBG_TRANSDAT,
  1521. Hresult,
  1522. "CTransData::OnStart",
  1523. "this=%#x, %#x",
  1524. this, pCINet
  1525. ));
  1526. HRESULT hr = NOERROR;
  1527. PerfDbgLog(tagCTransData, this, "+CTransData::OnStart");
  1528. TransAssert((pCINet != NULL));
  1529. if (_pProt)
  1530. {
  1531. _pProt->Release();
  1532. _pProt = NULL;
  1533. }
  1534. switch (_ds)
  1535. {
  1536. case DataSink_StreamBindToObject:
  1537. case DataSink_StreamNoCopyData:
  1538. case DataSink_StreamOnFile:
  1539. case DataSink_GenericStream:
  1540. {
  1541. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  1542. // this point is not addref by CTransData
  1543. TransAssert((_pProt == NULL));
  1544. _pProt = pCINet;
  1545. }
  1546. break;
  1547. case DataSink_Storage:
  1548. {
  1549. TransAssert((_formatetc.tymed == TYMED_ISTORAGE));
  1550. // this point is not addref by CTransData
  1551. TransAssert((_pProt == NULL));
  1552. _pProt = pCINet;
  1553. }
  1554. break;
  1555. case DataSink_File:
  1556. {
  1557. TransAssert((_formatetc.tymed == TYMED_FILE));
  1558. // this point is not addref by CTransData
  1559. TransAssert((_pProt == NULL));
  1560. _pProt = pCINet;
  1561. }
  1562. break;
  1563. default:
  1564. TransAssert((FALSE && "Invalid data location"));
  1565. break;
  1566. }
  1567. if (_pProt)
  1568. {
  1569. _pProt->AddRef();
  1570. }
  1571. else
  1572. {
  1573. TransAssert((FALSE));
  1574. }
  1575. PerfDbgLog1(tagCTransData, this, "-CTransData::OnStart (hr:%lx)", hr);
  1576. DEBUG_LEAVE(hr);
  1577. return hr;
  1578. }
  1579. //+---------------------------------------------------------------------------
  1580. //
  1581. // Method: CTransData::OnTerminate
  1582. //
  1583. // Synopsis:
  1584. //
  1585. // Arguments: (none)
  1586. //
  1587. // Returns:
  1588. //
  1589. // History: 1-27-96 JohannP (Johann Posch) Created
  1590. //
  1591. // Notes:
  1592. //
  1593. //----------------------------------------------------------------------------
  1594. STDMETHODIMP CTransData::OnTerminate()
  1595. {
  1596. DEBUG_ENTER((DBG_TRANSDAT,
  1597. Hresult,
  1598. "CTransData::OnTerminate",
  1599. "this=%#x",
  1600. this
  1601. ));
  1602. HRESULT hr = NOERROR;
  1603. PerfDbgLog(tagCTransData, this, "+CTransData::OnTerminate");
  1604. TransAssert((_TransDataState < TransData_ProtoTerminated));
  1605. switch (_ds)
  1606. {
  1607. case DataSink_Storage:
  1608. case DataSink_File:
  1609. {
  1610. TransAssert((_formatetc.tymed == TYMED_FILE) || (_formatetc.tymed == TYMED_ISTORAGE));
  1611. DbgLog2(tagCTransData, this, ">>> CTransData::OnTerminate (hr:%lx, _wzTempFile:%ws)", hr, _wzFileName);
  1612. }
  1613. break;
  1614. case DataSink_StreamBindToObject:
  1615. case DataSink_StreamNoCopyData:
  1616. case DataSink_StreamOnFile:
  1617. case DataSink_GenericStream:
  1618. {
  1619. TransAssert((_formatetc.tymed == TYMED_ISTREAM));
  1620. TransAssert((_pProt != NULL));
  1621. }
  1622. break;
  1623. default:
  1624. TransAssert((FALSE && "Invalid data location"));
  1625. break;
  1626. }
  1627. if (_pBndCtx)
  1628. {
  1629. _pBndCtx->Release();
  1630. _pBndCtx = NULL;
  1631. }
  1632. PerfDbgLog1(tagCTransData, this, "-CTransData::OnTerminate (hr:%lx)", hr);
  1633. DEBUG_LEAVE(hr);
  1634. return hr;
  1635. }
  1636. //+---------------------------------------------------------------------------
  1637. //
  1638. // Method: CTransData::FindFormatETC
  1639. //
  1640. // Synopsis:
  1641. //
  1642. // Arguments: (none)
  1643. //
  1644. // Returns:
  1645. //
  1646. // History: 1-27-96 JohannP (Johann Posch) Created
  1647. //
  1648. // Notes:
  1649. //
  1650. //----------------------------------------------------------------------------
  1651. STDMETHODIMP CTransData::FindFormatETC()
  1652. {
  1653. DEBUG_ENTER((DBG_TRANSDAT,
  1654. Hresult,
  1655. "CTransData::FindFormatETC",
  1656. "this=%#x",
  1657. this
  1658. ));
  1659. HRESULT hr = NOERROR;
  1660. PerfDbgLog1(tagCTransData, this, "+CTransData::FindFormatETC (_cbBufferFilled:%ld)", _cbBufferFilled);
  1661. _formatetc.ptd = NULL;
  1662. _formatetc.dwAspect = DVASPECT_CONTENT;
  1663. _formatetc.lindex = -1;
  1664. _formatetc.cfFormat = 0;
  1665. TransAssert(( _formatetc.tymed == TYMED_ISTREAM
  1666. || _formatetc.tymed == TYMED_FILE
  1667. || _formatetc.tymed == TYMED_ISTORAGE ));
  1668. LPCWSTR pwzStrOrg = GetMimeType();
  1669. LPCWSTR pwzStr = pwzStrOrg;
  1670. // If not already done so, attempt to
  1671. // verify mime type by examining data.
  1672. if (!_fMimeTypeVerified)
  1673. {
  1674. DWORD dwFlags = 0;
  1675. DWORD dwSniffFlags = 0;
  1676. DWORD cbLen = sizeof(dwFlags);
  1677. LPWSTR pwzFileName = GetFileName();
  1678. LPWSTR pwzStrOut = 0;
  1679. // the buffer should contain data if the no mime
  1680. TransAssert(( (_cbBufferFilled == 0 && (pwzStr || pwzFileName))
  1681. || ( _cbBufferFilled != 0) ));
  1682. FindMimeFromData(NULL, pwzFileName,_lpBuffer, _cbBufferFilled, pwzStrOrg, dwSniffFlags, &pwzStrOut, 0);
  1683. if (pwzStrOut)
  1684. {
  1685. SetMimeType(pwzStrOut);
  1686. pwzStr = GetMimeType();
  1687. }
  1688. delete [] pwzStrOut;
  1689. _fMimeTypeVerified = TRUE;
  1690. }
  1691. // the new mime should never be NULL if we had a proposed mime
  1692. TransAssert(( (pwzStrOrg && pwzStr)
  1693. || (pwzStrOrg == NULL) ));
  1694. if (pwzStr)
  1695. {
  1696. char szMime[SZMIMESIZE_MAX];
  1697. W2A(pwzStr, szMime, SZMIMESIZE_MAX);
  1698. CLIPFORMAT cfType;
  1699. if (FindMediaTypeW(pwzStr,&cfType) != NOERROR)
  1700. {
  1701. _formatetc.cfFormat = (CLIPFORMAT) RegisterClipboardFormat(szMime);
  1702. }
  1703. else
  1704. {
  1705. _formatetc.cfFormat = cfType;
  1706. }
  1707. }
  1708. else
  1709. {
  1710. _formatetc.cfFormat = CF_NULL;
  1711. }
  1712. // Check if the format that we got is one of the format that
  1713. // is requested, and if so, use it
  1714. #ifdef UNUSED
  1715. if (_pEnumFE)
  1716. {
  1717. FORMATETC FmtetcT;
  1718. BOOL fDone = FALSE;
  1719. _pEnumFE->Reset();
  1720. while (!fDone && ((hr = _pEnumFE->Next(1, &FmtetcT,NULL)) == NOERROR))
  1721. {
  1722. TransAssert((SUCCEEDED(hr)));
  1723. if (FmtetcT.cfFormat == _cfFormat)
  1724. {
  1725. _formatetc.cfFormat = _cfFormat;
  1726. }
  1727. }
  1728. }
  1729. #endif //UNUSED
  1730. PerfDbgLog3(tagCTransData, this, "-CTransData::FindFormatETC (hr:%lx, szStr:%ws, _formatetc.cfFormat:%lx)", hr, pwzStr?pwzStr:L"", _formatetc.cfFormat);
  1731. DEBUG_LEAVE(hr);
  1732. return hr;
  1733. }
  1734. //+---------------------------------------------------------------------------
  1735. //
  1736. // Method: CTransData::GetAcceptStr
  1737. //
  1738. // Synopsis:
  1739. //
  1740. // Arguments: [ppwzStr] --
  1741. // [pcElements] --
  1742. //
  1743. // Returns:
  1744. //
  1745. // History: 3-29-96 JohannP (Johann Posch) Created
  1746. //
  1747. // Notes:
  1748. //
  1749. //----------------------------------------------------------------------------
  1750. STDMETHODIMP CTransData::GetAcceptStr(LPWSTR *ppwzStr, ULONG *pcElements)
  1751. {
  1752. DEBUG_ENTER((DBG_TRANSDAT,
  1753. Hresult,
  1754. "CTransData::GetAcceptStr",
  1755. "this=%#x, %#x, %#x",
  1756. this, ppwzStr, pcElements
  1757. ));
  1758. HRESULT hr = NOERROR;
  1759. PerfDbgLog(tagCTransData, this, "+CTransData::GetAcceptStr");
  1760. IEnumFORMATETC *pIEnumFE = NULL;
  1761. TransAssert((ppwzStr));
  1762. TransAssert((*pcElements > 0));
  1763. CHAR pszUnknownName[MAX_PATH];
  1764. ULONG cMimes = 0;
  1765. *ppwzStr = 0;
  1766. hr = GetObjectParam(_pBndCtx, REG_ENUMFORMATETC, IID_IEnumFORMATETC, (IUnknown**)&pIEnumFE);
  1767. if (hr == NOERROR)
  1768. {
  1769. BOOL fCF_NULL = FALSE;
  1770. #define ELEMENTS 10
  1771. ULONG cElementsIn = ELEMENTS;
  1772. ULONG cElements = 0;
  1773. FORMATETC rgFormatEtc[ELEMENTS];
  1774. pIEnumFE->Reset();
  1775. // find # of elements
  1776. do
  1777. {
  1778. ULONG cEl = 0;
  1779. hr = pIEnumFE->Next(cElementsIn, rgFormatEtc ,&cEl);
  1780. cElements += cEl;
  1781. } while (hr == S_OK);
  1782. UrlMkAssert((cElements > 0));
  1783. if ( (cElements > 0)
  1784. && (hr == S_OK || hr == S_FALSE))
  1785. {
  1786. {
  1787. ULONG cElementsOut = 0;
  1788. pIEnumFE->Reset();
  1789. do
  1790. {
  1791. ULONG cEl = 0;
  1792. FORMATETC *pFmtEtc = rgFormatEtc;
  1793. hr = pIEnumFE->Next(cElementsIn, rgFormatEtc ,&cEl);
  1794. cElementsOut += cEl;
  1795. // (hr==S_FALSE) => (cElementsOut==cEl)
  1796. UrlMkAssert((!(hr==S_FALSE) || (cElementsOut == cElements)));
  1797. // On the last call to ->Next() enumerator, we get back an S_FALSE
  1798. // if the # of elements received (cEl) < asked for (cElementsIn)
  1799. if ((cElementsOut == cElements) && (hr == S_FALSE))
  1800. hr = S_OK;
  1801. for (ULONG i = 0; i < cEl; i++)
  1802. {
  1803. if( cMimes >= (*pcElements - 1) )
  1804. {
  1805. // exceeding the income array size, stop
  1806. break;
  1807. }
  1808. LPSTR szFormat = NULL;
  1809. CLIPFORMAT cfFormat = (pFmtEtc + i)->cfFormat;
  1810. if (cfFormat == CF_NULL)
  1811. {
  1812. fCF_NULL = TRUE;
  1813. }
  1814. else
  1815. {
  1816. hr = FindMediaString(cfFormat, &szFormat);
  1817. if (hr != NOERROR || !szFormat)
  1818. {
  1819. // unknown cfFormat
  1820. if( GetClipboardFormatName(cfFormat, pszUnknownName, MAX_PATH))
  1821. {
  1822. hr = NOERROR;
  1823. szFormat = pszUnknownName;
  1824. }
  1825. else
  1826. {
  1827. // word97 will send out cfFormat=1
  1828. // which associated to "" string
  1829. hr = NOERROR;
  1830. }
  1831. }
  1832. if( szFormat )
  1833. {
  1834. *(ppwzStr + cMimes)= NULL;
  1835. *(ppwzStr + cMimes) = DupA2W(szFormat);
  1836. if( *(ppwzStr + cMimes) )
  1837. {
  1838. cMimes++;
  1839. }
  1840. else
  1841. {
  1842. hr = E_OUTOFMEMORY;
  1843. break;
  1844. }
  1845. }
  1846. }
  1847. }
  1848. } while ( (cElementsOut < cElements) && (hr == NOERROR) );
  1849. // append the cf_null (*/*)
  1850. if( hr == NOERROR && (fCF_NULL || (cMimes == 0)) )
  1851. {
  1852. *(ppwzStr + cMimes) = DupA2W(g_szCF_NULL);
  1853. if( !*(ppwzStr + cMimes) )
  1854. {
  1855. hr = E_OUTOFMEMORY;
  1856. }
  1857. else
  1858. {
  1859. cMimes++;
  1860. hr = NOERROR;
  1861. }
  1862. }
  1863. if( hr == NOERROR )
  1864. {
  1865. *(ppwzStr + cMimes) = NULL;
  1866. }
  1867. }
  1868. }
  1869. pIEnumFE->Release();
  1870. }
  1871. else
  1872. {
  1873. {
  1874. *ppwzStr = DupA2W(g_szCF_NULL);
  1875. if( *ppwzStr )
  1876. {
  1877. cMimes = 1;
  1878. *(ppwzStr + 1) = NULL;
  1879. hr = NOERROR;
  1880. }
  1881. else
  1882. {
  1883. hr = E_OUTOFMEMORY;
  1884. }
  1885. }
  1886. }
  1887. if( hr == NOERROR )
  1888. {
  1889. *pcElements = cMimes;
  1890. }
  1891. else
  1892. {
  1893. *pcElements = 0;
  1894. if( cMimes >= 1 )
  1895. {
  1896. for( ULONG i = 0; i < cMimes; i ++)
  1897. {
  1898. delete [] *(ppwzStr + i);
  1899. }
  1900. }
  1901. *ppwzStr = NULL;
  1902. }
  1903. PerfDbgLog1(tagCTransData, this, "-CTransData::GetAcceptStr (hr:%lx)", hr);
  1904. DEBUG_LEAVE(hr);
  1905. return hr;
  1906. }
  1907. //+---------------------------------------------------------------------------
  1908. //
  1909. // Method: CTransData::GetAcceptMimes
  1910. //
  1911. // Synopsis:
  1912. //
  1913. // Arguments: [ppStr] --
  1914. //
  1915. // Returns:
  1916. //
  1917. // History: 3-29-96 JohannP (Johann Posch) Created
  1918. //
  1919. // Notes:
  1920. //
  1921. //----------------------------------------------------------------------------
  1922. STDMETHODIMP CTransData::GetAcceptMimes(LPWSTR *ppwzStr, ULONG cel, ULONG *pcElements)
  1923. {
  1924. DEBUG_ENTER((DBG_TRANSDAT,
  1925. Hresult,
  1926. "CTransData::GetAcceptMimes",
  1927. "this=%#x, %#x, %#x, %#x",
  1928. this, ppwzStr, cel, pcElements
  1929. ));
  1930. HRESULT hr = NOERROR;
  1931. PerfDbgLog(tagCTransData, this, "+CTransData::GetAcceptMimes");
  1932. TransAssert((ppwzStr && pcElements && *pcElements));
  1933. if (ppwzStr && pcElements)
  1934. {
  1935. if( *pcElements > 1 )
  1936. {
  1937. hr = GetAcceptStr( ppwzStr, pcElements );
  1938. }
  1939. else if( *pcElements == 1)
  1940. {
  1941. // zero terminated
  1942. *ppwzStr = NULL;
  1943. }
  1944. else
  1945. {
  1946. hr = E_INVALIDARG;
  1947. }
  1948. }
  1949. else
  1950. {
  1951. hr = E_INVALIDARG;
  1952. }
  1953. PerfDbgLog1(tagCTransData, this, "-CTransData::GetAcceptMimes (hr:%lx)", hr);
  1954. DEBUG_LEAVE(hr);
  1955. return hr;
  1956. }
  1957. //+---------------------------------------------------------------------------
  1958. //
  1959. // Method: CTransData::SetClipFormat
  1960. //
  1961. // Synopsis:
  1962. //
  1963. // Arguments: [cfFormat] --
  1964. //
  1965. // Returns:
  1966. //
  1967. // History: 1-27-96 JohannP (Johann Posch) Created
  1968. //
  1969. // Notes:
  1970. //
  1971. //----------------------------------------------------------------------------
  1972. STDMETHODIMP CTransData::SetClipFormat(CLIPFORMAT cfFormat)
  1973. {
  1974. DEBUG_ENTER((DBG_TRANSDAT,
  1975. Hresult,
  1976. "CTransData::SetClipFormat",
  1977. "this=%#x, %#x",
  1978. this, cfFormat
  1979. ));
  1980. HRESULT hr = NOERROR;
  1981. PerfDbgLog(tagCTransData, this, "+CTransData::SetClipFormat");
  1982. _cfFormat = cfFormat;
  1983. PerfDbgLog1(tagCTransData, this, "-CTransData::SetClipFormat (hr:%lx)", hr);
  1984. DEBUG_LEAVE(hr);
  1985. return hr;
  1986. }
  1987. //+---------------------------------------------------------------------------
  1988. //
  1989. // Method: CTransData::IsObjectReady
  1990. //
  1991. // Synopsis:
  1992. //
  1993. // Arguments: (none)
  1994. //
  1995. // Returns:
  1996. //
  1997. // History: 1-27-96 JohannP (Johann Posch) Created
  1998. //
  1999. // Notes:
  2000. //
  2001. //----------------------------------------------------------------------------
  2002. STDMETHODIMP CTransData::IsObjectReady( )
  2003. {
  2004. DEBUG_ENTER((DBG_TRANSDAT,
  2005. Hresult,
  2006. "CTransData::IsObjectReady",
  2007. "this=%#x",
  2008. this
  2009. ));
  2010. HRESULT hr = E_FAIL;
  2011. PerfDbgLog(tagCTransData, this, "+CTransData::IsObjectReady");
  2012. // check size and
  2013. if ((_cbDataSize != 0) && (_cbDataSize == _cbTotalBytesRead))
  2014. {
  2015. hr = NOERROR;
  2016. }
  2017. PerfDbgLog3(tagCTransData, this, "-CTransData::IsObjectReady (hr:%lx, _cbDataSize:%ld, _cbTotalBytesRead:%ld)", hr, _cbDataSize, _cbTotalBytesRead);
  2018. DEBUG_LEAVE(hr);
  2019. return hr;
  2020. }
  2021. //+---------------------------------------------------------------------------
  2022. //
  2023. // Method: CTransData::InProgress
  2024. //
  2025. // Synopsis:
  2026. //
  2027. // Arguments: (none)
  2028. //
  2029. // Returns:
  2030. //
  2031. // History: 1-27-96 JohannP (Johann Posch) Created
  2032. //
  2033. // Notes:
  2034. //
  2035. //----------------------------------------------------------------------------
  2036. STDMETHODIMP CTransData::InProgress()
  2037. {
  2038. DEBUG_ENTER((DBG_TRANSDAT,
  2039. Hresult,
  2040. "CTransData::InProgress",
  2041. "this=%#x",
  2042. this
  2043. ));
  2044. HRESULT hr = S_FALSE;
  2045. PerfDbgLog(tagCTransData, this, "+CTransData::InProgress");
  2046. if (_grfBSC & (BSCF_LASTDATANOTIFICATION | BSCF_FIRSTDATANOTIFICATION))
  2047. {
  2048. hr = S_FALSE;
  2049. }
  2050. else if (_cbTotalBytesRead == 0)
  2051. {
  2052. // check if some bits already in the buffer
  2053. hr = S_OK;
  2054. }
  2055. PerfDbgLog1(tagCTransData, this, "-CTransData::InProgress (hr:%lx)", hr);
  2056. DEBUG_LEAVE(hr);
  2057. return hr;
  2058. }
  2059. //+---------------------------------------------------------------------------
  2060. //
  2061. // Method: CTransData::GetFileName
  2062. //
  2063. // Synopsis:
  2064. //
  2065. // Arguments: (none)
  2066. //
  2067. // Returns:
  2068. //
  2069. // History: 1-27-96 JohannP (Johann Posch) Created
  2070. //
  2071. // Notes:
  2072. //
  2073. //----------------------------------------------------------------------------
  2074. LPWSTR CTransData::GetFileName()
  2075. {
  2076. DEBUG_ENTER((DBG_TRANSDAT,
  2077. Pointer,
  2078. "CTransData::GetFileName",
  2079. "this=%#x",
  2080. this
  2081. ));
  2082. PerfDbgLog(tagCTransData, this, "+CTransData::GetFileName");
  2083. LPWSTR pwzFileName = NULL;
  2084. //TransAssert((_wzFileName[0] != 0));
  2085. if (_wzFileName[0] != 0)
  2086. {
  2087. pwzFileName = _wzFileName;
  2088. }
  2089. PerfDbgLog1(tagCTransData, this, "-CTransData::GetFileName (szFile:%ws)", pwzFileName?pwzFileName:L"");
  2090. DEBUG_LEAVE(pwzFileName);
  2091. return pwzFileName;
  2092. }
  2093. //+---------------------------------------------------------------------------
  2094. //
  2095. // Method: CTransData::GetClassID
  2096. //
  2097. // Synopsis:
  2098. //
  2099. // Arguments: [pclsid] --
  2100. // [fReOpen] --
  2101. //
  2102. // Returns:
  2103. //
  2104. // History: 1-27-96 JohannP (Johann Posch) Created
  2105. //
  2106. // Notes:
  2107. //
  2108. //----------------------------------------------------------------------------
  2109. STDMETHODIMP CTransData::GetClassID(CLSID clsidIn, CLSID *pclsid)
  2110. {
  2111. DEBUG_ENTER((DBG_TRANSDAT,
  2112. Hresult,
  2113. "CTransData::GetClassID",
  2114. "this=%#x, %#x, %#x",
  2115. this, clsidIn, pclsid
  2116. ));
  2117. PerfDbgLog(tagCTransData, this, "+CTransData::GetClassID");
  2118. WCHAR wzMime[SZMIMESIZE_MAX];
  2119. HRESULT hr;
  2120. LPWSTR pwzTempFile = NULL;
  2121. DWORD fIgnoreMimeClsid = GetBindFlags() & BINDF_IGNOREMIMECLSID;
  2122. LPCWSTR pwzMime = GetMimeType();
  2123. pwzTempFile = GetFileName();
  2124. if ( (_cbBufferFilled != 0)
  2125. && (_cbTotalBytesRead <= _cbBufferSize)
  2126. && (IsDocFile(_lpBuffer, _cbBufferFilled) == S_OK))
  2127. {
  2128. _fDocFile = TRUE;
  2129. _fMimeTypeVerified = TRUE;
  2130. // Storage file (docfile) case
  2131. // GetClassFileOrMime takes care of class mapping
  2132. hr = GetClassFileOrMime2(_pBndCtx, pwzTempFile, _lpBuffer, _cbBufferFilled, pwzMime, 0, pclsid, fIgnoreMimeClsid);
  2133. if (hr != NOERROR)
  2134. {
  2135. // S_FALSE means keep downloading
  2136. hr = S_FALSE;
  2137. }
  2138. }
  2139. else
  2140. {
  2141. if (!_fMimeTypeVerified)
  2142. {
  2143. DWORD dwFlags = 0;
  2144. DWORD dwSniffFlags = 0;
  2145. DWORD cbLen = sizeof(dwFlags);
  2146. LPWSTR pwzStr = 0;
  2147. FindMimeFromData(NULL, pwzTempFile, _lpBuffer, _cbBufferFilled, pwzMime, dwSniffFlags, &pwzStr, 0);
  2148. if (pwzStr)
  2149. {
  2150. SetMimeType(pwzStr);
  2151. }
  2152. _fMimeTypeVerified = TRUE;
  2153. delete [] pwzStr;
  2154. }
  2155. hr = GetClassFileOrMime2(_pBndCtx, pwzTempFile, NULL, 0, pwzMime, 0, pclsid, fIgnoreMimeClsid);
  2156. }
  2157. #if DBG==1
  2158. if (hr == NOERROR)
  2159. {
  2160. LPOLESTR pszStr;
  2161. StringFromCLSID(*pclsid, &pszStr);
  2162. DbgLog2(tagCTransData, this, "CTransData::GetClassID (file:%ws)(class:%ws)",
  2163. pwzTempFile, pszStr);
  2164. delete pszStr;
  2165. }
  2166. #endif
  2167. PerfDbgLog1(tagCTransData, this, "-CTransData::GetClassID (hr:%lx)", hr);
  2168. DEBUG_LEAVE(hr);
  2169. return hr;
  2170. }
  2171. //+---------------------------------------------------------------------------
  2172. //
  2173. // Method: CTransData::SetMimeType
  2174. //
  2175. // Synopsis:
  2176. //
  2177. // Arguments: [pszMime] --
  2178. //
  2179. // Returns:
  2180. //
  2181. // History: 2-07-96 JohannP (Johann Posch) Created
  2182. //
  2183. // Notes:
  2184. //
  2185. //----------------------------------------------------------------------------
  2186. STDMETHODIMP CTransData::SetMimeType(LPCWSTR pwzMime)
  2187. {
  2188. DEBUG_ENTER((DBG_TRANSDAT,
  2189. Hresult,
  2190. "CTransData::SetMimeType",
  2191. "this=%#x, %.80wq",
  2192. this, pwzMime
  2193. ));
  2194. PerfDbgLog2(tagCTransData, this, "+CTransData::SetMimeType (OldMime:%ws; MimeStr:%ws)", _wzMime?_wzMime:L"", pwzMime?pwzMime:L"");
  2195. HRESULT hr = NOERROR;
  2196. if (pwzMime)
  2197. {
  2198. #if DBG_XXX
  2199. if (pwzMime)
  2200. {
  2201. if ( !wcscmp(_wzMime, CFWSTR_MIME_HTML)
  2202. || !wcscmp(_wzMime, CFWSTR_MIME_TEXT))
  2203. {
  2204. if ( !wcscmp(pwzMime, CFWSTR_MIME_RAWDATA)
  2205. || !wcscmp(pwzMime,L"application/octet-stream"))
  2206. {
  2207. DbgLog2(tagCTransDataErr, "=== SetMimeType: OldMime:%ws, NewMime:%ws",
  2208. _wzMime, pwzMime);
  2209. //TransAssert((FALSE));
  2210. }
  2211. }
  2212. }
  2213. if (_wzMime[0] != 0 && strcmp(_wzMime,pwzMime))
  2214. {
  2215. DbgLog2(tagTransDataErr, "=== SetMimeType: OldMime:%s, NewMime:%s",
  2216. _wzMime, pwzMime);
  2217. }
  2218. #endif //DBG
  2219. DWORD cLen = wcslen((LPWSTR)pwzMime);
  2220. if (cLen >= SZMIMESIZE_MAX)
  2221. {
  2222. cLen = SZMIMESIZE_MAX - 1;
  2223. wcsncpy(_wzMime, (LPWSTR)pwzMime, cLen);
  2224. _wzMime[cLen] = 0;
  2225. }
  2226. else
  2227. {
  2228. wcscpy(_wzMime, (LPWSTR)pwzMime);
  2229. }
  2230. }
  2231. else
  2232. {
  2233. DbgLog(tagCTransDataErr, this, "CTransData::SetMimeType ->invalid mime");
  2234. }
  2235. PerfDbgLog2(tagCTransData, this, "-CTransData::SetMimeType (hr:%lx, Mime:%ws)", hr,_wzMime?_wzMime:L"");
  2236. DEBUG_LEAVE(hr);
  2237. return hr;
  2238. }
  2239. //+---------------------------------------------------------------------------
  2240. //
  2241. // Method: CTransData::SetFileName
  2242. //
  2243. // Synopsis:
  2244. //
  2245. // Arguments: [szFile] --
  2246. //
  2247. // Returns:
  2248. //
  2249. // History: 1-27-96 JohannP (Johann Posch) Created
  2250. //
  2251. // Notes:
  2252. //
  2253. //----------------------------------------------------------------------------
  2254. STDMETHODIMP CTransData::SetFileName(LPWSTR pwzFile)
  2255. {
  2256. DEBUG_ENTER((DBG_TRANSDAT,
  2257. Hresult,
  2258. "CTransData::SetFileName",
  2259. "this=%#x, %.80wq",
  2260. this, pwzFile
  2261. ));
  2262. PerfDbgLog(tagCTransData, this, "+CTransData::SetFileName");
  2263. TransAssert((pwzFile));
  2264. if(pwzFile)
  2265. {
  2266. wcscpy(_wzFileName, pwzFile);
  2267. }
  2268. PerfDbgLog2(tagCTransData, this, "-CTransData::SetFileName (_wzFileName:%ws, hr:%lx)", _wzFileName?_wzFileName:L"", NOERROR);
  2269. DEBUG_LEAVE(NOERROR);
  2270. return NOERROR;
  2271. }
  2272. //+---------------------------------------------------------------------------
  2273. //
  2274. // Method: CTransData::GetMimeType
  2275. //
  2276. // Synopsis:
  2277. //
  2278. // Arguments: (none)
  2279. //
  2280. // Returns:
  2281. //
  2282. // History: 4-24-96 JohannP (Johann Posch) Created
  2283. //
  2284. // Notes:
  2285. //
  2286. //----------------------------------------------------------------------------
  2287. LPCWSTR CTransData::GetMimeType()
  2288. {
  2289. DEBUG_ENTER((DBG_TRANSDAT,
  2290. Pointer,
  2291. "CTransData::GetMimeType",
  2292. "this=%#x",
  2293. this
  2294. ));
  2295. PerfDbgLog(tagCTransData, this, "+CTransData::GetMimeType");
  2296. LPWSTR pwzStr = NULL;
  2297. if (_wzMime[0] != 0)
  2298. {
  2299. pwzStr = _wzMime;
  2300. }
  2301. PerfDbgLog1(tagCTransData, this, "-CTransData::GetMimeType (pStr:%ws)", pwzStr?pwzStr:L"");
  2302. DEBUG_LEAVE(pwzStr);
  2303. return pwzStr;
  2304. }
  2305. //+---------------------------------------------------------------------------
  2306. //
  2307. // Method: CTransData::OnEndofData()
  2308. //
  2309. // Synopsis:
  2310. //
  2311. // Arguments: (none)
  2312. //
  2313. // Returns:
  2314. //
  2315. // History: 7-30-97 DanpoZ(Danpo Zhang) Created
  2316. //
  2317. // Notes:
  2318. //
  2319. //----------------------------------------------------------------------------
  2320. void CTransData::OnEndofData()
  2321. {
  2322. DEBUG_ENTER((DBG_TRANSDAT,
  2323. None,
  2324. "CTransData::OnEndofData",
  2325. "this=%#x",
  2326. this
  2327. ));
  2328. PerfDbgLog1(tagCTransData, this, "+CTransData::OnEndofData(_ds:%ld)", _ds);
  2329. BOOL fNewStgMed = FALSE;
  2330. if (_pStgMed && _ds == DataSink_StreamOnFile && _pStgMed->pstm )
  2331. {
  2332. ((CReadOnlyStreamFile*)(_pStgMed->pstm))->SetDataFullyAvailable();
  2333. }
  2334. PerfDbgLog(tagCTransData, this, "-CTransData::OnEndofData");
  2335. DEBUG_LEAVE(0);
  2336. }