amstream: Implement AMAudioStream::NewSegment.
[wine/zf.git] / dlls / mf / main.c
blob3546caa6912aa0bbdc7eee0e01d701a2c76cf380
1 /*
2 * Copyright (C) 2015 Austin English
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "mfidl.h"
27 #include "rpcproxy.h"
29 #include "mfapi.h"
30 #include "mferror.h"
32 #include "mf_private.h"
34 #include "wine/debug.h"
35 #include "wine/heap.h"
36 #include "wine/list.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
40 static HINSTANCE mf_instance;
41 extern const GUID CLSID_FileSchemePlugin;
43 struct activate_object
45 IMFActivate IMFActivate_iface;
46 LONG refcount;
47 IMFAttributes *attributes;
48 IUnknown *object;
49 const struct activate_funcs *funcs;
50 void *context;
53 static struct activate_object *impl_from_IMFActivate(IMFActivate *iface)
55 return CONTAINING_RECORD(iface, struct activate_object, IMFActivate_iface);
58 static HRESULT WINAPI activate_object_QueryInterface(IMFActivate *iface, REFIID riid, void **obj)
60 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
62 if (IsEqualIID(riid, &IID_IMFActivate) ||
63 IsEqualIID(riid, &IID_IMFAttributes) ||
64 IsEqualIID(riid, &IID_IUnknown))
66 *obj = iface;
67 IMFActivate_AddRef(iface);
68 return S_OK;
71 WARN("Unsupported %s.\n", debugstr_guid(riid));
72 *obj = NULL;
73 return E_NOINTERFACE;
76 static ULONG WINAPI activate_object_AddRef(IMFActivate *iface)
78 struct activate_object *activate = impl_from_IMFActivate(iface);
79 ULONG refcount = InterlockedIncrement(&activate->refcount);
81 TRACE("%p, refcount %u.\n", iface, refcount);
83 return refcount;
86 static ULONG WINAPI activate_object_Release(IMFActivate *iface)
88 struct activate_object *activate = impl_from_IMFActivate(iface);
89 ULONG refcount = InterlockedDecrement(&activate->refcount);
91 TRACE("%p, refcount %u.\n", iface, refcount);
93 if (!refcount)
95 activate->funcs->free_private(activate->context);
96 if (activate->object)
97 IUnknown_Release(activate->object);
98 IMFAttributes_Release(activate->attributes);
99 heap_free(activate);
102 return refcount;
105 static HRESULT WINAPI activate_object_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
107 struct activate_object *activate = impl_from_IMFActivate(iface);
109 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
111 return IMFAttributes_GetItem(activate->attributes, key, value);
114 static HRESULT WINAPI activate_object_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
116 struct activate_object *activate = impl_from_IMFActivate(iface);
118 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
120 return IMFAttributes_GetItemType(activate->attributes, key, type);
123 static HRESULT WINAPI activate_object_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
125 struct activate_object *activate = impl_from_IMFActivate(iface);
127 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
129 return IMFAttributes_CompareItem(activate->attributes, key, value, result);
132 static HRESULT WINAPI activate_object_Compare(IMFActivate *iface, IMFAttributes *theirs, MF_ATTRIBUTES_MATCH_TYPE type,
133 BOOL *result)
135 struct activate_object *activate = impl_from_IMFActivate(iface);
137 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
139 return IMFAttributes_Compare(activate->attributes, theirs, type, result);
142 static HRESULT WINAPI activate_object_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
144 struct activate_object *activate = impl_from_IMFActivate(iface);
146 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
148 return IMFAttributes_GetUINT32(activate->attributes, key, value);
151 static HRESULT WINAPI activate_object_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
153 struct activate_object *activate = impl_from_IMFActivate(iface);
155 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
157 return IMFAttributes_GetUINT64(activate->attributes, key, value);
160 static HRESULT WINAPI activate_object_GetDouble(IMFActivate *iface, REFGUID key, double *value)
162 struct activate_object *activate = impl_from_IMFActivate(iface);
164 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
166 return IMFAttributes_GetDouble(activate->attributes, key, value);
169 static HRESULT WINAPI activate_object_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
171 struct activate_object *activate = impl_from_IMFActivate(iface);
173 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
175 return IMFAttributes_GetGUID(activate->attributes, key, value);
178 static HRESULT WINAPI activate_object_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
180 struct activate_object *activate = impl_from_IMFActivate(iface);
182 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
184 return IMFAttributes_GetStringLength(activate->attributes, key, length);
187 static HRESULT WINAPI activate_object_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
188 UINT32 size, UINT32 *length)
190 struct activate_object *activate = impl_from_IMFActivate(iface);
192 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), value, size, length);
194 return IMFAttributes_GetString(activate->attributes, key, value, size, length);
197 static HRESULT WINAPI activate_object_GetAllocatedString(IMFActivate *iface, REFGUID key,
198 WCHAR **value, UINT32 *length)
200 struct activate_object *activate = impl_from_IMFActivate(iface);
202 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
204 return IMFAttributes_GetAllocatedString(activate->attributes, key, value, length);
207 static HRESULT WINAPI activate_object_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
209 struct activate_object *activate = impl_from_IMFActivate(iface);
211 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
213 return IMFAttributes_GetBlobSize(activate->attributes, key, size);
216 static HRESULT WINAPI activate_object_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf,
217 UINT32 bufsize, UINT32 *blobsize)
219 struct activate_object *activate = impl_from_IMFActivate(iface);
221 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
223 return IMFAttributes_GetBlob(activate->attributes, key, buf, bufsize, blobsize);
226 static HRESULT WINAPI activate_object_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
228 struct activate_object *activate = impl_from_IMFActivate(iface);
230 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
232 return IMFAttributes_GetAllocatedBlob(activate->attributes, key, buf, size);
235 static HRESULT WINAPI activate_object_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **ppv)
237 struct activate_object *activate = impl_from_IMFActivate(iface);
239 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), ppv);
241 return IMFAttributes_GetUnknown(activate->attributes, key, riid, ppv);
244 static HRESULT WINAPI activate_object_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
246 struct activate_object *activate = impl_from_IMFActivate(iface);
248 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
250 return IMFAttributes_SetItem(activate->attributes, key, value);
253 static HRESULT WINAPI activate_object_DeleteItem(IMFActivate *iface, REFGUID key)
255 struct activate_object *activate = impl_from_IMFActivate(iface);
257 TRACE("%p, %s.\n", iface, debugstr_guid(key));
259 return IMFAttributes_DeleteItem(activate->attributes, key);
262 static HRESULT WINAPI activate_object_DeleteAllItems(IMFActivate *iface)
264 struct activate_object *activate = impl_from_IMFActivate(iface);
266 TRACE("%p.\n", iface);
268 return IMFAttributes_DeleteAllItems(activate->attributes);
271 static HRESULT WINAPI activate_object_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
273 struct activate_object *activate = impl_from_IMFActivate(iface);
275 TRACE("%p, %s, %d.\n", iface, debugstr_guid(key), value);
277 return IMFAttributes_SetUINT32(activate->attributes, key, value);
280 static HRESULT WINAPI activate_object_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
282 struct activate_object *activate = impl_from_IMFActivate(iface);
284 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
286 return IMFAttributes_SetUINT64(activate->attributes, key, value);
289 static HRESULT WINAPI activate_object_SetDouble(IMFActivate *iface, REFGUID key, double value)
291 struct activate_object *activate = impl_from_IMFActivate(iface);
293 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
295 return IMFAttributes_SetDouble(activate->attributes, key, value);
298 static HRESULT WINAPI activate_object_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
300 struct activate_object *activate = impl_from_IMFActivate(iface);
302 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
304 return IMFAttributes_SetGUID(activate->attributes, key, value);
307 static HRESULT WINAPI activate_object_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
309 struct activate_object *activate = impl_from_IMFActivate(iface);
311 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
313 return IMFAttributes_SetString(activate->attributes, key, value);
316 static HRESULT WINAPI activate_object_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
318 struct activate_object *activate = impl_from_IMFActivate(iface);
320 TRACE("%p, %s, %p, %d.\n", iface, debugstr_guid(key), buf, size);
322 return IMFAttributes_SetBlob(activate->attributes, key, buf, size);
325 static HRESULT WINAPI activate_object_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
327 struct activate_object *activate = impl_from_IMFActivate(iface);
329 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(key), unknown);
331 return IMFAttributes_SetUnknown(activate->attributes, key, unknown);
334 static HRESULT WINAPI activate_object_LockStore(IMFActivate *iface)
336 struct activate_object *activate = impl_from_IMFActivate(iface);
338 TRACE("%p.\n", iface);
340 return IMFAttributes_LockStore(activate->attributes);
343 static HRESULT WINAPI activate_object_UnlockStore(IMFActivate *iface)
345 struct activate_object *activate = impl_from_IMFActivate(iface);
347 TRACE("%p.\n", iface);
349 return IMFAttributes_UnlockStore(activate->attributes);
352 static HRESULT WINAPI activate_object_GetCount(IMFActivate *iface, UINT32 *count)
354 struct activate_object *activate = impl_from_IMFActivate(iface);
356 TRACE("%p, %p.\n", iface, count);
358 return IMFAttributes_GetCount(activate->attributes, count);
361 static HRESULT WINAPI activate_object_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key, PROPVARIANT *value)
363 struct activate_object *activate = impl_from_IMFActivate(iface);
365 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
367 return IMFAttributes_GetItemByIndex(activate->attributes, index, key, value);
370 static HRESULT WINAPI activate_object_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
372 struct activate_object *activate = impl_from_IMFActivate(iface);
374 TRACE("%p, %p.\n", iface, dest);
376 return IMFAttributes_CopyAllItems(activate->attributes, dest);
379 static HRESULT WINAPI activate_object_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
381 struct activate_object *activate = impl_from_IMFActivate(iface);
382 IUnknown *object;
383 HRESULT hr;
385 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
387 if (!activate->object)
389 if (FAILED(hr = activate->funcs->create_object((IMFAttributes *)iface, activate->context, &object)))
390 return hr;
392 if (InterlockedCompareExchangePointer((void **)&activate->object, object, NULL))
393 IUnknown_Release(object);
396 return IUnknown_QueryInterface(activate->object, riid, obj);
399 static HRESULT WINAPI activate_object_ShutdownObject(IMFActivate *iface)
401 struct activate_object *activate = impl_from_IMFActivate(iface);
402 IUnknown *object;
404 TRACE("%p.\n", iface);
406 if ((object = InterlockedCompareExchangePointer((void **)&activate->object, NULL, activate->object)))
408 activate->funcs->shutdown_object(activate->context, object);
409 IUnknown_Release(object);
412 return S_OK;
415 static HRESULT WINAPI activate_object_DetachObject(IMFActivate *iface)
417 TRACE("%p.\n", iface);
419 return E_NOTIMPL;
422 static const IMFActivateVtbl activate_object_vtbl =
424 activate_object_QueryInterface,
425 activate_object_AddRef,
426 activate_object_Release,
427 activate_object_GetItem,
428 activate_object_GetItemType,
429 activate_object_CompareItem,
430 activate_object_Compare,
431 activate_object_GetUINT32,
432 activate_object_GetUINT64,
433 activate_object_GetDouble,
434 activate_object_GetGUID,
435 activate_object_GetStringLength,
436 activate_object_GetString,
437 activate_object_GetAllocatedString,
438 activate_object_GetBlobSize,
439 activate_object_GetBlob,
440 activate_object_GetAllocatedBlob,
441 activate_object_GetUnknown,
442 activate_object_SetItem,
443 activate_object_DeleteItem,
444 activate_object_DeleteAllItems,
445 activate_object_SetUINT32,
446 activate_object_SetUINT64,
447 activate_object_SetDouble,
448 activate_object_SetGUID,
449 activate_object_SetString,
450 activate_object_SetBlob,
451 activate_object_SetUnknown,
452 activate_object_LockStore,
453 activate_object_UnlockStore,
454 activate_object_GetCount,
455 activate_object_GetItemByIndex,
456 activate_object_CopyAllItems,
457 activate_object_ActivateObject,
458 activate_object_ShutdownObject,
459 activate_object_DetachObject,
462 HRESULT create_activation_object(void *context, const struct activate_funcs *funcs, IMFActivate **ret)
464 struct activate_object *object;
465 HRESULT hr;
467 object = heap_alloc_zero(sizeof(*object));
468 if (!object)
469 return E_OUTOFMEMORY;
471 object->IMFActivate_iface.lpVtbl = &activate_object_vtbl;
472 object->refcount = 1;
473 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
475 heap_free(object);
476 return hr;
478 object->funcs = funcs;
479 object->context = context;
481 *ret = &object->IMFActivate_iface;
483 return S_OK;
486 struct class_factory
488 IClassFactory IClassFactory_iface;
489 HRESULT (*create_instance)(REFIID riid, void **obj);
492 static inline struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
494 return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
497 static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
499 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
501 if (IsEqualGUID(riid, &IID_IClassFactory) ||
502 IsEqualGUID(riid, &IID_IUnknown))
504 *obj = iface;
505 IClassFactory_AddRef(iface);
506 return S_OK;
509 WARN("%s is not supported.\n", debugstr_guid(riid));
510 *obj = NULL;
511 return E_NOINTERFACE;
514 static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
516 return 2;
519 static ULONG WINAPI class_factory_Release(IClassFactory *iface)
521 return 1;
524 static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
526 struct class_factory *factory = impl_from_IClassFactory(iface);
528 TRACE("%p, %p, %s, %p.\n", iface, outer, debugstr_guid(riid), obj);
530 if (outer)
532 *obj = NULL;
533 return CLASS_E_NOAGGREGATION;
536 return factory->create_instance(riid, obj);
539 static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL dolock)
541 FIXME("%d.\n", dolock);
543 return S_OK;
546 static const IClassFactoryVtbl class_factory_vtbl =
548 class_factory_QueryInterface,
549 class_factory_AddRef,
550 class_factory_Release,
551 class_factory_CreateInstance,
552 class_factory_LockServer,
555 struct file_scheme_handler_result
557 struct list entry;
558 IMFAsyncResult *result;
559 MF_OBJECT_TYPE obj_type;
560 IUnknown *object;
563 struct file_scheme_handler
565 IMFSchemeHandler IMFSchemeHandler_iface;
566 IMFAsyncCallback IMFAsyncCallback_iface;
567 LONG refcount;
568 IMFSourceResolver *resolver;
569 struct list results;
570 CRITICAL_SECTION cs;
573 static struct file_scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *iface)
575 return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFSchemeHandler_iface);
578 static struct file_scheme_handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
580 return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFAsyncCallback_iface);
583 static HRESULT WINAPI file_scheme_handler_QueryInterface(IMFSchemeHandler *iface, REFIID riid, void **obj)
585 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
587 if (IsEqualIID(riid, &IID_IMFSchemeHandler) ||
588 IsEqualIID(riid, &IID_IUnknown))
590 *obj = iface;
591 IMFSchemeHandler_AddRef(iface);
592 return S_OK;
595 WARN("Unsupported %s.\n", debugstr_guid(riid));
596 *obj = NULL;
597 return E_NOINTERFACE;
600 static ULONG WINAPI file_scheme_handler_AddRef(IMFSchemeHandler *iface)
602 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
603 ULONG refcount = InterlockedIncrement(&handler->refcount);
605 TRACE("%p, refcount %u.\n", handler, refcount);
607 return refcount;
610 static ULONG WINAPI file_scheme_handler_Release(IMFSchemeHandler *iface)
612 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
613 ULONG refcount = InterlockedDecrement(&handler->refcount);
614 struct file_scheme_handler_result *result, *next;
616 TRACE("%p, refcount %u.\n", iface, refcount);
618 if (!refcount)
620 LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct file_scheme_handler_result, entry)
622 list_remove(&result->entry);
623 IMFAsyncResult_Release(result->result);
624 if (result->object)
625 IUnknown_Release(result->object);
626 heap_free(result);
628 DeleteCriticalSection(&handler->cs);
629 if (handler->resolver)
630 IMFSourceResolver_Release(handler->resolver);
631 heap_free(handler);
634 return refcount;
637 struct create_object_context
639 IUnknown IUnknown_iface;
640 LONG refcount;
642 IPropertyStore *props;
643 WCHAR *url;
644 DWORD flags;
647 static struct create_object_context *impl_from_IUnknown(IUnknown *iface)
649 return CONTAINING_RECORD(iface, struct create_object_context, IUnknown_iface);
652 static HRESULT WINAPI create_object_context_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
654 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
656 if (IsEqualIID(riid, &IID_IUnknown))
658 *obj = iface;
659 IUnknown_AddRef(iface);
660 return S_OK;
663 WARN("Unsupported %s.\n", debugstr_guid(riid));
664 *obj = NULL;
665 return E_NOINTERFACE;
668 static ULONG WINAPI create_object_context_AddRef(IUnknown *iface)
670 struct create_object_context *context = impl_from_IUnknown(iface);
671 ULONG refcount = InterlockedIncrement(&context->refcount);
673 TRACE("%p, refcount %u.\n", iface, refcount);
675 return refcount;
678 static ULONG WINAPI create_object_context_Release(IUnknown *iface)
680 struct create_object_context *context = impl_from_IUnknown(iface);
681 ULONG refcount = InterlockedDecrement(&context->refcount);
683 TRACE("%p, refcount %u.\n", iface, refcount);
685 if (!refcount)
687 if (context->props)
688 IPropertyStore_Release(context->props);
689 heap_free(context->url);
690 heap_free(context);
693 return refcount;
696 static const IUnknownVtbl create_object_context_vtbl =
698 create_object_context_QueryInterface,
699 create_object_context_AddRef,
700 create_object_context_Release,
703 static WCHAR *heap_strdupW(const WCHAR *str)
705 WCHAR *ret = NULL;
707 if (str)
709 unsigned int size;
711 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
712 ret = heap_alloc(size);
713 if (ret)
714 memcpy(ret, str, size);
717 return ret;
720 static HRESULT WINAPI file_scheme_handler_BeginCreateObject(IMFSchemeHandler *iface, const WCHAR *url, DWORD flags,
721 IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
723 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
724 struct create_object_context *context;
725 IMFAsyncResult *caller, *item;
726 HRESULT hr;
728 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
730 if (cancel_cookie)
731 *cancel_cookie = NULL;
733 if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &caller)))
734 return hr;
736 context = heap_alloc(sizeof(*context));
737 if (!context)
739 IMFAsyncResult_Release(caller);
740 return E_OUTOFMEMORY;
743 context->IUnknown_iface.lpVtbl = &create_object_context_vtbl;
744 context->refcount = 1;
745 context->props = props;
746 if (context->props)
747 IPropertyStore_AddRef(context->props);
748 context->flags = flags;
749 context->url = heap_strdupW(url);
750 if (!context->url)
752 IMFAsyncResult_Release(caller);
753 IUnknown_Release(&context->IUnknown_iface);
754 return E_OUTOFMEMORY;
757 hr = MFCreateAsyncResult(&context->IUnknown_iface, &handler->IMFAsyncCallback_iface, (IUnknown *)caller, &item);
758 IUnknown_Release(&context->IUnknown_iface);
759 if (SUCCEEDED(hr))
761 if (SUCCEEDED(hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO, item)))
763 if (cancel_cookie)
765 *cancel_cookie = (IUnknown *)caller;
766 IUnknown_AddRef(*cancel_cookie);
770 IMFAsyncResult_Release(item);
772 IMFAsyncResult_Release(caller);
774 return hr;
777 static HRESULT WINAPI file_scheme_handler_EndCreateObject(IMFSchemeHandler *iface, IMFAsyncResult *result,
778 MF_OBJECT_TYPE *obj_type, IUnknown **object)
780 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
781 struct file_scheme_handler_result *found = NULL, *cur;
782 HRESULT hr;
784 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
786 EnterCriticalSection(&handler->cs);
788 LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
790 if (result == cur->result)
792 list_remove(&cur->entry);
793 found = cur;
794 break;
798 LeaveCriticalSection(&handler->cs);
800 if (found)
802 *obj_type = found->obj_type;
803 *object = found->object;
804 hr = IMFAsyncResult_GetStatus(found->result);
805 IMFAsyncResult_Release(found->result);
806 heap_free(found);
808 else
810 *obj_type = MF_OBJECT_INVALID;
811 *object = NULL;
812 hr = MF_E_UNEXPECTED;
815 return hr;
818 static HRESULT WINAPI file_scheme_handler_CancelObjectCreation(IMFSchemeHandler *iface, IUnknown *cancel_cookie)
820 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
821 struct file_scheme_handler_result *found = NULL, *cur;
823 TRACE("%p, %p.\n", iface, cancel_cookie);
825 EnterCriticalSection(&handler->cs);
827 LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
829 if (cancel_cookie == (IUnknown *)cur->result)
831 list_remove(&cur->entry);
832 found = cur;
833 break;
837 LeaveCriticalSection(&handler->cs);
839 if (found)
841 IMFAsyncResult_Release(found->result);
842 if (found->object)
843 IUnknown_Release(found->object);
844 heap_free(found);
847 return found ? S_OK : MF_E_UNEXPECTED;
850 static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl =
852 file_scheme_handler_QueryInterface,
853 file_scheme_handler_AddRef,
854 file_scheme_handler_Release,
855 file_scheme_handler_BeginCreateObject,
856 file_scheme_handler_EndCreateObject,
857 file_scheme_handler_CancelObjectCreation,
860 static HRESULT WINAPI file_scheme_handler_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
862 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
863 IsEqualIID(riid, &IID_IUnknown))
865 *obj = iface;
866 IMFAsyncCallback_AddRef(iface);
867 return S_OK;
870 WARN("Unsupported %s.\n", debugstr_guid(riid));
871 *obj = NULL;
872 return E_NOINTERFACE;
875 static ULONG WINAPI file_scheme_handler_callback_AddRef(IMFAsyncCallback *iface)
877 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
878 return IMFSchemeHandler_AddRef(&handler->IMFSchemeHandler_iface);
881 static ULONG WINAPI file_scheme_handler_callback_Release(IMFAsyncCallback *iface)
883 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
884 return IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
887 static HRESULT WINAPI file_scheme_handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
889 return E_NOTIMPL;
892 static HRESULT file_scheme_handler_get_resolver(struct file_scheme_handler *handler, IMFSourceResolver **resolver)
894 HRESULT hr;
896 if (!handler->resolver)
898 IMFSourceResolver *resolver;
900 if (FAILED(hr = MFCreateSourceResolver(&resolver)))
901 return hr;
903 if (InterlockedCompareExchangePointer((void **)&handler->resolver, resolver, NULL))
904 IMFSourceResolver_Release(resolver);
907 *resolver = handler->resolver;
908 IMFSourceResolver_AddRef(*resolver);
910 return S_OK;
913 static HRESULT WINAPI file_scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
915 static const WCHAR schemeW[] = {'f','i','l','e',':','/','/'};
916 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
917 struct file_scheme_handler_result *handler_result;
918 MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
919 IUnknown *object = NULL, *context_object;
920 struct create_object_context *context;
921 IMFSourceResolver *resolver;
922 IMFAsyncResult *caller;
923 IMFByteStream *stream;
924 const WCHAR *url;
925 HRESULT hr;
927 caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
929 if (FAILED(hr = IMFAsyncResult_GetObject(result, &context_object)))
931 WARN("Expected context set for callee result.\n");
932 return hr;
935 context = impl_from_IUnknown(context_object);
937 /* Strip from scheme, MFCreateFile() won't be expecting it. */
938 url = context->url;
939 if (!wcsnicmp(context->url, schemeW, ARRAY_SIZE(schemeW)))
940 url += ARRAY_SIZE(schemeW);
942 hr = MFCreateFile(context->flags & MF_RESOLUTION_WRITE ? MF_ACCESSMODE_READWRITE : MF_ACCESSMODE_READ,
943 MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, url, &stream);
944 if (SUCCEEDED(hr))
946 if (context->flags & MF_RESOLUTION_MEDIASOURCE)
948 if (SUCCEEDED(hr = file_scheme_handler_get_resolver(handler, &resolver)))
950 hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, context->url, context->flags,
951 context->props, &obj_type, &object);
952 IMFSourceResolver_Release(resolver);
953 IMFByteStream_Release(stream);
956 else
958 object = (IUnknown *)stream;
959 obj_type = MF_OBJECT_BYTESTREAM;
963 handler_result = heap_alloc(sizeof(*handler_result));
964 if (handler_result)
966 handler_result->result = caller;
967 IMFAsyncResult_AddRef(handler_result->result);
968 handler_result->obj_type = obj_type;
969 handler_result->object = object;
971 EnterCriticalSection(&handler->cs);
972 list_add_tail(&handler->results, &handler_result->entry);
973 LeaveCriticalSection(&handler->cs);
975 else
977 if (object)
978 IUnknown_Release(object);
979 hr = E_OUTOFMEMORY;
982 IUnknown_Release(&context->IUnknown_iface);
984 IMFAsyncResult_SetStatus(caller, hr);
985 MFInvokeCallback(caller);
987 return S_OK;
990 static const IMFAsyncCallbackVtbl file_scheme_handler_callback_vtbl =
992 file_scheme_handler_callback_QueryInterface,
993 file_scheme_handler_callback_AddRef,
994 file_scheme_handler_callback_Release,
995 file_scheme_handler_callback_GetParameters,
996 file_scheme_handler_callback_Invoke,
999 static HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
1001 struct file_scheme_handler *handler;
1002 HRESULT hr;
1004 TRACE("%s, %p.\n", debugstr_guid(riid), obj);
1006 handler = heap_alloc_zero(sizeof(*handler));
1007 if (!handler)
1008 return E_OUTOFMEMORY;
1010 handler->IMFSchemeHandler_iface.lpVtbl = &file_scheme_handler_vtbl;
1011 handler->IMFAsyncCallback_iface.lpVtbl = &file_scheme_handler_callback_vtbl;
1012 handler->refcount = 1;
1013 list_init(&handler->results);
1014 InitializeCriticalSection(&handler->cs);
1016 hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
1017 IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
1019 return hr;
1022 static struct class_factory file_scheme_handler_factory = { { &class_factory_vtbl }, file_scheme_handler_construct };
1024 static const struct class_object
1026 const GUID *clsid;
1027 IClassFactory *factory;
1029 class_objects[] =
1031 { &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface },
1034 /*******************************************************************************
1035 * DllGetClassObject (mf.@)
1037 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **obj)
1039 unsigned int i;
1041 TRACE("%s, %s, %p.\n", debugstr_guid(rclsid), debugstr_guid(riid), obj);
1043 for (i = 0; i < ARRAY_SIZE(class_objects); ++i)
1045 if (IsEqualGUID(class_objects[i].clsid, rclsid))
1046 return IClassFactory_QueryInterface(class_objects[i].factory, riid, obj);
1049 WARN("%s: class not found.\n", debugstr_guid(rclsid));
1050 return CLASS_E_CLASSNOTAVAILABLE;
1053 /******************************************************************
1054 * DllCanUnloadNow (mf.@)
1056 HRESULT WINAPI DllCanUnloadNow(void)
1058 return S_FALSE;
1061 /***********************************************************************
1062 * DllRegisterServer (mf.@)
1064 HRESULT WINAPI DllRegisterServer(void)
1066 return __wine_register_resources( mf_instance );
1069 /***********************************************************************
1070 * DllUnregisterServer (mf.@)
1072 HRESULT WINAPI DllUnregisterServer(void)
1074 return __wine_unregister_resources( mf_instance );
1077 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
1079 switch (reason)
1081 case DLL_WINE_PREATTACH:
1082 return FALSE; /* prefer native version */
1083 case DLL_PROCESS_ATTACH:
1084 mf_instance = instance;
1085 DisableThreadLibraryCalls(instance);
1086 break;
1089 return TRUE;
1092 static HRESULT prop_string_vector_append(PROPVARIANT *vector, unsigned int *capacity, BOOL unique, const WCHAR *str)
1094 WCHAR *ptrW;
1095 int len, i;
1097 if (unique)
1099 for (i = 0; i < vector->calpwstr.cElems; ++i)
1101 if (!lstrcmpW(vector->calpwstr.pElems[i], str))
1102 return S_OK;
1106 if (!*capacity || *capacity - 1 < vector->calpwstr.cElems)
1108 unsigned int new_count;
1109 WCHAR **ptr;
1111 new_count = *capacity ? *capacity * 2 : 10;
1112 ptr = CoTaskMemRealloc(vector->calpwstr.pElems, new_count * sizeof(*vector->calpwstr.pElems));
1113 if (!ptr)
1114 return E_OUTOFMEMORY;
1115 vector->calpwstr.pElems = ptr;
1116 *capacity = new_count;
1119 len = lstrlenW(str);
1120 if (!(vector->calpwstr.pElems[vector->calpwstr.cElems] = ptrW = CoTaskMemAlloc((len + 1) * sizeof(WCHAR))))
1121 return E_OUTOFMEMORY;
1123 lstrcpyW(ptrW, str);
1124 vector->calpwstr.cElems++;
1126 return S_OK;
1129 static int __cdecl qsort_string_compare(const void *a, const void *b)
1131 const WCHAR *left = *(const WCHAR **)a, *right = *(const WCHAR **)b;
1132 return lstrcmpW(left, right);
1135 static HRESULT mf_get_handler_strings(const WCHAR *path, WCHAR filter, unsigned int maxlen, PROPVARIANT *dst)
1137 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
1138 unsigned int capacity = 0, count, size;
1139 HRESULT hr = S_OK;
1140 int i, index;
1141 WCHAR *buffW;
1143 buffW = heap_calloc(maxlen, sizeof(*buffW));
1144 if (!buffW)
1145 return E_OUTOFMEMORY;
1147 memset(dst, 0, sizeof(*dst));
1148 dst->vt = VT_VECTOR | VT_LPWSTR;
1150 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
1152 HKEY hkey;
1154 if (RegOpenKeyW(hkey_roots[i], path, &hkey))
1155 continue;
1157 index = 0;
1158 size = maxlen;
1159 count = dst->calpwstr.cElems;
1160 while (!RegEnumKeyExW(hkey, index++, buffW, &size, NULL, NULL, NULL, NULL))
1162 if (filter && !wcschr(buffW, filter))
1163 continue;
1165 if (FAILED(hr = prop_string_vector_append(dst, &capacity, i > 0, buffW)))
1166 break;
1167 size = maxlen;
1170 /* Sort last pass results. */
1171 qsort(&dst->calpwstr.pElems[count], dst->calpwstr.cElems - count, sizeof(*dst->calpwstr.pElems),
1172 qsort_string_compare);
1174 RegCloseKey(hkey);
1177 if (FAILED(hr))
1178 PropVariantClear(dst);
1180 heap_free(buffW);
1182 return hr;
1185 /***********************************************************************
1186 * MFGetSupportedMimeTypes (mf.@)
1188 HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *dst)
1190 unsigned int maxlen;
1192 TRACE("%p.\n", dst);
1194 if (!dst)
1195 return E_POINTER;
1197 /* According to RFC4288 it's 127/127 characters. */
1198 maxlen = 127 /* type */ + 1 /* / */ + 127 /* subtype */ + 1;
1199 return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", '/',
1200 maxlen, dst);
1203 /***********************************************************************
1204 * MFGetSupportedSchemes (mf.@)
1206 HRESULT WINAPI MFGetSupportedSchemes(PROPVARIANT *dst)
1208 TRACE("%p.\n", dst);
1210 if (!dst)
1211 return E_POINTER;
1213 return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", 0, 64, dst);
1216 /***********************************************************************
1217 * MFGetService (mf.@)
1219 HRESULT WINAPI MFGetService(IUnknown *object, REFGUID service, REFIID riid, void **obj)
1221 IMFGetService *gs;
1222 HRESULT hr;
1224 TRACE("(%p, %s, %s, %p)\n", object, debugstr_guid(service), debugstr_guid(riid), obj);
1226 if (!object)
1227 return E_POINTER;
1229 if (FAILED(hr = IUnknown_QueryInterface(object, &IID_IMFGetService, (void **)&gs)))
1230 return hr;
1232 hr = IMFGetService_GetService(gs, service, riid, obj);
1233 IMFGetService_Release(gs);
1234 return hr;
1237 /***********************************************************************
1238 * MFShutdownObject (mf.@)
1240 HRESULT WINAPI MFShutdownObject(IUnknown *object)
1242 IMFShutdown *shutdown;
1244 TRACE("%p.\n", object);
1246 if (object && SUCCEEDED(IUnknown_QueryInterface(object, &IID_IMFShutdown, (void **)&shutdown)))
1248 IMFShutdown_Shutdown(shutdown);
1249 IMFShutdown_Release(shutdown);
1252 return S_OK;
1255 /***********************************************************************
1256 * MFEnumDeviceSources (mf.@)
1258 HRESULT WINAPI MFEnumDeviceSources(IMFAttributes *attributes, IMFActivate ***sources, UINT32 *count)
1260 FIXME("%p, %p, %p.\n", attributes, sources, count);
1262 if (!attributes || !sources || !count)
1263 return E_INVALIDARG;
1265 *count = 0;
1267 return S_OK;
1270 static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
1272 FIXME("%p, %p, %p.\n", attributes, user_context, obj);
1274 return E_NOTIMPL;
1277 static void evr_shutdown_object(void *user_context, IUnknown *obj)
1281 static void evr_free_private(void *user_context)
1285 static const struct activate_funcs evr_activate_funcs =
1287 evr_create_object,
1288 evr_shutdown_object,
1289 evr_free_private,
1292 HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
1294 HRESULT hr;
1296 TRACE("%p, %p.\n", hwnd, activate);
1298 if (!activate)
1299 return E_POINTER;
1301 hr = create_activation_object(hwnd, &evr_activate_funcs, activate);
1302 if (SUCCEEDED(hr))
1303 IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd);
1305 return hr;
1308 struct simple_type_handler
1310 IMFMediaTypeHandler IMFMediaTypeHandler_iface;
1311 LONG refcount;
1312 IMFMediaType *media_type;
1313 CRITICAL_SECTION cs;
1316 static struct simple_type_handler *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface)
1318 return CONTAINING_RECORD(iface, struct simple_type_handler, IMFMediaTypeHandler_iface);
1321 static HRESULT WINAPI simple_type_handler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid, void **obj)
1323 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1325 if (IsEqualIID(riid, &IID_IMFMediaTypeHandler) ||
1326 IsEqualIID(riid, &IID_IUnknown))
1328 *obj = iface;
1329 IMFMediaTypeHandler_AddRef(iface);
1330 return S_OK;
1333 *obj = NULL;
1334 return E_NOINTERFACE;
1337 static ULONG WINAPI simple_type_handler_AddRef(IMFMediaTypeHandler *iface)
1339 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1340 ULONG refcount = InterlockedIncrement(&handler->refcount);
1342 TRACE("%p, refcount %u.\n", iface, refcount);
1344 return refcount;
1347 static ULONG WINAPI simple_type_handler_Release(IMFMediaTypeHandler *iface)
1349 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1350 ULONG refcount = InterlockedDecrement(&handler->refcount);
1352 TRACE("%p, refcount %u.\n", iface, refcount);
1354 if (!refcount)
1356 if (handler->media_type)
1357 IMFMediaType_Release(handler->media_type);
1358 DeleteCriticalSection(&handler->cs);
1359 heap_free(handler);
1362 return refcount;
1365 static HRESULT WINAPI simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type,
1366 IMFMediaType **out_type)
1368 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1369 DWORD flags = 0;
1370 HRESULT hr;
1372 TRACE("%p, %p, %p.\n", iface, in_type, out_type);
1374 if (out_type)
1375 *out_type = NULL;
1377 EnterCriticalSection(&handler->cs);
1378 if (!handler->media_type)
1379 hr = MF_E_UNEXPECTED;
1380 else
1382 if (SUCCEEDED(hr = IMFMediaType_IsEqual(handler->media_type, in_type, &flags)))
1383 hr = (flags & (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES)) ==
1384 (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES) ? S_OK : E_FAIL;
1386 LeaveCriticalSection(&handler->cs);
1388 return hr;
1391 static HRESULT WINAPI simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
1393 TRACE("%p, %p.\n", iface, count);
1395 if (!count)
1396 return E_POINTER;
1398 *count = 1;
1400 return S_OK;
1403 static HRESULT WINAPI simple_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
1404 IMFMediaType **type)
1406 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1408 TRACE("%p, %u, %p.\n", iface, index, type);
1410 if (index > 0)
1411 return MF_E_NO_MORE_TYPES;
1413 EnterCriticalSection(&handler->cs);
1414 *type = handler->media_type;
1415 if (*type)
1416 IMFMediaType_AddRef(*type);
1417 LeaveCriticalSection(&handler->cs);
1419 return S_OK;
1422 static HRESULT WINAPI simple_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *media_type)
1424 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1426 TRACE("%p, %p.\n", iface, media_type);
1428 EnterCriticalSection(&handler->cs);
1429 if (handler->media_type)
1430 IMFMediaType_Release(handler->media_type);
1431 handler->media_type = media_type;
1432 if (handler->media_type)
1433 IMFMediaType_AddRef(handler->media_type);
1434 LeaveCriticalSection(&handler->cs);
1436 return S_OK;
1439 static HRESULT WINAPI simple_type_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **media_type)
1441 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1443 TRACE("%p, %p.\n", iface, media_type);
1445 if (!media_type)
1446 return E_POINTER;
1448 EnterCriticalSection(&handler->cs);
1449 *media_type = handler->media_type;
1450 if (*media_type)
1451 IMFMediaType_AddRef(*media_type);
1452 LeaveCriticalSection(&handler->cs);
1454 return S_OK;
1457 static HRESULT WINAPI simple_type_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
1459 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1460 HRESULT hr;
1462 TRACE("%p, %p.\n", iface, type);
1464 EnterCriticalSection(&handler->cs);
1465 if (handler->media_type)
1466 hr = IMFMediaType_GetGUID(handler->media_type, &MF_MT_MAJOR_TYPE, type);
1467 else
1468 hr = MF_E_NOT_INITIALIZED;
1469 LeaveCriticalSection(&handler->cs);
1471 return hr;
1474 static const IMFMediaTypeHandlerVtbl simple_type_handler_vtbl =
1476 simple_type_handler_QueryInterface,
1477 simple_type_handler_AddRef,
1478 simple_type_handler_Release,
1479 simple_type_handler_IsMediaTypeSupported,
1480 simple_type_handler_GetMediaTypeCount,
1481 simple_type_handler_GetMediaTypeByIndex,
1482 simple_type_handler_SetCurrentMediaType,
1483 simple_type_handler_GetCurrentMediaType,
1484 simple_type_handler_GetMajorType,
1487 HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler)
1489 struct simple_type_handler *object;
1491 TRACE("%p.\n", handler);
1493 object = heap_alloc_zero(sizeof(*object));
1494 if (!object)
1495 return E_OUTOFMEMORY;
1497 object->IMFMediaTypeHandler_iface.lpVtbl = &simple_type_handler_vtbl;
1498 object->refcount = 1;
1499 InitializeCriticalSection(&object->cs);
1501 *handler = &object->IMFMediaTypeHandler_iface;
1503 return S_OK;
1506 enum sample_copier_flags
1508 SAMPLE_COPIER_INPUT_TYPE_SET = 0x1,
1509 SAMPLE_COPIER_OUTPUT_TYPE_SET = 0x2
1512 struct sample_copier
1514 IMFTransform IMFTransform_iface;
1515 LONG refcount;
1517 IMFAttributes *attributes;
1518 IMFMediaType *buffer_type;
1519 DWORD buffer_size;
1520 IMFSample *sample;
1521 DWORD flags;
1522 CRITICAL_SECTION cs;
1525 static struct sample_copier *impl_copier_from_IMFTransform(IMFTransform *iface)
1527 return CONTAINING_RECORD(iface, struct sample_copier, IMFTransform_iface);
1530 static HRESULT WINAPI sample_copier_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
1532 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1534 if (IsEqualIID(riid, &IID_IMFTransform) ||
1535 IsEqualIID(riid, &IID_IUnknown))
1537 *obj = iface;
1538 IMFTransform_AddRef(iface);
1539 return S_OK;
1542 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
1543 *obj = NULL;
1544 return E_NOINTERFACE;
1547 static ULONG WINAPI sample_copier_transform_AddRef(IMFTransform *iface)
1549 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1550 ULONG refcount = InterlockedIncrement(&transform->refcount);
1552 TRACE("%p, refcount %u.\n", iface, refcount);
1554 return refcount;
1557 static ULONG WINAPI sample_copier_transform_Release(IMFTransform *iface)
1559 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1560 ULONG refcount = InterlockedDecrement(&transform->refcount);
1562 TRACE("%p, refcount %u.\n", iface, refcount);
1564 if (!refcount)
1566 IMFAttributes_Release(transform->attributes);
1567 if (transform->buffer_type)
1568 IMFMediaType_Release(transform->buffer_type);
1569 DeleteCriticalSection(&transform->cs);
1570 heap_free(transform);
1573 return refcount;
1576 static HRESULT WINAPI sample_copier_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
1577 DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
1579 TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
1581 *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
1583 return S_OK;
1586 static HRESULT WINAPI sample_copier_transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
1588 TRACE("%p, %p, %p.\n", iface, inputs, outputs);
1590 *inputs = 1;
1591 *outputs = 1;
1593 return S_OK;
1596 static HRESULT WINAPI sample_copier_transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
1597 DWORD output_size, DWORD *outputs)
1599 TRACE("%p, %u, %p, %u, %p.\n", iface, input_size, inputs, output_size, outputs);
1601 return E_NOTIMPL;
1604 static HRESULT WINAPI sample_copier_transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
1606 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1608 TRACE("%p, %u, %p.\n", iface, id, info);
1610 memset(info, 0, sizeof(*info));
1612 EnterCriticalSection(&transform->cs);
1613 info->cbSize = transform->buffer_size;
1614 LeaveCriticalSection(&transform->cs);
1616 return S_OK;
1619 static HRESULT WINAPI sample_copier_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id,
1620 MFT_OUTPUT_STREAM_INFO *info)
1622 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1624 TRACE("%p, %u, %p.\n", iface, id, info);
1626 memset(info, 0, sizeof(*info));
1628 EnterCriticalSection(&transform->cs);
1629 info->cbSize = transform->buffer_size;
1630 LeaveCriticalSection(&transform->cs);
1632 return S_OK;
1635 static HRESULT WINAPI sample_copier_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
1637 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1639 TRACE("%p, %p.\n", iface, attributes);
1641 *attributes = transform->attributes;
1642 IMFAttributes_AddRef(*attributes);
1644 return S_OK;
1647 static HRESULT WINAPI sample_copier_transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
1648 IMFAttributes **attributes)
1650 TRACE("%p, %u, %p.\n", iface, id, attributes);
1652 return E_NOTIMPL;
1655 static HRESULT WINAPI sample_copier_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
1656 IMFAttributes **attributes)
1658 TRACE("%p, %u, %p.\n", iface, id, attributes);
1660 return E_NOTIMPL;
1663 static HRESULT WINAPI sample_copier_transform_DeleteInputStream(IMFTransform *iface, DWORD id)
1665 TRACE("%p, %u.\n", iface, id);
1667 return E_NOTIMPL;
1670 static HRESULT WINAPI sample_copier_transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
1672 TRACE("%p, %u, %p.\n", iface, streams, ids);
1674 return E_NOTIMPL;
1677 static HRESULT WINAPI sample_copier_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
1678 IMFMediaType **type)
1680 static const GUID *types[] = { &MFMediaType_Video, &MFMediaType_Audio };
1681 HRESULT hr;
1683 TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
1685 if (id)
1686 return MF_E_INVALIDSTREAMNUMBER;
1688 if (index > ARRAY_SIZE(types) - 1)
1689 return MF_E_NO_MORE_TYPES;
1691 if (SUCCEEDED(hr = MFCreateMediaType(type)))
1692 hr = IMFMediaType_SetGUID(*type, &MF_MT_MAJOR_TYPE, types[index]);
1694 return hr;
1697 static HRESULT WINAPI sample_copier_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
1698 IMFMediaType **type)
1700 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1701 IMFMediaType *cloned_type = NULL;
1702 HRESULT hr = S_OK;
1704 TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
1706 EnterCriticalSection(&transform->cs);
1707 if (transform->buffer_type)
1709 if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type)))
1710 hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type);
1712 else if (id)
1713 hr = MF_E_INVALIDSTREAMNUMBER;
1714 else
1715 hr = MF_E_NO_MORE_TYPES;
1716 LeaveCriticalSection(&transform->cs);
1718 if (SUCCEEDED(hr))
1719 *type = cloned_type;
1720 else if (cloned_type)
1721 IMFMediaType_Release(cloned_type);
1723 return hr;
1726 static HRESULT sample_copier_get_buffer_size(IMFMediaType *type, DWORD *size)
1728 GUID major, subtype;
1729 UINT64 frame_size;
1730 HRESULT hr;
1732 *size = 0;
1734 if (FAILED(hr = IMFMediaType_GetMajorType(type, &major)))
1735 return hr;
1737 if (IsEqualGUID(&major, &MFMediaType_Video))
1739 if (SUCCEEDED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
1741 if (SUCCEEDED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
1743 if (FAILED(hr = MFCalculateImageSize(&subtype, (UINT32)(frame_size >> 32), (UINT32)frame_size, size)))
1744 WARN("Failed to get image size for video format %s.\n", debugstr_guid(&subtype));
1748 else if (IsEqualGUID(&major, &MFMediaType_Audio))
1750 FIXME("Audio formats are not handled.\n");
1751 hr = E_NOTIMPL;
1754 return hr;
1757 static HRESULT sample_copier_set_media_type(struct sample_copier *transform, BOOL input, DWORD id, IMFMediaType *type,
1758 DWORD flags)
1760 DWORD buffer_size;
1761 HRESULT hr = S_OK;
1763 if (id)
1764 return MF_E_INVALIDSTREAMNUMBER;
1766 EnterCriticalSection(&transform->cs);
1767 if (type)
1769 hr = sample_copier_get_buffer_size(type, &buffer_size);
1770 if (!(flags & MFT_SET_TYPE_TEST_ONLY) && SUCCEEDED(hr))
1772 if (!transform->buffer_type)
1773 hr = MFCreateMediaType(&transform->buffer_type);
1774 if (SUCCEEDED(hr))
1775 hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)transform->buffer_type);
1776 if (SUCCEEDED(hr))
1777 transform->buffer_size = buffer_size;
1779 if (SUCCEEDED(hr))
1781 if (input)
1783 transform->flags |= SAMPLE_COPIER_INPUT_TYPE_SET;
1784 transform->flags &= ~SAMPLE_COPIER_OUTPUT_TYPE_SET;
1786 else
1787 transform->flags |= SAMPLE_COPIER_OUTPUT_TYPE_SET;
1791 else if (transform->buffer_type)
1793 IMFMediaType_Release(transform->buffer_type);
1794 transform->buffer_type = NULL;
1796 LeaveCriticalSection(&transform->cs);
1798 return hr;
1801 static HRESULT WINAPI sample_copier_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
1803 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1805 TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
1807 return sample_copier_set_media_type(transform, TRUE, id, type, flags);
1810 static HRESULT WINAPI sample_copier_transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
1812 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1814 TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
1816 return sample_copier_set_media_type(transform, FALSE, id, type, flags);
1819 static HRESULT sample_copier_get_current_type(struct sample_copier *transform, DWORD id, DWORD flags,
1820 IMFMediaType **ret)
1822 IMFMediaType *cloned_type = NULL;
1823 HRESULT hr;
1825 if (id)
1826 return MF_E_INVALIDSTREAMNUMBER;
1828 EnterCriticalSection(&transform->cs);
1829 if (transform->flags & flags)
1831 if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type)))
1832 hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type);
1834 else
1835 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1836 LeaveCriticalSection(&transform->cs);
1838 if (SUCCEEDED(hr))
1839 *ret = cloned_type;
1840 else if (cloned_type)
1841 IMFMediaType_Release(cloned_type);
1843 return hr;
1846 static HRESULT WINAPI sample_copier_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
1848 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1850 TRACE("%p, %u, %p.\n", iface, id, type);
1852 return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_INPUT_TYPE_SET, type);
1855 static HRESULT WINAPI sample_copier_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
1857 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1859 TRACE("%p, %u, %p.\n", iface, id, type);
1861 return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_OUTPUT_TYPE_SET, type);
1864 static HRESULT WINAPI sample_copier_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
1866 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1867 HRESULT hr = S_OK;
1869 TRACE("%p, %u, %p.\n", iface, id, flags);
1871 if (id)
1872 return MF_E_INVALIDSTREAMNUMBER;
1874 EnterCriticalSection(&transform->cs);
1875 if (!(transform->flags & SAMPLE_COPIER_INPUT_TYPE_SET))
1876 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1877 else
1878 *flags = transform->sample ? 0 : MFT_INPUT_STATUS_ACCEPT_DATA;
1879 LeaveCriticalSection(&transform->cs);
1881 return hr;
1884 static HRESULT WINAPI sample_copier_transform_GetOutputStatus(IMFTransform *iface, DWORD *flags)
1886 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1887 HRESULT hr = S_OK;
1889 TRACE("%p, %p.\n", iface, flags);
1891 EnterCriticalSection(&transform->cs);
1892 if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET))
1893 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1894 else
1895 *flags = transform->sample ? MFT_OUTPUT_STATUS_SAMPLE_READY : 0;
1896 LeaveCriticalSection(&transform->cs);
1898 return hr;
1901 static HRESULT WINAPI sample_copier_transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
1903 TRACE("%p, %s, %s.\n", iface, debugstr_time(lower), debugstr_time(upper));
1905 return E_NOTIMPL;
1908 static HRESULT WINAPI sample_copier_transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
1910 FIXME("%p, %u, %p.\n", iface, id, event);
1912 return E_NOTIMPL;
1915 static HRESULT WINAPI sample_copier_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
1917 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1919 TRACE("%p, %#x, %p.\n", iface, message, (void *)param);
1921 EnterCriticalSection(&transform->cs);
1923 if (message == MFT_MESSAGE_COMMAND_FLUSH)
1925 if (transform->sample)
1927 IMFSample_Release(transform->sample);
1928 transform->sample = NULL;
1932 LeaveCriticalSection(&transform->cs);
1934 return S_OK;
1937 static HRESULT WINAPI sample_copier_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
1939 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1940 HRESULT hr = S_OK;
1942 TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags);
1944 if (id)
1945 return MF_E_INVALIDSTREAMNUMBER;
1947 EnterCriticalSection(&transform->cs);
1948 if (!transform->buffer_type)
1949 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1950 else if (transform->sample)
1951 hr = MF_E_NOTACCEPTING;
1952 else
1954 transform->sample = sample;
1955 IMFSample_AddRef(transform->sample);
1957 LeaveCriticalSection(&transform->cs);
1959 return hr;
1962 static HRESULT WINAPI sample_copier_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
1963 MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
1965 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1966 IMFMediaBuffer *buffer;
1967 DWORD sample_flags;
1968 HRESULT hr = S_OK;
1969 LONGLONG time;
1971 TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, buffers, status);
1973 EnterCriticalSection(&transform->cs);
1974 if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET))
1975 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1976 else if (!transform->sample)
1977 hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
1978 else
1980 IMFSample_CopyAllItems(transform->sample, (IMFAttributes *)buffers->pSample);
1982 if (SUCCEEDED(IMFSample_GetSampleDuration(transform->sample, &time)))
1983 IMFSample_SetSampleDuration(buffers->pSample, time);
1985 if (SUCCEEDED(IMFSample_GetSampleTime(transform->sample, &time)))
1986 IMFSample_SetSampleTime(buffers->pSample, time);
1988 if (SUCCEEDED(IMFSample_GetSampleFlags(transform->sample, &sample_flags)))
1989 IMFSample_SetSampleFlags(buffers->pSample, sample_flags);
1991 if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(transform->sample, NULL)))
1993 if (SUCCEEDED(IMFSample_GetBufferByIndex(buffers->pSample, 0, &buffer)))
1995 if (FAILED(IMFSample_CopyToBuffer(transform->sample, buffer)))
1996 hr = MF_E_UNEXPECTED;
1997 IMFMediaBuffer_Release(buffer);
2001 IMFSample_Release(transform->sample);
2002 transform->sample = NULL;
2004 LeaveCriticalSection(&transform->cs);
2006 return hr;
2009 static const IMFTransformVtbl sample_copier_transform_vtbl =
2011 sample_copier_transform_QueryInterface,
2012 sample_copier_transform_AddRef,
2013 sample_copier_transform_Release,
2014 sample_copier_transform_GetStreamLimits,
2015 sample_copier_transform_GetStreamCount,
2016 sample_copier_transform_GetStreamIDs,
2017 sample_copier_transform_GetInputStreamInfo,
2018 sample_copier_transform_GetOutputStreamInfo,
2019 sample_copier_transform_GetAttributes,
2020 sample_copier_transform_GetInputStreamAttributes,
2021 sample_copier_transform_GetOutputStreamAttributes,
2022 sample_copier_transform_DeleteInputStream,
2023 sample_copier_transform_AddInputStreams,
2024 sample_copier_transform_GetInputAvailableType,
2025 sample_copier_transform_GetOutputAvailableType,
2026 sample_copier_transform_SetInputType,
2027 sample_copier_transform_SetOutputType,
2028 sample_copier_transform_GetInputCurrentType,
2029 sample_copier_transform_GetOutputCurrentType,
2030 sample_copier_transform_GetInputStatus,
2031 sample_copier_transform_GetOutputStatus,
2032 sample_copier_transform_SetOutputBounds,
2033 sample_copier_transform_ProcessEvent,
2034 sample_copier_transform_ProcessMessage,
2035 sample_copier_transform_ProcessInput,
2036 sample_copier_transform_ProcessOutput,
2039 HRESULT WINAPI MFCreateSampleCopierMFT(IMFTransform **transform)
2041 struct sample_copier *object;
2043 TRACE("%p.\n", transform);
2045 object = heap_alloc_zero(sizeof(*object));
2046 if (!object)
2047 return E_OUTOFMEMORY;
2049 object->IMFTransform_iface.lpVtbl = &sample_copier_transform_vtbl;
2050 object->refcount = 1;
2051 MFCreateAttributes(&object->attributes, 0);
2052 InitializeCriticalSection(&object->cs);
2054 *transform = &object->IMFTransform_iface;
2056 return S_OK;