2 * Implements CLSID_FileWriter.
4 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
41 #include "quartz_private.h"
45 static const WCHAR QUARTZ_FileWriter_Name[] =
46 { 'F','i','l','e',' ','W','r','i','t','e','r',0 };
47 static const WCHAR QUARTZ_FileWriterPin_Name[] =
51 /* FIXME - add this flag to strmif.h */
52 #define AM_FILE_OVERWRITE 0x1
54 /***************************************************************************
56 * CFileWriterImpl methods
60 static HRESULT CFileWriterImpl_OnActive( CBaseFilterImpl* pImpl )
62 CFileWriterImpl_THIS(pImpl,basefilter);
64 FIXME( "(%p)\n", This );
69 static HRESULT CFileWriterImpl_OnInactive( CBaseFilterImpl* pImpl )
71 CFileWriterImpl_THIS(pImpl,basefilter);
73 FIXME( "(%p)\n", This );
78 static const CBaseFilterHandlers filterhandlers =
80 CFileWriterImpl_OnActive, /* pOnActive */
81 CFileWriterImpl_OnInactive, /* pOnInactive */
86 /***************************************************************************
88 * CFileWriterPinImpl methods
92 static HRESULT CFileWriterPinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
94 CFileWriterPinImpl_THIS(pImpl,pin);
96 TRACE("(%p,%p)\n",This,pPin);
101 static HRESULT CFileWriterPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
103 CFileWriterPinImpl_THIS(pImpl,pin);
105 TRACE("(%p,%p)\n",This,pPin);
110 static HRESULT CFileWriterPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
112 CFileWriterPinImpl_THIS(pImpl,pin);
114 TRACE("(%p)\n",This);
116 if ( This->meminput.pAllocator != NULL )
118 IMemAllocator_Decommit(This->meminput.pAllocator);
119 IMemAllocator_Release(This->meminput.pAllocator);
120 This->meminput.pAllocator = NULL;
126 static HRESULT CFileWriterPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
128 CFileWriterPinImpl_THIS(pImpl,pin);
130 TRACE("(%p,%p)\n",This,pmt);
132 if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
138 static HRESULT CFileWriterPinImpl_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
140 CFileWriterPinImpl_THIS(pImpl,pin);
146 TRACE( "(%p,%p)\n",This,pSample );
148 if ( This->pRender->m_fInFlush )
150 if ( pSample == NULL )
153 hr = IMediaSample_GetPointer(pSample,&pData);
156 lLength = (LONG)IMediaSample_GetActualDataLength(pSample);
162 ERR( "invalid length: %ld\n", lLength );
166 hr = IStream_Write((IStream*)(&This->stream),pData,lLength,&cbWritten);
171 static HRESULT CFileWriterPinImpl_ReceiveCanBlock( CPinBaseImpl* pImpl )
173 CFileWriterPinImpl_THIS(pImpl,pin);
175 TRACE( "(%p)\n", This );
180 static HRESULT CFileWriterPinImpl_EndOfStream( CPinBaseImpl* pImpl )
182 CFileWriterPinImpl_THIS(pImpl,pin);
184 FIXME( "(%p)\n", This );
186 This->pRender->m_fInFlush = FALSE;
188 /* FIXME - don't notify twice until stopped or seeked. */
189 return CBaseFilterImpl_MediaEventNotify(
190 &This->pRender->basefilter, EC_COMPLETE,
191 (LONG_PTR)S_OK, (LONG_PTR)(IBaseFilter*)(This->pRender) );
194 static HRESULT CFileWriterPinImpl_BeginFlush( CPinBaseImpl* pImpl )
196 CFileWriterPinImpl_THIS(pImpl,pin);
198 FIXME( "(%p)\n", This );
200 This->pRender->m_fInFlush = TRUE;
205 static HRESULT CFileWriterPinImpl_EndFlush( CPinBaseImpl* pImpl )
207 CFileWriterPinImpl_THIS(pImpl,pin);
209 FIXME( "(%p)\n", This );
211 This->pRender->m_fInFlush = FALSE;
216 static HRESULT CFileWriterPinImpl_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
218 CFileWriterPinImpl_THIS(pImpl,pin);
220 FIXME( "(%p)\n", This );
222 This->pRender->m_fInFlush = FALSE;
230 static const CBasePinHandlers pinhandlers =
232 CFileWriterPinImpl_OnPreConnect, /* pOnPreConnect */
233 CFileWriterPinImpl_OnPostConnect, /* pOnPostConnect */
234 CFileWriterPinImpl_OnDisconnect, /* pOnDisconnect */
235 CFileWriterPinImpl_CheckMediaType, /* pCheckMediaType */
236 NULL, /* pQualityNotify */
237 CFileWriterPinImpl_Receive, /* pReceive */
238 CFileWriterPinImpl_ReceiveCanBlock, /* pReceiveCanBlock */
239 CFileWriterPinImpl_EndOfStream, /* pEndOfStream */
240 CFileWriterPinImpl_BeginFlush, /* pBeginFlush */
241 CFileWriterPinImpl_EndFlush, /* pEndFlush */
242 CFileWriterPinImpl_NewSegment, /* pNewSegment */
246 /***************************************************************************
248 * new/delete CFileWriterImpl
252 /* can I use offsetof safely? - FIXME? */
253 static QUARTZ_IFEntry FilterIFEntries[] =
255 { &IID_IPersist, offsetof(CFileWriterImpl,basefilter)-offsetof(CFileWriterImpl,unk) },
256 { &IID_IMediaFilter, offsetof(CFileWriterImpl,basefilter)-offsetof(CFileWriterImpl,unk) },
257 { &IID_IBaseFilter, offsetof(CFileWriterImpl,basefilter)-offsetof(CFileWriterImpl,unk) },
258 { &IID_IFileSinkFilter, offsetof(CFileWriterImpl,filesink)-offsetof(CFileWriterImpl,unk) },
259 { &IID_IFileSinkFilter2, offsetof(CFileWriterImpl,filesink)-offsetof(CFileWriterImpl,unk) },
262 static HRESULT CFileWriterImpl_OnQueryInterface(
263 IUnknown* punk, const IID* piid, void** ppobj )
265 CFileWriterImpl_THIS(punk,unk);
267 if ( This->pSeekPass == NULL )
268 return E_NOINTERFACE;
270 if ( IsEqualGUID( &IID_IMediaPosition, piid ) ||
271 IsEqualGUID( &IID_IMediaSeeking, piid ) )
273 TRACE( "IMediaSeeking(or IMediaPosition) is queried\n" );
274 return IUnknown_QueryInterface( (IUnknown*)(&This->pSeekPass->unk), piid, ppobj );
277 return E_NOINTERFACE;
280 static void QUARTZ_DestroyFileWriter(IUnknown* punk)
282 CFileWriterImpl_THIS(punk,unk);
284 TRACE( "(%p)\n", This );
285 CFileWriterImpl_OnInactive(&This->basefilter);
287 if ( This->pPin != NULL )
289 IUnknown_Release(This->pPin->unk.punkControl);
292 if ( This->pSeekPass != NULL )
294 IUnknown_Release((IUnknown*)&This->pSeekPass->unk);
295 This->pSeekPass = NULL;
298 if ( This->m_hFile != INVALID_HANDLE_VALUE )
300 CloseHandle( This->m_hFile );
301 This->m_hFile = INVALID_HANDLE_VALUE;
303 if ( This->m_pszFileName != NULL )
305 QUARTZ_FreeMem( This->m_pszFileName );
306 This->m_pszFileName = NULL;
308 QUARTZ_MediaType_Free( &This->m_mt );
310 CFileWriterImpl_UninitIFileSinkFilter2(This);
311 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
313 DeleteCriticalSection( &This->m_csReceive );
316 HRESULT QUARTZ_CreateFileWriter(IUnknown* punkOuter,void** ppobj)
318 CFileWriterImpl* This = NULL;
321 TRACE("(%p,%p)\n",punkOuter,ppobj);
323 This = (CFileWriterImpl*)
324 QUARTZ_AllocObj( sizeof(CFileWriterImpl) );
326 return E_OUTOFMEMORY;
327 This->pSeekPass = NULL;
329 This->m_fInFlush = FALSE;
331 This->m_hFile = INVALID_HANDLE_VALUE;
332 This->m_pszFileName = NULL;
333 This->m_cbFileName = 0;
335 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
337 QUARTZ_IUnkInit( &This->unk, punkOuter );
338 This->qiext.pNext = NULL;
339 This->qiext.pOnQueryInterface = &CFileWriterImpl_OnQueryInterface;
340 QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
342 hr = CBaseFilterImpl_InitIBaseFilter(
344 This->unk.punkControl,
346 QUARTZ_FileWriter_Name,
350 hr = CFileWriterImpl_InitIFileSinkFilter2(This);
353 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
359 QUARTZ_FreeObj(This);
363 This->unk.pEntries = FilterIFEntries;
364 This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
365 This->unk.pOnFinalRelease = QUARTZ_DestroyFileWriter;
367 InitializeCriticalSection( &This->m_csReceive );
369 hr = QUARTZ_CreateFileWriterPin(
371 &This->basefilter.csFilter,
375 hr = QUARTZ_CompList_AddComp(
376 This->basefilter.pInPins,
377 (IUnknown*)&This->pPin->pin,
380 hr = QUARTZ_CreateSeekingPassThruInternal(
381 (IUnknown*)&(This->unk), &This->pSeekPass,
382 TRUE, (IPin*)&(This->pPin->pin) );
386 IUnknown_Release( This->unk.punkControl );
390 *ppobj = (void*)&(This->unk);
395 /***************************************************************************
397 * new/delete CFileWriterPinImpl
401 /* can I use offsetof safely? - FIXME? */
402 static QUARTZ_IFEntry PinIFEntries[] =
404 { &IID_IPin, offsetof(CFileWriterPinImpl,pin)-offsetof(CFileWriterPinImpl,unk) },
405 { &IID_IMemInputPin, offsetof(CFileWriterPinImpl,meminput)-offsetof(CFileWriterPinImpl,unk) },
406 { &IID_IStream, offsetof(CFileWriterPinImpl,stream)-offsetof(CFileWriterPinImpl,unk) },
409 static void QUARTZ_DestroyFileWriterPin(IUnknown* punk)
411 CFileWriterPinImpl_THIS(punk,unk);
413 TRACE( "(%p)\n", This );
415 CPinBaseImpl_UninitIPin( &This->pin );
416 CMemInputPinBaseImpl_UninitIMemInputPin( &This->meminput );
417 CFileWriterPinImpl_UninitIStream(This);
420 HRESULT QUARTZ_CreateFileWriterPin(
421 CFileWriterImpl* pFilter,
422 CRITICAL_SECTION* pcsPin,
423 CRITICAL_SECTION* pcsPinReceive,
424 CFileWriterPinImpl** ppPin)
426 CFileWriterPinImpl* This = NULL;
429 TRACE("(%p,%p,%p,%p)\n",pFilter,pcsPin,pcsPinReceive,ppPin);
431 This = (CFileWriterPinImpl*)
432 QUARTZ_AllocObj( sizeof(CFileWriterPinImpl) );
434 return E_OUTOFMEMORY;
436 QUARTZ_IUnkInit( &This->unk, NULL );
437 This->pRender = pFilter;
439 hr = CPinBaseImpl_InitIPin(
441 This->unk.punkControl,
442 pcsPin, pcsPinReceive,
443 &pFilter->basefilter,
444 QUARTZ_FileWriterPin_Name,
450 hr = CMemInputPinBaseImpl_InitIMemInputPin(
452 This->unk.punkControl,
456 hr = CFileWriterPinImpl_InitIStream(This);
459 CMemInputPinBaseImpl_UninitIMemInputPin(&This->meminput);
465 CPinBaseImpl_UninitIPin( &This->pin );
471 QUARTZ_FreeObj(This);
475 This->unk.pEntries = PinIFEntries;
476 This->unk.dwEntries = sizeof(PinIFEntries)/sizeof(PinIFEntries[0]);
477 This->unk.pOnFinalRelease = QUARTZ_DestroyFileWriterPin;
481 TRACE("returned successfully.\n");
486 /***************************************************************************
488 * CFileWriterPinImpl::IStream
492 static HRESULT WINAPI
493 IStream_fnQueryInterface(IStream* iface,REFIID riid,void** ppobj)
495 CFileWriterPinImpl_THIS(iface,stream);
497 TRACE("(%p)->()\n",This);
499 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
503 IStream_fnAddRef(IStream* iface)
505 CFileWriterPinImpl_THIS(iface,stream);
507 TRACE("(%p)->()\n",This);
509 return IUnknown_AddRef(This->unk.punkControl);
513 IStream_fnRelease(IStream* iface)
515 CFileWriterPinImpl_THIS(iface,stream);
517 TRACE("(%p)->()\n",This);
519 return IUnknown_Release(This->unk.punkControl);
522 static HRESULT WINAPI
523 IStream_fnRead(IStream* iface,void* pv,ULONG cb,ULONG* pcbRead)
525 CFileWriterPinImpl_THIS(iface,stream);
527 FIXME("(%p)->()\n",This);
532 static HRESULT WINAPI
533 IStream_fnWrite(IStream* iface,const void* pv,ULONG cb,ULONG* pcbWritten)
535 CFileWriterPinImpl_THIS(iface,stream);
538 FIXME("(%p)->(%p,%lu,%p)\n",This,pv,cb,pcbWritten);
540 EnterCriticalSection( &This->pRender->m_csReceive );
541 if ( This->pRender->m_hFile == INVALID_HANDLE_VALUE )
547 if ( ! WriteFile( This->pRender->m_hFile, pv, cb, pcbWritten, NULL ) )
555 LeaveCriticalSection( &This->pRender->m_csReceive );
559 static HRESULT WINAPI
560 IStream_fnSeek(IStream* iface,LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER* plibNewPosition)
562 CFileWriterPinImpl_THIS(iface,stream);
567 FIXME("(%p)->() stub!\n",This);
569 EnterCriticalSection( &This->pRender->m_csReceive );
570 if ( This->pRender->m_hFile == INVALID_HANDLE_VALUE )
576 dwDistLow = dlibMove.s.LowPart;
577 lDistHigh = dlibMove.s.HighPart;
580 dwDistLow = SetFilePointer( This->pRender->m_hFile, (LONG)dwDistLow, &lDistHigh, dwOrigin );
581 if ( dwDistLow == 0xffffffff && GetLastError() != 0 )
587 if ( plibNewPosition != NULL )
589 plibNewPosition->s.LowPart = dwDistLow;
590 plibNewPosition->s.HighPart = lDistHigh;
595 LeaveCriticalSection( &This->pRender->m_csReceive );
599 static HRESULT WINAPI
600 IStream_fnSetSize(IStream* iface,ULARGE_INTEGER libNewSize)
602 CFileWriterPinImpl_THIS(iface,stream);
604 FIXME("(%p)->() stub!\n",This);
606 if ( This->pRender->m_hFile == INVALID_HANDLE_VALUE )
613 static HRESULT WINAPI
614 IStream_fnCopyTo(IStream* iface,IStream* pstrm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
616 CFileWriterPinImpl_THIS(iface,stream);
618 FIXME("(%p)->()\n",This);
623 static HRESULT WINAPI
624 IStream_fnCommit(IStream* iface,DWORD grfCommitFlags)
626 CFileWriterPinImpl_THIS(iface,stream);
628 FIXME("(%p)->() stub!\n",This);
633 static HRESULT WINAPI
634 IStream_fnRevert(IStream* iface)
636 CFileWriterPinImpl_THIS(iface,stream);
638 FIXME("(%p)->() stub!\n",This);
643 static HRESULT WINAPI
644 IStream_fnLockRegion(IStream* iface,ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType)
646 CFileWriterPinImpl_THIS(iface,stream);
648 FIXME("(%p)->() stub!\n",This);
653 static HRESULT WINAPI
654 IStream_fnUnlockRegion(IStream* iface,ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType)
656 CFileWriterPinImpl_THIS(iface,stream);
658 FIXME("(%p)->() stub!\n",This);
663 static HRESULT WINAPI
664 IStream_fnStat(IStream* iface,STATSTG* pstatstg,DWORD grfStatFlag)
666 CFileWriterPinImpl_THIS(iface,stream);
668 FIXME("(%p)->() stub!\n",This);
673 static HRESULT WINAPI
674 IStream_fnClone(IStream* iface,IStream** ppstrm)
676 CFileWriterPinImpl_THIS(iface,stream);
678 FIXME("(%p)->() stub!\n",This);
683 static ICOM_VTABLE(IStream) istream =
685 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
686 /* IUnknown fields */
687 IStream_fnQueryInterface,
698 IStream_fnLockRegion,
699 IStream_fnUnlockRegion,
704 HRESULT CFileWriterPinImpl_InitIStream( CFileWriterPinImpl* This )
706 TRACE("(%p)\n",This);
707 ICOM_VTBL(&This->stream) = &istream;
712 HRESULT CFileWriterPinImpl_UninitIStream( CFileWriterPinImpl* This )
714 TRACE("(%p)\n",This);
720 /***************************************************************************
722 * CFileWriterImpl::IFileSinkFilter2
726 static HRESULT WINAPI
727 IFileSinkFilter2_fnQueryInterface(IFileSinkFilter2* iface,REFIID riid,void** ppobj)
729 CFileWriterImpl_THIS(iface,filesink);
731 TRACE("(%p)->()\n",This);
733 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
737 IFileSinkFilter2_fnAddRef(IFileSinkFilter2* iface)
739 CFileWriterImpl_THIS(iface,filesink);
741 TRACE("(%p)->()\n",This);
743 return IUnknown_AddRef(This->unk.punkControl);
747 IFileSinkFilter2_fnRelease(IFileSinkFilter2* iface)
749 CFileWriterImpl_THIS(iface,filesink);
751 TRACE("(%p)->()\n",This);
753 return IUnknown_Release(This->unk.punkControl);
756 static HRESULT WINAPI
757 IFileSinkFilter2_fnSetFileName(IFileSinkFilter2* iface,LPCOLESTR pszFileName,const AM_MEDIA_TYPE* pmt)
759 CFileWriterImpl_THIS(iface,filesink);
762 TRACE("(%p)->(%s,%p)\n",This,debugstr_w(pszFileName),pmt);
764 if ( pszFileName == NULL )
767 if ( This->m_pszFileName != NULL )
770 This->m_cbFileName = sizeof(WCHAR)*(lstrlenW(pszFileName)+1);
771 This->m_pszFileName = (WCHAR*)QUARTZ_AllocMem( This->m_cbFileName );
772 if ( This->m_pszFileName == NULL )
773 return E_OUTOFMEMORY;
774 memcpy( This->m_pszFileName, pszFileName, This->m_cbFileName );
778 hr = QUARTZ_MediaType_Copy( &This->m_mt, pmt );
784 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
785 memcpy( &This->m_mt.majortype, &MEDIATYPE_Stream, sizeof(GUID) );
786 memcpy( &This->m_mt.subtype, &MEDIASUBTYPE_NULL, sizeof(GUID) );
787 This->m_mt.lSampleSize = 1;
788 memcpy( &This->m_mt.formattype, &FORMAT_None, sizeof(GUID) );
791 This->m_hFile = CreateFileW(
796 ( This->m_dwMode == AM_FILE_OVERWRITE ) ? CREATE_ALWAYS : OPEN_ALWAYS,
797 FILE_ATTRIBUTE_NORMAL,
799 if ( This->m_hFile == INVALID_HANDLE_VALUE )
805 This->pPin->pin.pmtAcceptTypes = &This->m_mt;
806 This->pPin->pin.cAcceptTypes = 1;
813 static HRESULT WINAPI
814 IFileSinkFilter2_fnGetCurFile(IFileSinkFilter2* iface,LPOLESTR* ppszFileName,AM_MEDIA_TYPE* pmt)
816 CFileWriterImpl_THIS(iface,filesink);
817 HRESULT hr = E_NOTIMPL;
819 TRACE("(%p)->(%p,%p)\n",This,ppszFileName,pmt);
821 if ( ppszFileName == NULL || pmt == NULL )
824 if ( This->m_pszFileName == NULL )
827 hr = QUARTZ_MediaType_Copy( pmt, &This->m_mt );
831 *ppszFileName = (WCHAR*)CoTaskMemAlloc( This->m_cbFileName );
832 if ( *ppszFileName == NULL )
834 QUARTZ_MediaType_Free(pmt);
835 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
836 return E_OUTOFMEMORY;
839 memcpy( *ppszFileName, This->m_pszFileName, This->m_cbFileName );
844 static HRESULT WINAPI
845 IFileSinkFilter2_fnSetMode(IFileSinkFilter2* iface,DWORD dwFlags)
847 CFileWriterImpl_THIS(iface,filesink);
849 TRACE("(%p)->(%08lx)\n",This,dwFlags);
851 if ( dwFlags != 0 && dwFlags != AM_FILE_OVERWRITE )
853 This->m_dwMode = dwFlags;
858 static HRESULT WINAPI
859 IFileSinkFilter2_fnGetMode(IFileSinkFilter2* iface,DWORD* pdwFlags)
861 CFileWriterImpl_THIS(iface,filesink);
863 TRACE("(%p)->(%p)\n",This,pdwFlags);
865 if ( pdwFlags == NULL )
868 *pdwFlags = This->m_dwMode;
873 static ICOM_VTABLE(IFileSinkFilter2) ifilesink2 =
875 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
876 /* IUnknown fields */
877 IFileSinkFilter2_fnQueryInterface,
878 IFileSinkFilter2_fnAddRef,
879 IFileSinkFilter2_fnRelease,
880 /* IFileSinkFilter2 fields */
881 IFileSinkFilter2_fnSetFileName,
882 IFileSinkFilter2_fnGetCurFile,
883 IFileSinkFilter2_fnSetMode,
884 IFileSinkFilter2_fnGetMode,
887 HRESULT CFileWriterImpl_InitIFileSinkFilter2( CFileWriterImpl* This )
889 TRACE("(%p)\n",This);
890 ICOM_VTBL(&This->filesink) = &ifilesink2;
895 HRESULT CFileWriterImpl_UninitIFileSinkFilter2( CFileWriterImpl* This )
897 TRACE("(%p)\n",This);