Correctly fill parent pid, module size and module name in process and
[wine] / dlls / quartz / basefilt.c
1 /*
2  * Implements IBaseFilter. (internal)
3  *
4  * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winerror.h"
28 #include "strmif.h"
29 #include "vfwmsgs.h"
30
31 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
33
34 #include "quartz_private.h"
35 #include "basefilt.h"
36 #include "enumunk.h"
37
38
39 /***************************************************************************
40  *
41  *      CBaseFilterImpl::IBaseFilter
42  *
43  */
44
45 static HRESULT WINAPI
46 CBaseFilterImpl_fnQueryInterface(IBaseFilter* iface,REFIID riid,void** ppobj)
47 {
48         ICOM_THIS(CBaseFilterImpl,iface);
49
50         TRACE("(%p)->()\n",This);
51
52         return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
53 }
54
55 static ULONG WINAPI
56 CBaseFilterImpl_fnAddRef(IBaseFilter* iface)
57 {
58         ICOM_THIS(CBaseFilterImpl,iface);
59
60         TRACE("(%p)->()\n",This);
61
62         return IUnknown_AddRef(This->punkControl);
63 }
64
65 static ULONG WINAPI
66 CBaseFilterImpl_fnRelease(IBaseFilter* iface)
67 {
68         ICOM_THIS(CBaseFilterImpl,iface);
69
70         TRACE("(%p)->()\n",This);
71
72         return IUnknown_Release(This->punkControl);
73 }
74
75
76 static HRESULT WINAPI
77 CBaseFilterImpl_fnGetClassID(IBaseFilter* iface,CLSID* pclsid)
78 {
79         ICOM_THIS(CBaseFilterImpl,iface);
80
81         TRACE("(%p)->()\n",This);
82
83         if ( pclsid == NULL )
84                 return E_POINTER;
85
86         memcpy( pclsid, This->pclsidFilter, sizeof(CLSID) );
87
88         return NOERROR;
89 }
90
91 static HRESULT WINAPI
92 CBaseFilterImpl_fnStop(IBaseFilter* iface)
93 {
94         ICOM_THIS(CBaseFilterImpl,iface);
95         HRESULT hr;
96
97         TRACE("(%p)->()\n",This);
98
99         hr = NOERROR;
100
101         EnterCriticalSection( &This->csFilter );
102         TRACE("(%p) state = %d\n",This,This->fstate);
103
104         if ( This->fstate == State_Running )
105         {
106                 if ( This->pHandlers->pOnInactive != NULL )
107                         hr = This->pHandlers->pOnInactive( This );
108                 if ( SUCCEEDED(hr) )
109                         This->fstate = State_Paused;
110         }
111         if ( This->fstate == State_Paused )
112         {
113                 if ( This->pHandlers->pOnStop != NULL )
114                         hr = This->pHandlers->pOnStop( This );
115                 if ( SUCCEEDED(hr) )
116                         This->fstate = State_Stopped;
117         }
118
119         LeaveCriticalSection( &This->csFilter );
120
121         return hr;
122 }
123
124 static HRESULT WINAPI
125 CBaseFilterImpl_fnPause(IBaseFilter* iface)
126 {
127         ICOM_THIS(CBaseFilterImpl,iface);
128         HRESULT hr;
129
130         TRACE("(%p)->()\n",This);
131
132         hr = NOERROR;
133
134         EnterCriticalSection( &This->csFilter );
135         TRACE("(%p) state = %d\n",This,This->fstate);
136
137         if ( This->fstate != State_Paused )
138         {
139                 if ( This->pHandlers->pOnInactive != NULL )
140                         hr = This->pHandlers->pOnInactive( This );
141                 if ( SUCCEEDED(hr) )
142                         This->fstate = State_Paused;
143         }
144         LeaveCriticalSection( &This->csFilter );
145
146         TRACE("hr = %08lx\n",hr);
147
148         return hr;
149 }
150
151 static HRESULT WINAPI
152 CBaseFilterImpl_fnRun(IBaseFilter* iface,REFERENCE_TIME rtStart)
153 {
154         ICOM_THIS(CBaseFilterImpl,iface);
155         HRESULT hr;
156
157         TRACE("(%p)->()\n",This);
158
159         hr = NOERROR;
160
161         EnterCriticalSection( &This->csFilter );
162         TRACE("(%p) state = %d\n",This,This->fstate);
163
164         This->rtStart = rtStart;
165
166         if ( This->fstate == State_Stopped )
167         {
168                 if ( This->pHandlers->pOnInactive != NULL )
169                         hr = This->pHandlers->pOnInactive( This );
170                 if ( SUCCEEDED(hr) )
171                         This->fstate = State_Paused;
172         }
173         if ( This->fstate == State_Paused )
174         {
175                 if ( This->pHandlers->pOnActive != NULL )
176                         hr = This->pHandlers->pOnActive( This );
177                 if ( SUCCEEDED(hr) )
178                         This->fstate = State_Running;
179         }
180
181         LeaveCriticalSection( &This->csFilter );
182
183         return hr;
184 }
185
186 static HRESULT WINAPI
187 CBaseFilterImpl_fnGetState(IBaseFilter* iface,DWORD dw,FILTER_STATE* pState)
188 {
189         ICOM_THIS(CBaseFilterImpl,iface);
190         HRESULT hr = S_OK;
191
192         TRACE("(%p)->(%p)\n",This,pState);
193
194         if ( pState == NULL )
195                 return E_POINTER;
196
197         EnterCriticalSection( &This->csFilter );
198         TRACE("(%p) state = %d\n",This,This->fstate);
199         *pState = This->fstate;
200         if ( This->bIntermediateState )
201                 hr = VFW_S_STATE_INTERMEDIATE;
202         LeaveCriticalSection( &This->csFilter );
203
204         return hr;
205 }
206
207 static HRESULT WINAPI
208 CBaseFilterImpl_fnSetSyncSource(IBaseFilter* iface,IReferenceClock* pobjClock)
209 {
210         ICOM_THIS(CBaseFilterImpl,iface);
211
212         TRACE("(%p)->(%p)\n",This,pobjClock);
213
214         EnterCriticalSection( &This->csFilter );
215
216         if ( This->pClock != NULL )
217         {
218                 IReferenceClock_Release( This->pClock );
219                 This->pClock = NULL;
220         }
221
222         This->pClock = pobjClock;
223         if ( pobjClock != NULL )
224                 IReferenceClock_AddRef( pobjClock );
225
226         LeaveCriticalSection( &This->csFilter );
227
228         return NOERROR;
229 }
230
231 static HRESULT WINAPI
232 CBaseFilterImpl_fnGetSyncSource(IBaseFilter* iface,IReferenceClock** ppobjClock)
233 {
234         ICOM_THIS(CBaseFilterImpl,iface);
235         HRESULT hr = VFW_E_NO_CLOCK;
236
237         TRACE("(%p)->(%p)\n",This,ppobjClock);
238
239         if ( ppobjClock == NULL )
240                 return E_POINTER;
241
242         EnterCriticalSection( &This->csFilter );
243
244         *ppobjClock = This->pClock;
245         if ( This->pClock != NULL )
246         {
247                 hr = NOERROR;
248                 IReferenceClock_AddRef( This->pClock );
249         }
250
251         LeaveCriticalSection( &This->csFilter );
252
253         return hr;
254 }
255
256
257 static HRESULT WINAPI
258 CBaseFilterImpl_fnEnumPins(IBaseFilter* iface,IEnumPins** ppenum)
259 {
260         ICOM_THIS(CBaseFilterImpl,iface);
261         HRESULT hr = E_FAIL;
262         QUARTZ_CompList*        pListPins;
263         QUARTZ_CompListItem*    pItem;
264         IUnknown*       punkPin;
265
266         TRACE("(%p)->(%p)\n",This,ppenum);
267
268         if ( ppenum == NULL )
269                 return E_POINTER;
270         *ppenum = NULL;
271
272         pListPins = QUARTZ_CompList_Alloc();
273         if ( pListPins == NULL )
274                 return E_OUTOFMEMORY;
275
276         QUARTZ_CompList_Lock( This->pInPins );
277         QUARTZ_CompList_Lock( This->pOutPins );
278
279         pItem = QUARTZ_CompList_GetFirst( This->pInPins );
280         while ( pItem != NULL )
281         {
282                 punkPin = QUARTZ_CompList_GetItemPtr( pItem );
283                 hr = QUARTZ_CompList_AddComp( pListPins, punkPin, NULL, 0 );
284                 if ( FAILED(hr) )
285                         goto err;
286                 pItem = QUARTZ_CompList_GetNext( This->pInPins, pItem );
287         }
288
289         pItem = QUARTZ_CompList_GetFirst( This->pOutPins );
290         while ( pItem != NULL )
291         {
292                 punkPin = QUARTZ_CompList_GetItemPtr( pItem );
293                 hr = QUARTZ_CompList_AddComp( pListPins, punkPin, NULL, 0 );
294                 if ( FAILED(hr) )
295                         goto err;
296                 pItem = QUARTZ_CompList_GetNext( This->pOutPins, pItem );
297         }
298
299         hr = QUARTZ_CreateEnumUnknown(
300                 &IID_IEnumPins, (void**)ppenum, pListPins );
301 err:
302         QUARTZ_CompList_Unlock( This->pInPins );
303         QUARTZ_CompList_Unlock( This->pOutPins );
304
305         QUARTZ_CompList_Free( pListPins );
306
307         return hr;
308 }
309
310 static HRESULT WINAPI
311 CBaseFilterImpl_fnFindPin(IBaseFilter* iface,LPCWSTR lpwszId,IPin** ppobj)
312 {
313         ICOM_THIS(CBaseFilterImpl,iface);
314
315         FIXME("(%p)->(%s,%p) stub!\n",This,debugstr_w(lpwszId),ppobj);
316
317         if ( ppobj == NULL )
318                 return E_POINTER;
319
320
321
322         return E_NOTIMPL;
323 }
324
325 static HRESULT WINAPI
326 CBaseFilterImpl_fnQueryFilterInfo(IBaseFilter* iface,FILTER_INFO* pfi)
327 {
328         ICOM_THIS(CBaseFilterImpl,iface);
329
330         TRACE("(%p)->(%p)\n",This,pfi);
331
332         if ( pfi == NULL )
333                 return E_POINTER;
334
335         EnterCriticalSection( &This->csFilter );
336
337         if ( This->cbNameGraph <= sizeof(WCHAR)*MAX_FILTER_NAME )
338         {
339                 memcpy( pfi->achName, This->pwszNameGraph, This->cbNameGraph );
340         }
341         else
342         {
343                 memcpy( pfi->achName, This->pwszNameGraph,
344                                 sizeof(WCHAR)*MAX_FILTER_NAME );
345                 pfi->achName[MAX_FILTER_NAME-1] = (WCHAR)0;
346         }
347
348         pfi->pGraph = This->pfg;
349         if ( pfi->pGraph != NULL )
350                 IFilterGraph_AddRef(pfi->pGraph);
351
352         LeaveCriticalSection( &This->csFilter );
353
354         return NOERROR;
355 }
356
357 static HRESULT WINAPI
358 CBaseFilterImpl_fnJoinFilterGraph(IBaseFilter* iface,IFilterGraph* pfg,LPCWSTR lpwszName)
359 {
360         ICOM_THIS(CBaseFilterImpl,iface);
361         HRESULT hr;
362
363         TRACE("(%p)->(%p,%s)\n",This,pfg,debugstr_w(lpwszName));
364
365         EnterCriticalSection( &This->csFilter );
366
367         if ( This->pwszNameGraph != NULL )
368         {
369                 QUARTZ_FreeMem( This->pwszNameGraph );
370                 This->pwszNameGraph = NULL;
371                 This->cbNameGraph = 0;
372         }
373
374         This->pfg = pfg;
375         This->cbNameGraph = sizeof(WCHAR) * (lstrlenW(lpwszName)+1);
376         This->pwszNameGraph = (WCHAR*)QUARTZ_AllocMem( This->cbNameGraph );
377         if ( This->pwszNameGraph == NULL )
378         {
379                 hr = E_OUTOFMEMORY;
380                 goto err;
381         }
382         memcpy( This->pwszNameGraph, lpwszName, This->cbNameGraph );
383
384         hr = NOERROR;
385 err:
386         LeaveCriticalSection( &This->csFilter );
387
388         return hr;
389 }
390
391 static HRESULT WINAPI
392 CBaseFilterImpl_fnQueryVendorInfo(IBaseFilter* iface,LPWSTR* lpwszVendor)
393 {
394         ICOM_THIS(CBaseFilterImpl,iface);
395
396         TRACE("(%p)->(%p)\n",This,lpwszVendor);
397
398         /* E_NOTIMPL means 'no vender information'. */
399         return E_NOTIMPL;
400 }
401
402
403 /***************************************************************************
404  *
405  *      construct/destruct CBaseFilterImpl
406  *
407  */
408
409 static ICOM_VTABLE(IBaseFilter) ibasefilter =
410 {
411         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
412         /* IUnknown fields */
413         CBaseFilterImpl_fnQueryInterface,
414         CBaseFilterImpl_fnAddRef,
415         CBaseFilterImpl_fnRelease,
416         /* IPersist fields */
417         CBaseFilterImpl_fnGetClassID,
418         /* IMediaFilter fields */
419         CBaseFilterImpl_fnStop,
420         CBaseFilterImpl_fnPause,
421         CBaseFilterImpl_fnRun,
422         CBaseFilterImpl_fnGetState,
423         CBaseFilterImpl_fnSetSyncSource,
424         CBaseFilterImpl_fnGetSyncSource,
425         /* IBaseFilter fields */
426         CBaseFilterImpl_fnEnumPins,
427         CBaseFilterImpl_fnFindPin,
428         CBaseFilterImpl_fnQueryFilterInfo,
429         CBaseFilterImpl_fnJoinFilterGraph,
430         CBaseFilterImpl_fnQueryVendorInfo,
431 };
432
433
434 HRESULT CBaseFilterImpl_InitIBaseFilter(
435         CBaseFilterImpl* This, IUnknown* punkControl,
436         const CLSID* pclsidFilter, LPCWSTR lpwszNameGraph,
437         const CBaseFilterHandlers* pHandlers )
438 {
439         TRACE("(%p,%p)\n",This,punkControl);
440
441         if ( punkControl == NULL )
442         {
443                 ERR( "punkControl must not be NULL\n" );
444                 return E_INVALIDARG;
445         }
446
447         ICOM_VTBL(This) = &ibasefilter;
448         This->punkControl = punkControl;
449         This->pHandlers = pHandlers;
450         This->pclsidFilter = pclsidFilter;
451         This->pInPins = NULL;
452         This->pOutPins = NULL;
453         This->pfg = NULL;
454         This->cbNameGraph = 0;
455         This->pwszNameGraph = NULL;
456         This->pClock = NULL;
457         This->rtStart = 0;
458         This->fstate = State_Stopped;
459         This->bIntermediateState = FALSE;
460
461         This->cbNameGraph = sizeof(WCHAR) * (lstrlenW(lpwszNameGraph)+1);
462         This->pwszNameGraph = (WCHAR*)QUARTZ_AllocMem( This->cbNameGraph );
463         if ( This->pwszNameGraph == NULL )
464                 return E_OUTOFMEMORY;
465         memcpy( This->pwszNameGraph, lpwszNameGraph, This->cbNameGraph );
466
467         This->pInPins = QUARTZ_CompList_Alloc();
468         This->pOutPins = QUARTZ_CompList_Alloc();
469         if ( This->pInPins == NULL || This->pOutPins == NULL )
470         {
471                 if ( This->pInPins != NULL )
472                         QUARTZ_CompList_Free(This->pInPins);
473                 if ( This->pOutPins != NULL )
474                         QUARTZ_CompList_Free(This->pOutPins);
475                 QUARTZ_FreeMem(This->pwszNameGraph);
476                 return E_OUTOFMEMORY;
477         }
478
479         InitializeCriticalSection( &This->csFilter );
480
481         return NOERROR;
482 }
483
484 void CBaseFilterImpl_UninitIBaseFilter( CBaseFilterImpl* This )
485 {
486         QUARTZ_CompListItem*    pListItem;
487         IPin*   pPin;
488
489         TRACE("(%p)\n",This);
490
491         if ( This->pInPins != NULL )
492         {
493                 while ( 1 )
494                 {
495                         pListItem = QUARTZ_CompList_GetFirst( This->pInPins );
496                         if ( pListItem == NULL )
497                                 break;
498                         pPin = (IPin*)QUARTZ_CompList_GetItemPtr( pListItem );
499                         QUARTZ_CompList_RemoveComp( This->pInPins, (IUnknown*)pPin );
500                 }
501
502                 QUARTZ_CompList_Free( This->pInPins );
503                 This->pInPins = NULL;
504         }
505         if ( This->pOutPins != NULL )
506         {
507                 while ( 1 )
508                 {
509                         pListItem = QUARTZ_CompList_GetFirst( This->pOutPins );
510                         if ( pListItem == NULL )
511                                 break;
512                         pPin = (IPin*)QUARTZ_CompList_GetItemPtr( pListItem );
513                         QUARTZ_CompList_RemoveComp( This->pOutPins, (IUnknown*)pPin );
514                 }
515
516                 QUARTZ_CompList_Free( This->pOutPins );
517                 This->pOutPins = NULL;
518         }
519
520         if ( This->pwszNameGraph != NULL )
521         {
522                 QUARTZ_FreeMem( This->pwszNameGraph );
523                 This->pwszNameGraph = NULL;
524         }
525
526         if ( This->pClock != NULL )
527         {
528                 IReferenceClock_Release( This->pClock );
529                 This->pClock = NULL;
530         }
531
532         DeleteCriticalSection( &This->csFilter );
533 }
534
535 /***************************************************************************
536  *
537  *      CBaseFilterImpl methods
538  *
539  */
540
541 HRESULT CBaseFilterImpl_MediaEventNotify(
542         CBaseFilterImpl* This, long lEvent,LONG_PTR lParam1,LONG_PTR lParam2)
543 {
544         IMediaEventSink*        pSink = NULL;
545         HRESULT hr = E_NOTIMPL;
546
547         EnterCriticalSection( &This->csFilter );
548
549         if ( This->pfg == NULL )
550         {
551                 hr = E_UNEXPECTED;
552                 goto err;
553         }
554
555         hr = IFilterGraph_QueryInterface( This->pfg, &IID_IMediaEventSink, (void**)&pSink );
556         if ( FAILED(hr) )
557                 goto err;
558         if ( pSink == NULL )
559         {
560                 hr = E_FAIL;
561                 goto err;
562         }
563
564         hr = IMediaEventSink_Notify(pSink,lEvent,lParam1,lParam2);
565         IMediaEventSink_Release(pSink);
566 err:
567         LeaveCriticalSection( &This->csFilter );
568
569         return hr;
570 }
571