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