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