Correctly fill parent pid, module size and module name in process and
[wine] / dlls / quartz / main.c
1 /*
2  * Exported APIs.
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 "winerror.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winnls.h"
29 #include "mmsystem.h"
30 #include "ole2.h"
31 #include "strmif.h"
32 #include "control.h"
33 #include "uuids.h"
34 #include "errors.h"
35
36 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
38
39 #include "initguid.h"
40
41 #include "quartz_private.h"
42 #include "fgraph.h"
43 #include "sysclock.h"
44 #include "memalloc.h"
45 #include "devenum.h"
46 #include "fmap.h"
47 #include "seekpass.h"
48 #include "audren.h"
49 #include "vidren.h"
50 #include "parser.h"
51 #include "asyncsrc.h"
52 #include "xform.h"
53 #include "capgraph.h"
54 #include "filesink.h"
55
56
57 typedef struct QUARTZ_CLASSENTRY
58 {
59         const CLSID*    pclsid;
60         QUARTZ_pCreateIUnknown  pCreateIUnk;
61 } QUARTZ_CLASSENTRY;
62
63
64 static HRESULT WINAPI
65 IClassFactory_fnQueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj);
66 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface);
67 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface);
68 static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj);
69 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface,BOOL dolock);
70
71 static ICOM_VTABLE(IClassFactory) iclassfact =
72 {
73         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
74         IClassFactory_fnQueryInterface,
75         IClassFactory_fnAddRef,
76         IClassFactory_fnRelease,
77         IClassFactory_fnCreateInstance,
78         IClassFactory_fnLockServer
79 };
80
81 typedef struct
82 {
83         /* IUnknown fields */
84         ICOM_VFIELD(IClassFactory);
85         LONG    ref;
86         /* IClassFactory fields */
87         const QUARTZ_CLASSENTRY* pEntry;
88 } IClassFactoryImpl;
89
90 static const QUARTZ_CLASSENTRY QUARTZ_ClassList[] =
91 {
92         { &CLSID_FilterGraph, &QUARTZ_CreateFilterGraph },
93         { &CLSID_FilterGraphNoThread, &QUARTZ_CreateFilterGraph }, /* FIXME? */
94         { &CLSID_SystemClock, &QUARTZ_CreateSystemClock },
95         { &CLSID_MemoryAllocator, &QUARTZ_CreateMemoryAllocator },
96         { &CLSID_SystemDeviceEnum, &QUARTZ_CreateSystemDeviceEnum },
97         { &CLSID_FilterMapper, &QUARTZ_CreateFilterMapper },
98         { &CLSID_FilterMapper2, &QUARTZ_CreateFilterMapper2 },
99         { &CLSID_SeekingPassThru, &QUARTZ_CreateSeekingPassThru },
100         { &CLSID_CaptureGraphBuilder, &QUARTZ_CreateCaptureGraph },
101         { &CLSID_CaptureGraphBuilder2, &QUARTZ_CreateCaptureGraph },
102
103         { &CLSID_AudioRender, &QUARTZ_CreateAudioRenderer },
104         { &CLSID_VideoRenderer, &QUARTZ_CreateVideoRenderer },
105         { &CLSID_quartzWaveParser, &QUARTZ_CreateWaveParser },
106         { &CLSID_AviSplitter, &QUARTZ_CreateAVISplitter },
107         { &CLSID_MPEG1Splitter, &QUARTZ_CreateMPEG1Splitter },
108         { &CLSID_MMSPLITTER, &QUARTZ_CreateMPEG2Splitter },
109         { &CLSID_AsyncReader, &QUARTZ_CreateAsyncReader },
110         { &CLSID_URLReader, &QUARTZ_CreateURLReader },
111         { &CLSID_AVIDec, &QUARTZ_CreateAVIDec },
112         { &CLSID_Colour, &QUARTZ_CreateColour },
113         { &CLSID_FileWriter, &QUARTZ_CreateFileWriter },
114         { NULL, NULL },
115 };
116
117 /* per-process variables */
118 static CRITICAL_SECTION csHeap;
119 static DWORD dwClassObjRef;
120 static HANDLE hDLLHeap;
121
122 void* QUARTZ_AllocObj( DWORD dwSize )
123 {
124         void*   pv;
125
126         EnterCriticalSection( &csHeap );
127         dwClassObjRef ++;
128         pv = HeapAlloc( hDLLHeap, 0, dwSize );
129         if ( pv == NULL )
130                 dwClassObjRef --;
131         LeaveCriticalSection( &csHeap );
132
133         return pv;
134 }
135
136 void QUARTZ_FreeObj( void* pobj )
137 {
138         EnterCriticalSection( &csHeap );
139         HeapFree( hDLLHeap, 0, pobj );
140         dwClassObjRef --;
141         LeaveCriticalSection( &csHeap );
142 }
143
144 void* QUARTZ_AllocMem( DWORD dwSize )
145 {
146         return HeapAlloc( hDLLHeap, 0, dwSize );
147 }
148
149 void QUARTZ_FreeMem( void* pMem )
150 {
151         HeapFree( hDLLHeap, 0, pMem );
152 }
153
154 void* QUARTZ_ReallocMem( void* pMem, DWORD dwSize )
155 {
156         if ( pMem == NULL )
157                 return QUARTZ_AllocMem( dwSize );
158
159         return HeapReAlloc( hDLLHeap, 0, pMem, dwSize );
160 }
161
162 static
163 LPWSTR QUARTZ_strncpyAtoW( LPWSTR lpwstr, LPCSTR lpstr, INT wbuflen )
164 {
165         INT     len;
166
167         len = MultiByteToWideChar( CP_ACP, 0, lpstr, -1, lpwstr, wbuflen );
168         if ( len == 0 )
169                 *lpwstr = 0;
170         return lpwstr;
171 }
172
173
174 /************************************************************************/
175
176 static HRESULT WINAPI
177 IClassFactory_fnQueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
178 {
179         ICOM_THIS(IClassFactoryImpl,iface);
180
181         TRACE("(%p)->(%p,%p)\n",This,riid,ppobj);
182         if ( ( IsEqualGUID( &IID_IUnknown, riid ) ) ||
183              ( IsEqualGUID( &IID_IClassFactory, riid ) ) )
184         {
185                 *ppobj = iface;
186                 IClassFactory_AddRef(iface);
187                 return S_OK;
188         }
189
190         return E_NOINTERFACE;
191 }
192
193 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
194 {
195         ICOM_THIS(IClassFactoryImpl,iface);
196
197         TRACE("(%p)->()\n",This);
198
199         return InterlockedExchangeAdd(&(This->ref),1) + 1;
200 }
201
202 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
203 {
204         ICOM_THIS(IClassFactoryImpl,iface);
205         LONG    ref;
206
207         TRACE("(%p)->()\n",This);
208         ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
209         if ( ref > 0 )
210                 return (ULONG)ref;
211
212         QUARTZ_FreeObj(This);
213         return 0;
214 }
215
216 static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj)
217 {
218         ICOM_THIS(IClassFactoryImpl,iface);
219         HRESULT hr;
220         IUnknown*       punk;
221
222         TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
223
224         if ( ppobj == NULL )
225                 return E_POINTER;
226         if ( pOuter != NULL && !IsEqualGUID( riid, &IID_IUnknown ) )
227                 return CLASS_E_NOAGGREGATION;
228
229         *ppobj = NULL;
230
231         hr = (*This->pEntry->pCreateIUnk)(pOuter,(void**)&punk);
232         if ( hr != S_OK )
233                 return hr;
234
235         hr = IUnknown_QueryInterface(punk,riid,ppobj);
236         IUnknown_Release(punk);
237
238         return hr;
239 }
240
241 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface,BOOL dolock)
242 {
243         ICOM_THIS(IClassFactoryImpl,iface);
244         HRESULT hr;
245
246         TRACE("(%p)->(%d)\n",This,dolock);
247         if (dolock)
248                 hr = IClassFactory_AddRef(iface);
249         else
250                 hr = IClassFactory_Release(iface);
251
252         return hr;
253 }
254
255
256
257 static HRESULT IClassFactory_Alloc( const CLSID* pclsid, void** ppobj )
258 {
259         const QUARTZ_CLASSENTRY*        pEntry;
260         IClassFactoryImpl*      pImpl;
261
262         TRACE( "(%s,%p)\n", debugstr_guid(pclsid), ppobj );
263
264         pEntry = QUARTZ_ClassList;
265         while ( pEntry->pclsid != NULL )
266         {
267                 if ( IsEqualGUID( pclsid, pEntry->pclsid ) )
268                         goto found;
269                 pEntry ++;
270         }
271
272         return CLASS_E_CLASSNOTAVAILABLE;
273 found:
274         pImpl = (IClassFactoryImpl*)QUARTZ_AllocObj( sizeof(IClassFactoryImpl) );
275         if ( pImpl == NULL )
276                 return E_OUTOFMEMORY;
277
278         TRACE( "allocated successfully.\n" );
279
280         ICOM_VTBL(pImpl) = &iclassfact;
281         pImpl->ref = 1;
282         pImpl->pEntry = pEntry;
283
284         *ppobj = (void*)pImpl;
285         return S_OK;
286 }
287
288
289 /***********************************************************************
290  *              QUARTZ_InitProcess (internal)
291  */
292 static BOOL QUARTZ_InitProcess( void )
293 {
294         TRACE("()\n");
295
296         dwClassObjRef = 0;
297         hDLLHeap = (HANDLE)NULL;
298         InitializeCriticalSection( &csHeap );
299
300         hDLLHeap = HeapCreate( 0, 0x10000, 0 );
301         if ( hDLLHeap == (HANDLE)NULL )
302                 return FALSE;
303
304         return TRUE;
305 }
306
307 /***********************************************************************
308  *              QUARTZ_UninitProcess (internal)
309  */
310 static void QUARTZ_UninitProcess( void )
311 {
312         TRACE("()\n");
313
314         if ( dwClassObjRef != 0 )
315                 ERR( "you must release some objects allocated from quartz.\n" );
316         if ( hDLLHeap != (HANDLE)NULL )
317         {
318                 HeapDestroy( hDLLHeap );
319                 hDLLHeap = (HANDLE)NULL;
320         }
321         DeleteCriticalSection( &csHeap );
322 }
323
324 /***********************************************************************
325  *              QUARTZ_DllMain
326  */
327 BOOL WINAPI QUARTZ_DllMain(
328         HINSTANCE hInstDLL,
329         DWORD fdwReason,
330         LPVOID lpvReserved )
331 {
332         TRACE("(%08x,%08lx,%p)\n",hInstDLL,fdwReason,lpvReserved);
333
334         switch ( fdwReason )
335         {
336         case DLL_PROCESS_ATTACH:
337                 if ( !QUARTZ_InitProcess() )
338                         return FALSE;
339                 break;
340         case DLL_PROCESS_DETACH:
341                 QUARTZ_UninitProcess();
342                 break;
343         case DLL_THREAD_ATTACH:
344                 break;
345         case DLL_THREAD_DETACH:
346                 break;
347         }
348
349         return TRUE;
350 }
351
352
353 /***********************************************************************
354  *              DllCanUnloadNow (QUARTZ.@)
355  *
356  * RETURNS
357  *    Success: S_OK
358  *    Failure: S_FALSE
359  */
360 HRESULT WINAPI QUARTZ_DllCanUnloadNow(void)
361 {
362         HRESULT hr;
363
364         EnterCriticalSection( &csHeap );
365         hr = ( dwClassObjRef == 0 ) ? S_OK : S_FALSE;
366         LeaveCriticalSection( &csHeap );
367
368         return hr;
369 }
370
371 /***********************************************************************
372  *              DllGetClassObject (QUARTZ.@)
373  */
374 HRESULT WINAPI QUARTZ_DllGetClassObject(
375                 const CLSID* pclsid,const IID* piid,void** ppv)
376 {
377         *ppv = NULL;
378         if ( IsEqualCLSID( &IID_IUnknown, piid ) ||
379              IsEqualCLSID( &IID_IClassFactory, piid ) )
380         {
381                 return IClassFactory_Alloc( pclsid, ppv );
382         }
383
384         return CLASS_E_CLASSNOTAVAILABLE;
385 }
386
387 /***********************************************************************
388  *              DllRegisterServer (QUARTZ.@)
389  */
390
391 HRESULT WINAPI QUARTZ_DllRegisterServer( void )
392 {
393         FIXME( "(): stub\n" );
394         return E_FAIL;
395 }
396
397 /***********************************************************************
398  *              DllUnregisterServer (QUARTZ.@)
399  */
400
401 HRESULT WINAPI QUARTZ_DllUnregisterServer( void )
402 {
403         FIXME( "(): stub\n" );
404         return E_FAIL;
405 }
406
407 /**************************************************************************/
408 /**************************************************************************/
409
410 /* FIXME - all string should be defined in the resource of quartz. */
411
412 static LPCSTR hresult_to_string( HRESULT hr )
413 {
414         switch ( hr )
415         {
416         #define ENTRY(x)        case x: return (const char*)#x
417         /* some known codes */
418         ENTRY(S_OK);
419         ENTRY(S_FALSE);
420         ENTRY(E_FAIL);
421         ENTRY(E_POINTER);
422         ENTRY(E_NOTIMPL);
423         ENTRY(E_NOINTERFACE);
424         ENTRY(E_OUTOFMEMORY);
425         ENTRY(CLASS_E_CLASSNOTAVAILABLE);
426         ENTRY(CLASS_E_NOAGGREGATION);
427
428         /* vfwmsgs.h */
429         ENTRY(VFW_S_NO_MORE_ITEMS);
430         ENTRY(VFW_E_BAD_KEY);
431         ENTRY(VFW_E_INVALIDMEDIATYPE);
432         ENTRY(VFW_E_INVALIDSUBTYPE);
433         ENTRY(VFW_E_NEED_OWNER);
434         ENTRY(VFW_E_ENUM_OUT_OF_SYNC);
435         ENTRY(VFW_E_ALREADY_CONNECTED);
436         ENTRY(VFW_E_FILTER_ACTIVE);
437         ENTRY(VFW_E_NO_TYPES);
438         ENTRY(VFW_E_NO_ACCEPTABLE_TYPES);
439         ENTRY(VFW_E_INVALID_DIRECTION);
440         ENTRY(VFW_E_NOT_CONNECTED);
441         ENTRY(VFW_E_NO_ALLOCATOR);
442         ENTRY(VFW_E_RUNTIME_ERROR);
443         ENTRY(VFW_E_BUFFER_NOTSET);
444         ENTRY(VFW_E_BUFFER_OVERFLOW);
445         ENTRY(VFW_E_BADALIGN);
446         ENTRY(VFW_E_ALREADY_COMMITTED);
447         ENTRY(VFW_E_BUFFERS_OUTSTANDING);
448         ENTRY(VFW_E_NOT_COMMITTED);
449         ENTRY(VFW_E_SIZENOTSET);
450         ENTRY(VFW_E_NO_CLOCK);
451         ENTRY(VFW_E_NO_SINK);
452         ENTRY(VFW_E_NO_INTERFACE);
453         ENTRY(VFW_E_NOT_FOUND);
454         ENTRY(VFW_E_CANNOT_CONNECT);
455         ENTRY(VFW_E_CANNOT_RENDER);
456         ENTRY(VFW_E_CHANGING_FORMAT);
457         ENTRY(VFW_E_NO_COLOR_KEY_SET);
458         ENTRY(VFW_E_NOT_OVERLAY_CONNECTION);
459         ENTRY(VFW_E_NOT_SAMPLE_CONNECTION);
460         ENTRY(VFW_E_PALETTE_SET);
461         ENTRY(VFW_E_COLOR_KEY_SET);
462         ENTRY(VFW_E_NO_COLOR_KEY_FOUND);
463         ENTRY(VFW_E_NO_PALETTE_AVAILABLE);
464         ENTRY(VFW_E_NO_DISPLAY_PALETTE);
465         ENTRY(VFW_E_TOO_MANY_COLORS);
466         ENTRY(VFW_E_STATE_CHANGED);
467         ENTRY(VFW_E_NOT_STOPPED);
468         ENTRY(VFW_E_NOT_PAUSED);
469         ENTRY(VFW_E_NOT_RUNNING);
470         ENTRY(VFW_E_WRONG_STATE);
471         ENTRY(VFW_E_START_TIME_AFTER_END);
472         ENTRY(VFW_E_INVALID_RECT);
473         ENTRY(VFW_E_TYPE_NOT_ACCEPTED);
474         ENTRY(VFW_E_SAMPLE_REJECTED);
475         ENTRY(VFW_E_SAMPLE_REJECTED_EOS);
476         ENTRY(VFW_S_DUPLICATE_NAME);
477         ENTRY(VFW_E_DUPLICATE_NAME);
478         ENTRY(VFW_E_TIMEOUT);
479         ENTRY(VFW_E_INVALID_FILE_FORMAT);
480         ENTRY(VFW_E_ENUM_OUT_OF_RANGE);
481         ENTRY(VFW_E_CIRCULAR_GRAPH);
482         ENTRY(VFW_E_NOT_ALLOWED_TO_SAVE);
483         ENTRY(VFW_E_TIME_ALREADY_PASSED);
484         ENTRY(VFW_E_ALREADY_CANCELLED);
485         ENTRY(VFW_E_CORRUPT_GRAPH_FILE);
486         ENTRY(VFW_E_ADVISE_ALREADY_SET);
487         ENTRY(VFW_S_STATE_INTERMEDIATE);
488         ENTRY(VFW_E_NO_MODEX_AVAILABLE);
489         ENTRY(VFW_E_NO_ADVISE_SET);
490         ENTRY(VFW_E_NO_FULLSCREEN);
491         ENTRY(VFW_E_IN_FULLSCREEN_MODE);
492         ENTRY(VFW_E_UNKNOWN_FILE_TYPE);
493         ENTRY(VFW_E_CANNOT_LOAD_SOURCE_FILTER);
494         ENTRY(VFW_S_PARTIAL_RENDER);
495         ENTRY(VFW_E_FILE_TOO_SHORT);
496         ENTRY(VFW_E_INVALID_FILE_VERSION);
497         ENTRY(VFW_S_SOME_DATA_IGNORED);
498         ENTRY(VFW_S_CONNECTIONS_DEFERRED);
499         ENTRY(VFW_E_INVALID_CLSID);
500         ENTRY(VFW_E_INVALID_MEDIA_TYPE);
501         ENTRY(VFW_E_SAMPLE_TIME_NOT_SET);
502         ENTRY(VFW_S_RESOURCE_NOT_NEEDED);
503         ENTRY(VFW_E_MEDIA_TIME_NOT_SET);
504         ENTRY(VFW_E_NO_TIME_FORMAT_SET);
505         ENTRY(VFW_E_MONO_AUDIO_HW);
506         ENTRY(VFW_S_MEDIA_TYPE_IGNORED);
507         ENTRY(VFW_E_NO_DECOMPRESSOR);
508         ENTRY(VFW_E_NO_AUDIO_HARDWARE);
509         ENTRY(VFW_S_VIDEO_NOT_RENDERED);
510         ENTRY(VFW_S_AUDIO_NOT_RENDERED);
511         ENTRY(VFW_E_RPZA);
512         ENTRY(VFW_S_RPZA);
513         ENTRY(VFW_E_PROCESSOR_NOT_SUITABLE);
514         ENTRY(VFW_E_UNSUPPORTED_AUDIO);
515         ENTRY(VFW_E_UNSUPPORTED_VIDEO);
516         ENTRY(VFW_E_MPEG_NOT_CONSTRAINED);
517         ENTRY(VFW_E_NOT_IN_GRAPH);
518         ENTRY(VFW_S_ESTIMATED);
519         ENTRY(VFW_E_NO_TIME_FORMAT);
520         ENTRY(VFW_E_READ_ONLY);
521         ENTRY(VFW_S_RESERVED);
522         ENTRY(VFW_E_BUFFER_UNDERFLOW);
523         ENTRY(VFW_E_UNSUPPORTED_STREAM);
524         ENTRY(VFW_E_NO_TRANSPORT);
525         ENTRY(VFW_S_STREAM_OFF);
526         ENTRY(VFW_S_CANT_CUE);
527         ENTRY(VFW_E_BAD_VIDEOCD);
528         ENTRY(VFW_S_NO_STOP_TIME);
529         ENTRY(VFW_E_OUT_OF_VIDEO_MEMORY);
530         ENTRY(VFW_E_VP_NEGOTIATION_FAILED);
531         ENTRY(VFW_E_DDRAW_CAPS_NOT_SUITABLE);
532         ENTRY(VFW_E_NO_VP_HARDWARE);
533         ENTRY(VFW_E_NO_CAPTURE_HARDWARE);
534         ENTRY(VFW_E_DVD_OPERATION_INHIBITED);
535         ENTRY(VFW_E_DVD_INVALIDDOMAIN);
536         ENTRY(VFW_E_DVD_NO_BUTTON);
537         ENTRY(VFW_E_DVD_GRAPHNOTREADY);
538         ENTRY(VFW_E_DVD_RENDERFAIL);
539         ENTRY(VFW_E_DVD_DECNOTENOUGH);
540         ENTRY(VFW_E_DDRAW_VERSION_NOT_SUITABLE);
541         ENTRY(VFW_E_COPYPROT_FAILED);
542         ENTRY(VFW_S_NOPREVIEWPIN);
543         ENTRY(VFW_E_TIME_EXPIRED);
544         ENTRY(VFW_S_DVD_NON_ONE_SEQUENTIAL);
545         ENTRY(VFW_E_DVD_WRONG_SPEED);
546         ENTRY(VFW_E_DVD_MENU_DOES_NOT_EXIST);
547         ENTRY(VFW_E_DVD_CMD_CANCELLED);
548         ENTRY(VFW_E_DVD_STATE_WRONG_VERSION);
549         ENTRY(VFW_E_DVD_STATE_CORRUPT);
550         ENTRY(VFW_E_DVD_STATE_WRONG_DISC);
551         ENTRY(VFW_E_DVD_INCOMPATIBLE_REGION);
552         ENTRY(VFW_E_DVD_NO_ATTRIBUTES);
553         ENTRY(VFW_E_DVD_NO_GOUP_PGC);
554         ENTRY(VFW_E_DVD_LOW_PARENTAL_LEVEL);
555         ENTRY(VFW_E_DVD_NOT_IN_KARAOKE_MODE);
556         ENTRY(VFW_S_DVD_CHANNEL_CONTENTS_NOT_AVAILABLE);
557         ENTRY(VFW_S_DVD_NOT_ACCURATE);
558         ENTRY(VFW_E_FRAME_STEP_UNSUPPORTED);
559         ENTRY(VFW_E_DVD_STREAM_DISABLED);
560         ENTRY(VFW_E_DVD_TITLE_UNKNOWN);
561         ENTRY(VFW_E_DVD_INVALID_DISC);
562         ENTRY(VFW_E_DVD_NO_RESUME_INFORMATION);
563         ENTRY(VFW_E_PIN_ALREADY_BLOCKED_ON_THIS_THREAD);
564         ENTRY(VFW_E_PIN_ALREADY_BLOCKED);
565         ENTRY(VFW_E_CERTIFICATION_FAILURE);
566         #undef  ENTRY
567         }
568
569         return NULL;
570 }
571
572 /***********************************************************************
573  *      AMGetErrorTextA (quartz.@)
574  */
575 DWORD WINAPI AMGetErrorTextA(HRESULT hr, LPSTR pszbuf, DWORD dwBufLen)
576 {
577         LPCSTR  lpszRes;
578         DWORD len;
579
580         lpszRes = hresult_to_string( hr );
581         if ( lpszRes == NULL )
582                 return 0;
583         len = (DWORD)(strlen(lpszRes)+1);
584         if ( len > dwBufLen )
585                 return 0;
586
587         memcpy( pszbuf, lpszRes, len );
588         return len;
589 }
590
591 /***********************************************************************
592  *      AMGetErrorTextW (quartz.@)
593  */
594 DWORD WINAPI AMGetErrorTextW(HRESULT hr, LPWSTR pwszbuf, DWORD dwBufLen)
595 {
596         CHAR    szBuf[MAX_ERROR_TEXT_LEN+1];
597         DWORD   dwLen;
598
599         dwLen = AMGetErrorTextA(hr,szBuf,MAX_ERROR_TEXT_LEN);
600         if ( dwLen == 0 )
601                 return 0;
602         szBuf[dwLen] = 0;
603
604         QUARTZ_strncpyAtoW( pwszbuf, szBuf, dwBufLen );
605
606         return lstrlenW( pwszbuf );
607 }