mf: Add default attributes for sample copier.
[wine.git] / dlls / mf / main.c
blobc48fc81a1d20bbcf2d46c8b90aed3d2c5ec1f7d0
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 "mf_private.h"
31 #include "wine/debug.h"
32 #include "wine/heap.h"
33 #include "wine/list.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
37 static HINSTANCE mf_instance;
38 extern const GUID CLSID_FileSchemePlugin;
40 struct activate_object
42 IMFActivate IMFActivate_iface;
43 LONG refcount;
44 IMFAttributes *attributes;
45 IUnknown *object;
46 const struct activate_funcs *funcs;
47 void *context;
50 static struct activate_object *impl_from_IMFActivate(IMFActivate *iface)
52 return CONTAINING_RECORD(iface, struct activate_object, IMFActivate_iface);
55 static HRESULT WINAPI activate_object_QueryInterface(IMFActivate *iface, REFIID riid, void **obj)
57 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
59 if (IsEqualIID(riid, &IID_IMFActivate) ||
60 IsEqualIID(riid, &IID_IMFAttributes) ||
61 IsEqualIID(riid, &IID_IUnknown))
63 *obj = iface;
64 IMFActivate_AddRef(iface);
65 return S_OK;
68 WARN("Unsupported %s.\n", debugstr_guid(riid));
69 *obj = NULL;
70 return E_NOINTERFACE;
73 static ULONG WINAPI activate_object_AddRef(IMFActivate *iface)
75 struct activate_object *activate = impl_from_IMFActivate(iface);
76 ULONG refcount = InterlockedIncrement(&activate->refcount);
78 TRACE("%p, refcount %u.\n", iface, refcount);
80 return refcount;
83 static ULONG WINAPI activate_object_Release(IMFActivate *iface)
85 struct activate_object *activate = impl_from_IMFActivate(iface);
86 ULONG refcount = InterlockedDecrement(&activate->refcount);
88 TRACE("%p, refcount %u.\n", iface, refcount);
90 if (!refcount)
92 if (activate->funcs->free_private)
93 activate->funcs->free_private(activate->context);
94 if (activate->object)
95 IUnknown_Release(activate->object);
96 IMFAttributes_Release(activate->attributes);
97 heap_free(activate);
100 return refcount;
103 static HRESULT WINAPI activate_object_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
105 struct activate_object *activate = impl_from_IMFActivate(iface);
107 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
109 return IMFAttributes_GetItem(activate->attributes, key, value);
112 static HRESULT WINAPI activate_object_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
114 struct activate_object *activate = impl_from_IMFActivate(iface);
116 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
118 return IMFAttributes_GetItemType(activate->attributes, key, type);
121 static HRESULT WINAPI activate_object_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
123 struct activate_object *activate = impl_from_IMFActivate(iface);
125 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
127 return IMFAttributes_CompareItem(activate->attributes, key, value, result);
130 static HRESULT WINAPI activate_object_Compare(IMFActivate *iface, IMFAttributes *theirs, MF_ATTRIBUTES_MATCH_TYPE type,
131 BOOL *result)
133 struct activate_object *activate = impl_from_IMFActivate(iface);
135 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
137 return IMFAttributes_Compare(activate->attributes, theirs, type, result);
140 static HRESULT WINAPI activate_object_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
142 struct activate_object *activate = impl_from_IMFActivate(iface);
144 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
146 return IMFAttributes_GetUINT32(activate->attributes, key, value);
149 static HRESULT WINAPI activate_object_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
151 struct activate_object *activate = impl_from_IMFActivate(iface);
153 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
155 return IMFAttributes_GetUINT64(activate->attributes, key, value);
158 static HRESULT WINAPI activate_object_GetDouble(IMFActivate *iface, REFGUID key, double *value)
160 struct activate_object *activate = impl_from_IMFActivate(iface);
162 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
164 return IMFAttributes_GetDouble(activate->attributes, key, value);
167 static HRESULT WINAPI activate_object_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
169 struct activate_object *activate = impl_from_IMFActivate(iface);
171 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
173 return IMFAttributes_GetGUID(activate->attributes, key, value);
176 static HRESULT WINAPI activate_object_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
178 struct activate_object *activate = impl_from_IMFActivate(iface);
180 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
182 return IMFAttributes_GetStringLength(activate->attributes, key, length);
185 static HRESULT WINAPI activate_object_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
186 UINT32 size, UINT32 *length)
188 struct activate_object *activate = impl_from_IMFActivate(iface);
190 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), value, size, length);
192 return IMFAttributes_GetString(activate->attributes, key, value, size, length);
195 static HRESULT WINAPI activate_object_GetAllocatedString(IMFActivate *iface, REFGUID key,
196 WCHAR **value, UINT32 *length)
198 struct activate_object *activate = impl_from_IMFActivate(iface);
200 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
202 return IMFAttributes_GetAllocatedString(activate->attributes, key, value, length);
205 static HRESULT WINAPI activate_object_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
207 struct activate_object *activate = impl_from_IMFActivate(iface);
209 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
211 return IMFAttributes_GetBlobSize(activate->attributes, key, size);
214 static HRESULT WINAPI activate_object_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf,
215 UINT32 bufsize, UINT32 *blobsize)
217 struct activate_object *activate = impl_from_IMFActivate(iface);
219 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
221 return IMFAttributes_GetBlob(activate->attributes, key, buf, bufsize, blobsize);
224 static HRESULT WINAPI activate_object_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
226 struct activate_object *activate = impl_from_IMFActivate(iface);
228 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
230 return IMFAttributes_GetAllocatedBlob(activate->attributes, key, buf, size);
233 static HRESULT WINAPI activate_object_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **ppv)
235 struct activate_object *activate = impl_from_IMFActivate(iface);
237 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), ppv);
239 return IMFAttributes_GetUnknown(activate->attributes, key, riid, ppv);
242 static HRESULT WINAPI activate_object_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
244 struct activate_object *activate = impl_from_IMFActivate(iface);
246 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
248 return IMFAttributes_SetItem(activate->attributes, key, value);
251 static HRESULT WINAPI activate_object_DeleteItem(IMFActivate *iface, REFGUID key)
253 struct activate_object *activate = impl_from_IMFActivate(iface);
255 TRACE("%p, %s.\n", iface, debugstr_guid(key));
257 return IMFAttributes_DeleteItem(activate->attributes, key);
260 static HRESULT WINAPI activate_object_DeleteAllItems(IMFActivate *iface)
262 struct activate_object *activate = impl_from_IMFActivate(iface);
264 TRACE("%p.\n", iface);
266 return IMFAttributes_DeleteAllItems(activate->attributes);
269 static HRESULT WINAPI activate_object_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
271 struct activate_object *activate = impl_from_IMFActivate(iface);
273 TRACE("%p, %s, %d.\n", iface, debugstr_guid(key), value);
275 return IMFAttributes_SetUINT32(activate->attributes, key, value);
278 static HRESULT WINAPI activate_object_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
280 struct activate_object *activate = impl_from_IMFActivate(iface);
282 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
284 return IMFAttributes_SetUINT64(activate->attributes, key, value);
287 static HRESULT WINAPI activate_object_SetDouble(IMFActivate *iface, REFGUID key, double value)
289 struct activate_object *activate = impl_from_IMFActivate(iface);
291 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
293 return IMFAttributes_SetDouble(activate->attributes, key, value);
296 static HRESULT WINAPI activate_object_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
298 struct activate_object *activate = impl_from_IMFActivate(iface);
300 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
302 return IMFAttributes_SetGUID(activate->attributes, key, value);
305 static HRESULT WINAPI activate_object_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
307 struct activate_object *activate = impl_from_IMFActivate(iface);
309 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
311 return IMFAttributes_SetString(activate->attributes, key, value);
314 static HRESULT WINAPI activate_object_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
316 struct activate_object *activate = impl_from_IMFActivate(iface);
318 TRACE("%p, %s, %p, %d.\n", iface, debugstr_guid(key), buf, size);
320 return IMFAttributes_SetBlob(activate->attributes, key, buf, size);
323 static HRESULT WINAPI activate_object_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
325 struct activate_object *activate = impl_from_IMFActivate(iface);
327 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(key), unknown);
329 return IMFAttributes_SetUnknown(activate->attributes, key, unknown);
332 static HRESULT WINAPI activate_object_LockStore(IMFActivate *iface)
334 struct activate_object *activate = impl_from_IMFActivate(iface);
336 TRACE("%p.\n", iface);
338 return IMFAttributes_LockStore(activate->attributes);
341 static HRESULT WINAPI activate_object_UnlockStore(IMFActivate *iface)
343 struct activate_object *activate = impl_from_IMFActivate(iface);
345 TRACE("%p.\n", iface);
347 return IMFAttributes_UnlockStore(activate->attributes);
350 static HRESULT WINAPI activate_object_GetCount(IMFActivate *iface, UINT32 *count)
352 struct activate_object *activate = impl_from_IMFActivate(iface);
354 TRACE("%p, %p.\n", iface, count);
356 return IMFAttributes_GetCount(activate->attributes, count);
359 static HRESULT WINAPI activate_object_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key, PROPVARIANT *value)
361 struct activate_object *activate = impl_from_IMFActivate(iface);
363 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
365 return IMFAttributes_GetItemByIndex(activate->attributes, index, key, value);
368 static HRESULT WINAPI activate_object_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
370 struct activate_object *activate = impl_from_IMFActivate(iface);
372 TRACE("%p, %p.\n", iface, dest);
374 return IMFAttributes_CopyAllItems(activate->attributes, dest);
377 static HRESULT WINAPI activate_object_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
379 struct activate_object *activate = impl_from_IMFActivate(iface);
380 IUnknown *object;
381 HRESULT hr;
383 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
385 if (!activate->object)
387 if (FAILED(hr = activate->funcs->create_object((IMFAttributes *)iface, activate->context, &object)))
388 return hr;
390 if (InterlockedCompareExchangePointer((void **)&activate->object, object, NULL))
391 IUnknown_Release(object);
394 return IUnknown_QueryInterface(activate->object, riid, obj);
397 static HRESULT WINAPI activate_object_ShutdownObject(IMFActivate *iface)
399 struct activate_object *activate = impl_from_IMFActivate(iface);
400 IUnknown *object;
402 TRACE("%p.\n", iface);
404 if ((object = InterlockedCompareExchangePointer((void **)&activate->object, NULL, activate->object)))
406 activate->funcs->shutdown_object(activate->context, object);
407 IUnknown_Release(object);
410 return S_OK;
413 static HRESULT WINAPI activate_object_DetachObject(IMFActivate *iface)
415 TRACE("%p.\n", iface);
417 return E_NOTIMPL;
420 static const IMFActivateVtbl activate_object_vtbl =
422 activate_object_QueryInterface,
423 activate_object_AddRef,
424 activate_object_Release,
425 activate_object_GetItem,
426 activate_object_GetItemType,
427 activate_object_CompareItem,
428 activate_object_Compare,
429 activate_object_GetUINT32,
430 activate_object_GetUINT64,
431 activate_object_GetDouble,
432 activate_object_GetGUID,
433 activate_object_GetStringLength,
434 activate_object_GetString,
435 activate_object_GetAllocatedString,
436 activate_object_GetBlobSize,
437 activate_object_GetBlob,
438 activate_object_GetAllocatedBlob,
439 activate_object_GetUnknown,
440 activate_object_SetItem,
441 activate_object_DeleteItem,
442 activate_object_DeleteAllItems,
443 activate_object_SetUINT32,
444 activate_object_SetUINT64,
445 activate_object_SetDouble,
446 activate_object_SetGUID,
447 activate_object_SetString,
448 activate_object_SetBlob,
449 activate_object_SetUnknown,
450 activate_object_LockStore,
451 activate_object_UnlockStore,
452 activate_object_GetCount,
453 activate_object_GetItemByIndex,
454 activate_object_CopyAllItems,
455 activate_object_ActivateObject,
456 activate_object_ShutdownObject,
457 activate_object_DetachObject,
460 HRESULT create_activation_object(void *context, const struct activate_funcs *funcs, IMFActivate **ret)
462 struct activate_object *object;
463 HRESULT hr;
465 object = heap_alloc_zero(sizeof(*object));
466 if (!object)
467 return E_OUTOFMEMORY;
469 object->IMFActivate_iface.lpVtbl = &activate_object_vtbl;
470 object->refcount = 1;
471 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
473 heap_free(object);
474 return hr;
476 object->funcs = funcs;
477 object->context = context;
479 *ret = &object->IMFActivate_iface;
481 return S_OK;
484 struct class_factory
486 IClassFactory IClassFactory_iface;
487 HRESULT (*create_instance)(REFIID riid, void **obj);
490 static inline struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
492 return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
495 static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
497 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
499 if (IsEqualGUID(riid, &IID_IClassFactory) ||
500 IsEqualGUID(riid, &IID_IUnknown))
502 *obj = iface;
503 IClassFactory_AddRef(iface);
504 return S_OK;
507 WARN("%s is not supported.\n", debugstr_guid(riid));
508 *obj = NULL;
509 return E_NOINTERFACE;
512 static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
514 return 2;
517 static ULONG WINAPI class_factory_Release(IClassFactory *iface)
519 return 1;
522 static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
524 struct class_factory *factory = impl_from_IClassFactory(iface);
526 TRACE("%p, %p, %s, %p.\n", iface, outer, debugstr_guid(riid), obj);
528 if (outer)
530 *obj = NULL;
531 return CLASS_E_NOAGGREGATION;
534 return factory->create_instance(riid, obj);
537 static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL dolock)
539 FIXME("%d.\n", dolock);
541 return S_OK;
544 static const IClassFactoryVtbl class_factory_vtbl =
546 class_factory_QueryInterface,
547 class_factory_AddRef,
548 class_factory_Release,
549 class_factory_CreateInstance,
550 class_factory_LockServer,
553 struct file_scheme_handler_result
555 struct list entry;
556 IMFAsyncResult *result;
557 MF_OBJECT_TYPE obj_type;
558 IUnknown *object;
561 struct file_scheme_handler
563 IMFSchemeHandler IMFSchemeHandler_iface;
564 IMFAsyncCallback IMFAsyncCallback_iface;
565 LONG refcount;
566 IMFSourceResolver *resolver;
567 struct list results;
568 CRITICAL_SECTION cs;
571 static struct file_scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *iface)
573 return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFSchemeHandler_iface);
576 static struct file_scheme_handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
578 return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFAsyncCallback_iface);
581 static HRESULT WINAPI file_scheme_handler_QueryInterface(IMFSchemeHandler *iface, REFIID riid, void **obj)
583 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
585 if (IsEqualIID(riid, &IID_IMFSchemeHandler) ||
586 IsEqualIID(riid, &IID_IUnknown))
588 *obj = iface;
589 IMFSchemeHandler_AddRef(iface);
590 return S_OK;
593 WARN("Unsupported %s.\n", debugstr_guid(riid));
594 *obj = NULL;
595 return E_NOINTERFACE;
598 static ULONG WINAPI file_scheme_handler_AddRef(IMFSchemeHandler *iface)
600 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
601 ULONG refcount = InterlockedIncrement(&handler->refcount);
603 TRACE("%p, refcount %u.\n", handler, refcount);
605 return refcount;
608 static ULONG WINAPI file_scheme_handler_Release(IMFSchemeHandler *iface)
610 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
611 ULONG refcount = InterlockedDecrement(&handler->refcount);
612 struct file_scheme_handler_result *result, *next;
614 TRACE("%p, refcount %u.\n", iface, refcount);
616 if (!refcount)
618 LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct file_scheme_handler_result, entry)
620 list_remove(&result->entry);
621 IMFAsyncResult_Release(result->result);
622 if (result->object)
623 IUnknown_Release(result->object);
624 heap_free(result);
626 DeleteCriticalSection(&handler->cs);
627 if (handler->resolver)
628 IMFSourceResolver_Release(handler->resolver);
629 heap_free(handler);
632 return refcount;
635 struct create_object_context
637 IUnknown IUnknown_iface;
638 LONG refcount;
640 IPropertyStore *props;
641 WCHAR *url;
642 DWORD flags;
645 static struct create_object_context *impl_from_IUnknown(IUnknown *iface)
647 return CONTAINING_RECORD(iface, struct create_object_context, IUnknown_iface);
650 static HRESULT WINAPI create_object_context_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
652 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
654 if (IsEqualIID(riid, &IID_IUnknown))
656 *obj = iface;
657 IUnknown_AddRef(iface);
658 return S_OK;
661 WARN("Unsupported %s.\n", debugstr_guid(riid));
662 *obj = NULL;
663 return E_NOINTERFACE;
666 static ULONG WINAPI create_object_context_AddRef(IUnknown *iface)
668 struct create_object_context *context = impl_from_IUnknown(iface);
669 ULONG refcount = InterlockedIncrement(&context->refcount);
671 TRACE("%p, refcount %u.\n", iface, refcount);
673 return refcount;
676 static ULONG WINAPI create_object_context_Release(IUnknown *iface)
678 struct create_object_context *context = impl_from_IUnknown(iface);
679 ULONG refcount = InterlockedDecrement(&context->refcount);
681 TRACE("%p, refcount %u.\n", iface, refcount);
683 if (!refcount)
685 if (context->props)
686 IPropertyStore_Release(context->props);
687 heap_free(context->url);
688 heap_free(context);
691 return refcount;
694 static const IUnknownVtbl create_object_context_vtbl =
696 create_object_context_QueryInterface,
697 create_object_context_AddRef,
698 create_object_context_Release,
701 static WCHAR *heap_strdupW(const WCHAR *str)
703 WCHAR *ret = NULL;
705 if (str)
707 unsigned int size;
709 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
710 ret = heap_alloc(size);
711 if (ret)
712 memcpy(ret, str, size);
715 return ret;
718 static HRESULT WINAPI file_scheme_handler_BeginCreateObject(IMFSchemeHandler *iface, const WCHAR *url, DWORD flags,
719 IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
721 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
722 struct create_object_context *context;
723 IMFAsyncResult *caller, *item;
724 HRESULT hr;
726 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
728 if (cancel_cookie)
729 *cancel_cookie = NULL;
731 if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &caller)))
732 return hr;
734 context = heap_alloc(sizeof(*context));
735 if (!context)
737 IMFAsyncResult_Release(caller);
738 return E_OUTOFMEMORY;
741 context->IUnknown_iface.lpVtbl = &create_object_context_vtbl;
742 context->refcount = 1;
743 context->props = props;
744 if (context->props)
745 IPropertyStore_AddRef(context->props);
746 context->flags = flags;
747 context->url = heap_strdupW(url);
748 if (!context->url)
750 IMFAsyncResult_Release(caller);
751 IUnknown_Release(&context->IUnknown_iface);
752 return E_OUTOFMEMORY;
755 hr = MFCreateAsyncResult(&context->IUnknown_iface, &handler->IMFAsyncCallback_iface, (IUnknown *)caller, &item);
756 IUnknown_Release(&context->IUnknown_iface);
757 if (SUCCEEDED(hr))
759 if (SUCCEEDED(hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO, item)))
761 if (cancel_cookie)
763 *cancel_cookie = (IUnknown *)caller;
764 IUnknown_AddRef(*cancel_cookie);
768 IMFAsyncResult_Release(item);
770 IMFAsyncResult_Release(caller);
772 return hr;
775 static HRESULT WINAPI file_scheme_handler_EndCreateObject(IMFSchemeHandler *iface, IMFAsyncResult *result,
776 MF_OBJECT_TYPE *obj_type, IUnknown **object)
778 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
779 struct file_scheme_handler_result *found = NULL, *cur;
780 HRESULT hr;
782 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
784 EnterCriticalSection(&handler->cs);
786 LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
788 if (result == cur->result)
790 list_remove(&cur->entry);
791 found = cur;
792 break;
796 LeaveCriticalSection(&handler->cs);
798 if (found)
800 *obj_type = found->obj_type;
801 *object = found->object;
802 hr = IMFAsyncResult_GetStatus(found->result);
803 IMFAsyncResult_Release(found->result);
804 heap_free(found);
806 else
808 *obj_type = MF_OBJECT_INVALID;
809 *object = NULL;
810 hr = MF_E_UNEXPECTED;
813 return hr;
816 static HRESULT WINAPI file_scheme_handler_CancelObjectCreation(IMFSchemeHandler *iface, IUnknown *cancel_cookie)
818 struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
819 struct file_scheme_handler_result *found = NULL, *cur;
821 TRACE("%p, %p.\n", iface, cancel_cookie);
823 EnterCriticalSection(&handler->cs);
825 LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
827 if (cancel_cookie == (IUnknown *)cur->result)
829 list_remove(&cur->entry);
830 found = cur;
831 break;
835 LeaveCriticalSection(&handler->cs);
837 if (found)
839 IMFAsyncResult_Release(found->result);
840 if (found->object)
841 IUnknown_Release(found->object);
842 heap_free(found);
845 return found ? S_OK : MF_E_UNEXPECTED;
848 static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl =
850 file_scheme_handler_QueryInterface,
851 file_scheme_handler_AddRef,
852 file_scheme_handler_Release,
853 file_scheme_handler_BeginCreateObject,
854 file_scheme_handler_EndCreateObject,
855 file_scheme_handler_CancelObjectCreation,
858 static HRESULT WINAPI file_scheme_handler_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
860 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
861 IsEqualIID(riid, &IID_IUnknown))
863 *obj = iface;
864 IMFAsyncCallback_AddRef(iface);
865 return S_OK;
868 WARN("Unsupported %s.\n", debugstr_guid(riid));
869 *obj = NULL;
870 return E_NOINTERFACE;
873 static ULONG WINAPI file_scheme_handler_callback_AddRef(IMFAsyncCallback *iface)
875 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
876 return IMFSchemeHandler_AddRef(&handler->IMFSchemeHandler_iface);
879 static ULONG WINAPI file_scheme_handler_callback_Release(IMFAsyncCallback *iface)
881 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
882 return IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
885 static HRESULT WINAPI file_scheme_handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
887 return E_NOTIMPL;
890 static HRESULT file_scheme_handler_get_resolver(struct file_scheme_handler *handler, IMFSourceResolver **resolver)
892 HRESULT hr;
894 if (!handler->resolver)
896 IMFSourceResolver *resolver;
898 if (FAILED(hr = MFCreateSourceResolver(&resolver)))
899 return hr;
901 if (InterlockedCompareExchangePointer((void **)&handler->resolver, resolver, NULL))
902 IMFSourceResolver_Release(resolver);
905 *resolver = handler->resolver;
906 IMFSourceResolver_AddRef(*resolver);
908 return S_OK;
911 static HRESULT WINAPI file_scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
913 static const WCHAR schemeW[] = {'f','i','l','e',':','/','/'};
914 struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
915 struct file_scheme_handler_result *handler_result;
916 MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
917 IUnknown *object = NULL, *context_object;
918 struct create_object_context *context;
919 IMFSourceResolver *resolver;
920 IMFAsyncResult *caller;
921 IMFByteStream *stream;
922 const WCHAR *url;
923 HRESULT hr;
925 caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
927 if (FAILED(hr = IMFAsyncResult_GetObject(result, &context_object)))
929 WARN("Expected context set for callee result.\n");
930 return hr;
933 context = impl_from_IUnknown(context_object);
935 /* Strip from scheme, MFCreateFile() won't be expecting it. */
936 url = context->url;
937 if (!wcsnicmp(context->url, schemeW, ARRAY_SIZE(schemeW)))
938 url += ARRAY_SIZE(schemeW);
940 hr = MFCreateFile(context->flags & MF_RESOLUTION_WRITE ? MF_ACCESSMODE_READWRITE : MF_ACCESSMODE_READ,
941 MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, url, &stream);
942 if (SUCCEEDED(hr))
944 if (context->flags & MF_RESOLUTION_MEDIASOURCE)
946 if (SUCCEEDED(hr = file_scheme_handler_get_resolver(handler, &resolver)))
948 hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, context->url, context->flags,
949 context->props, &obj_type, &object);
950 IMFSourceResolver_Release(resolver);
951 IMFByteStream_Release(stream);
954 else
956 object = (IUnknown *)stream;
957 obj_type = MF_OBJECT_BYTESTREAM;
961 handler_result = heap_alloc(sizeof(*handler_result));
962 if (handler_result)
964 handler_result->result = caller;
965 IMFAsyncResult_AddRef(handler_result->result);
966 handler_result->obj_type = obj_type;
967 handler_result->object = object;
969 EnterCriticalSection(&handler->cs);
970 list_add_tail(&handler->results, &handler_result->entry);
971 LeaveCriticalSection(&handler->cs);
973 else
975 if (object)
976 IUnknown_Release(object);
977 hr = E_OUTOFMEMORY;
980 IUnknown_Release(&context->IUnknown_iface);
982 IMFAsyncResult_SetStatus(caller, hr);
983 MFInvokeCallback(caller);
985 return S_OK;
988 static const IMFAsyncCallbackVtbl file_scheme_handler_callback_vtbl =
990 file_scheme_handler_callback_QueryInterface,
991 file_scheme_handler_callback_AddRef,
992 file_scheme_handler_callback_Release,
993 file_scheme_handler_callback_GetParameters,
994 file_scheme_handler_callback_Invoke,
997 static HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
999 struct file_scheme_handler *handler;
1000 HRESULT hr;
1002 TRACE("%s, %p.\n", debugstr_guid(riid), obj);
1004 handler = heap_alloc_zero(sizeof(*handler));
1005 if (!handler)
1006 return E_OUTOFMEMORY;
1008 handler->IMFSchemeHandler_iface.lpVtbl = &file_scheme_handler_vtbl;
1009 handler->IMFAsyncCallback_iface.lpVtbl = &file_scheme_handler_callback_vtbl;
1010 handler->refcount = 1;
1011 list_init(&handler->results);
1012 InitializeCriticalSection(&handler->cs);
1014 hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
1015 IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
1017 return hr;
1020 static struct class_factory file_scheme_handler_factory = { { &class_factory_vtbl }, file_scheme_handler_construct };
1022 static const struct class_object
1024 const GUID *clsid;
1025 IClassFactory *factory;
1027 class_objects[] =
1029 { &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface },
1032 /*******************************************************************************
1033 * DllGetClassObject (mf.@)
1035 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **obj)
1037 unsigned int i;
1039 TRACE("%s, %s, %p.\n", debugstr_guid(rclsid), debugstr_guid(riid), obj);
1041 for (i = 0; i < ARRAY_SIZE(class_objects); ++i)
1043 if (IsEqualGUID(class_objects[i].clsid, rclsid))
1044 return IClassFactory_QueryInterface(class_objects[i].factory, riid, obj);
1047 WARN("%s: class not found.\n", debugstr_guid(rclsid));
1048 return CLASS_E_CLASSNOTAVAILABLE;
1051 /******************************************************************
1052 * DllCanUnloadNow (mf.@)
1054 HRESULT WINAPI DllCanUnloadNow(void)
1056 return S_FALSE;
1059 /***********************************************************************
1060 * DllRegisterServer (mf.@)
1062 HRESULT WINAPI DllRegisterServer(void)
1064 return __wine_register_resources( mf_instance );
1067 /***********************************************************************
1068 * DllUnregisterServer (mf.@)
1070 HRESULT WINAPI DllUnregisterServer(void)
1072 return __wine_unregister_resources( mf_instance );
1075 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
1077 switch (reason)
1079 case DLL_WINE_PREATTACH:
1080 return FALSE; /* prefer native version */
1081 case DLL_PROCESS_ATTACH:
1082 mf_instance = instance;
1083 DisableThreadLibraryCalls(instance);
1084 break;
1087 return TRUE;
1090 static HRESULT prop_string_vector_append(PROPVARIANT *vector, unsigned int *capacity, BOOL unique, const WCHAR *str)
1092 WCHAR *ptrW;
1093 int len, i;
1095 if (unique)
1097 for (i = 0; i < vector->calpwstr.cElems; ++i)
1099 if (!lstrcmpW(vector->calpwstr.pElems[i], str))
1100 return S_OK;
1104 if (!*capacity || *capacity - 1 < vector->calpwstr.cElems)
1106 unsigned int new_count;
1107 WCHAR **ptr;
1109 new_count = *capacity ? *capacity * 2 : 10;
1110 ptr = CoTaskMemRealloc(vector->calpwstr.pElems, new_count * sizeof(*vector->calpwstr.pElems));
1111 if (!ptr)
1112 return E_OUTOFMEMORY;
1113 vector->calpwstr.pElems = ptr;
1114 *capacity = new_count;
1117 len = lstrlenW(str);
1118 if (!(vector->calpwstr.pElems[vector->calpwstr.cElems] = ptrW = CoTaskMemAlloc((len + 1) * sizeof(WCHAR))))
1119 return E_OUTOFMEMORY;
1121 lstrcpyW(ptrW, str);
1122 vector->calpwstr.cElems++;
1124 return S_OK;
1127 static int __cdecl qsort_string_compare(const void *a, const void *b)
1129 const WCHAR *left = *(const WCHAR **)a, *right = *(const WCHAR **)b;
1130 return lstrcmpW(left, right);
1133 static HRESULT mf_get_handler_strings(const WCHAR *path, WCHAR filter, unsigned int maxlen, PROPVARIANT *dst)
1135 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
1136 unsigned int capacity = 0, count, size;
1137 HRESULT hr = S_OK;
1138 int i, index;
1139 WCHAR *buffW;
1141 buffW = heap_calloc(maxlen, sizeof(*buffW));
1142 if (!buffW)
1143 return E_OUTOFMEMORY;
1145 memset(dst, 0, sizeof(*dst));
1146 dst->vt = VT_VECTOR | VT_LPWSTR;
1148 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
1150 HKEY hkey;
1152 if (RegOpenKeyW(hkey_roots[i], path, &hkey))
1153 continue;
1155 index = 0;
1156 size = maxlen;
1157 count = dst->calpwstr.cElems;
1158 while (!RegEnumKeyExW(hkey, index++, buffW, &size, NULL, NULL, NULL, NULL))
1160 if (filter && !wcschr(buffW, filter))
1161 continue;
1163 if (FAILED(hr = prop_string_vector_append(dst, &capacity, i > 0, buffW)))
1164 break;
1165 size = maxlen;
1168 /* Sort last pass results. */
1169 qsort(&dst->calpwstr.pElems[count], dst->calpwstr.cElems - count, sizeof(*dst->calpwstr.pElems),
1170 qsort_string_compare);
1172 RegCloseKey(hkey);
1175 if (FAILED(hr))
1176 PropVariantClear(dst);
1178 heap_free(buffW);
1180 return hr;
1183 /***********************************************************************
1184 * MFGetSupportedMimeTypes (mf.@)
1186 HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *dst)
1188 unsigned int maxlen;
1190 TRACE("%p.\n", dst);
1192 if (!dst)
1193 return E_POINTER;
1195 /* According to RFC4288 it's 127/127 characters. */
1196 maxlen = 127 /* type */ + 1 /* / */ + 127 /* subtype */ + 1;
1197 return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", '/',
1198 maxlen, dst);
1201 /***********************************************************************
1202 * MFGetSupportedSchemes (mf.@)
1204 HRESULT WINAPI MFGetSupportedSchemes(PROPVARIANT *dst)
1206 TRACE("%p.\n", dst);
1208 if (!dst)
1209 return E_POINTER;
1211 return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", 0, 64, dst);
1214 /***********************************************************************
1215 * MFGetService (mf.@)
1217 HRESULT WINAPI MFGetService(IUnknown *object, REFGUID service, REFIID riid, void **obj)
1219 IMFGetService *gs;
1220 HRESULT hr;
1222 TRACE("(%p, %s, %s, %p)\n", object, debugstr_guid(service), debugstr_guid(riid), obj);
1224 if (!object)
1225 return E_POINTER;
1227 if (FAILED(hr = IUnknown_QueryInterface(object, &IID_IMFGetService, (void **)&gs)))
1228 return hr;
1230 hr = IMFGetService_GetService(gs, service, riid, obj);
1231 IMFGetService_Release(gs);
1232 return hr;
1235 /***********************************************************************
1236 * MFShutdownObject (mf.@)
1238 HRESULT WINAPI MFShutdownObject(IUnknown *object)
1240 IMFShutdown *shutdown;
1242 TRACE("%p.\n", object);
1244 if (object && SUCCEEDED(IUnknown_QueryInterface(object, &IID_IMFShutdown, (void **)&shutdown)))
1246 IMFShutdown_Shutdown(shutdown);
1247 IMFShutdown_Release(shutdown);
1250 return S_OK;
1253 /***********************************************************************
1254 * MFEnumDeviceSources (mf.@)
1256 HRESULT WINAPI MFEnumDeviceSources(IMFAttributes *attributes, IMFActivate ***sources, UINT32 *count)
1258 FIXME("%p, %p, %p.\n", attributes, sources, count);
1260 if (!attributes || !sources || !count)
1261 return E_INVALIDARG;
1263 *count = 0;
1265 return S_OK;
1268 struct simple_type_handler
1270 IMFMediaTypeHandler IMFMediaTypeHandler_iface;
1271 LONG refcount;
1272 IMFMediaType *media_type;
1273 CRITICAL_SECTION cs;
1276 static struct simple_type_handler *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface)
1278 return CONTAINING_RECORD(iface, struct simple_type_handler, IMFMediaTypeHandler_iface);
1281 static HRESULT WINAPI simple_type_handler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid, void **obj)
1283 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1285 if (IsEqualIID(riid, &IID_IMFMediaTypeHandler) ||
1286 IsEqualIID(riid, &IID_IUnknown))
1288 *obj = iface;
1289 IMFMediaTypeHandler_AddRef(iface);
1290 return S_OK;
1293 *obj = NULL;
1294 return E_NOINTERFACE;
1297 static ULONG WINAPI simple_type_handler_AddRef(IMFMediaTypeHandler *iface)
1299 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1300 ULONG refcount = InterlockedIncrement(&handler->refcount);
1302 TRACE("%p, refcount %u.\n", iface, refcount);
1304 return refcount;
1307 static ULONG WINAPI simple_type_handler_Release(IMFMediaTypeHandler *iface)
1309 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1310 ULONG refcount = InterlockedDecrement(&handler->refcount);
1312 TRACE("%p, refcount %u.\n", iface, refcount);
1314 if (!refcount)
1316 if (handler->media_type)
1317 IMFMediaType_Release(handler->media_type);
1318 DeleteCriticalSection(&handler->cs);
1319 heap_free(handler);
1322 return refcount;
1325 static HRESULT WINAPI simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type,
1326 IMFMediaType **out_type)
1328 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1329 DWORD flags = 0;
1330 HRESULT hr;
1332 TRACE("%p, %p, %p.\n", iface, in_type, out_type);
1334 if (out_type)
1335 *out_type = NULL;
1337 EnterCriticalSection(&handler->cs);
1338 if (!handler->media_type)
1339 hr = MF_E_UNEXPECTED;
1340 else
1342 if (SUCCEEDED(hr = IMFMediaType_IsEqual(handler->media_type, in_type, &flags)))
1343 hr = (flags & (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES)) ==
1344 (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES) ? S_OK : E_FAIL;
1346 LeaveCriticalSection(&handler->cs);
1348 return hr;
1351 static HRESULT WINAPI simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
1353 TRACE("%p, %p.\n", iface, count);
1355 if (!count)
1356 return E_POINTER;
1358 *count = 1;
1360 return S_OK;
1363 static HRESULT WINAPI simple_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
1364 IMFMediaType **type)
1366 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1368 TRACE("%p, %u, %p.\n", iface, index, type);
1370 if (index > 0)
1371 return MF_E_NO_MORE_TYPES;
1373 EnterCriticalSection(&handler->cs);
1374 *type = handler->media_type;
1375 if (*type)
1376 IMFMediaType_AddRef(*type);
1377 LeaveCriticalSection(&handler->cs);
1379 return S_OK;
1382 static HRESULT WINAPI simple_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *media_type)
1384 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1386 TRACE("%p, %p.\n", iface, media_type);
1388 EnterCriticalSection(&handler->cs);
1389 if (handler->media_type)
1390 IMFMediaType_Release(handler->media_type);
1391 handler->media_type = media_type;
1392 if (handler->media_type)
1393 IMFMediaType_AddRef(handler->media_type);
1394 LeaveCriticalSection(&handler->cs);
1396 return S_OK;
1399 static HRESULT WINAPI simple_type_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **media_type)
1401 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1403 TRACE("%p, %p.\n", iface, media_type);
1405 if (!media_type)
1406 return E_POINTER;
1408 EnterCriticalSection(&handler->cs);
1409 *media_type = handler->media_type;
1410 if (*media_type)
1411 IMFMediaType_AddRef(*media_type);
1412 LeaveCriticalSection(&handler->cs);
1414 return S_OK;
1417 static HRESULT WINAPI simple_type_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
1419 struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface);
1420 HRESULT hr;
1422 TRACE("%p, %p.\n", iface, type);
1424 EnterCriticalSection(&handler->cs);
1425 if (handler->media_type)
1426 hr = IMFMediaType_GetGUID(handler->media_type, &MF_MT_MAJOR_TYPE, type);
1427 else
1428 hr = MF_E_NOT_INITIALIZED;
1429 LeaveCriticalSection(&handler->cs);
1431 return hr;
1434 static const IMFMediaTypeHandlerVtbl simple_type_handler_vtbl =
1436 simple_type_handler_QueryInterface,
1437 simple_type_handler_AddRef,
1438 simple_type_handler_Release,
1439 simple_type_handler_IsMediaTypeSupported,
1440 simple_type_handler_GetMediaTypeCount,
1441 simple_type_handler_GetMediaTypeByIndex,
1442 simple_type_handler_SetCurrentMediaType,
1443 simple_type_handler_GetCurrentMediaType,
1444 simple_type_handler_GetMajorType,
1447 HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler)
1449 struct simple_type_handler *object;
1451 TRACE("%p.\n", handler);
1453 object = heap_alloc_zero(sizeof(*object));
1454 if (!object)
1455 return E_OUTOFMEMORY;
1457 object->IMFMediaTypeHandler_iface.lpVtbl = &simple_type_handler_vtbl;
1458 object->refcount = 1;
1459 InitializeCriticalSection(&object->cs);
1461 *handler = &object->IMFMediaTypeHandler_iface;
1463 return S_OK;
1466 enum sample_copier_flags
1468 SAMPLE_COPIER_INPUT_TYPE_SET = 0x1,
1469 SAMPLE_COPIER_OUTPUT_TYPE_SET = 0x2
1472 struct sample_copier
1474 IMFTransform IMFTransform_iface;
1475 LONG refcount;
1477 IMFAttributes *attributes;
1478 IMFMediaType *buffer_type;
1479 DWORD buffer_size;
1480 IMFSample *sample;
1481 DWORD flags;
1482 CRITICAL_SECTION cs;
1485 static struct sample_copier *impl_copier_from_IMFTransform(IMFTransform *iface)
1487 return CONTAINING_RECORD(iface, struct sample_copier, IMFTransform_iface);
1490 static HRESULT WINAPI sample_copier_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
1492 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1494 if (IsEqualIID(riid, &IID_IMFTransform) ||
1495 IsEqualIID(riid, &IID_IUnknown))
1497 *obj = iface;
1498 IMFTransform_AddRef(iface);
1499 return S_OK;
1502 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
1503 *obj = NULL;
1504 return E_NOINTERFACE;
1507 static ULONG WINAPI sample_copier_transform_AddRef(IMFTransform *iface)
1509 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1510 ULONG refcount = InterlockedIncrement(&transform->refcount);
1512 TRACE("%p, refcount %u.\n", iface, refcount);
1514 return refcount;
1517 static ULONG WINAPI sample_copier_transform_Release(IMFTransform *iface)
1519 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1520 ULONG refcount = InterlockedDecrement(&transform->refcount);
1522 TRACE("%p, refcount %u.\n", iface, refcount);
1524 if (!refcount)
1526 if (transform->attributes)
1527 IMFAttributes_Release(transform->attributes);
1528 if (transform->buffer_type)
1529 IMFMediaType_Release(transform->buffer_type);
1530 DeleteCriticalSection(&transform->cs);
1531 heap_free(transform);
1534 return refcount;
1537 static HRESULT WINAPI sample_copier_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
1538 DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
1540 TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
1542 *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
1544 return S_OK;
1547 static HRESULT WINAPI sample_copier_transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
1549 TRACE("%p, %p, %p.\n", iface, inputs, outputs);
1551 *inputs = 1;
1552 *outputs = 1;
1554 return S_OK;
1557 static HRESULT WINAPI sample_copier_transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
1558 DWORD output_size, DWORD *outputs)
1560 TRACE("%p, %u, %p, %u, %p.\n", iface, input_size, inputs, output_size, outputs);
1562 return E_NOTIMPL;
1565 static HRESULT WINAPI sample_copier_transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
1567 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1569 TRACE("%p, %u, %p.\n", iface, id, info);
1571 memset(info, 0, sizeof(*info));
1573 EnterCriticalSection(&transform->cs);
1574 info->cbSize = transform->buffer_size;
1575 LeaveCriticalSection(&transform->cs);
1577 return S_OK;
1580 static HRESULT WINAPI sample_copier_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id,
1581 MFT_OUTPUT_STREAM_INFO *info)
1583 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1585 TRACE("%p, %u, %p.\n", iface, id, info);
1587 memset(info, 0, sizeof(*info));
1589 EnterCriticalSection(&transform->cs);
1590 info->cbSize = transform->buffer_size;
1591 LeaveCriticalSection(&transform->cs);
1593 return S_OK;
1596 static HRESULT WINAPI sample_copier_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
1598 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1600 TRACE("%p, %p.\n", iface, attributes);
1602 *attributes = transform->attributes;
1603 IMFAttributes_AddRef(*attributes);
1605 return S_OK;
1608 static HRESULT WINAPI sample_copier_transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
1609 IMFAttributes **attributes)
1611 TRACE("%p, %u, %p.\n", iface, id, attributes);
1613 return E_NOTIMPL;
1616 static HRESULT WINAPI sample_copier_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
1617 IMFAttributes **attributes)
1619 TRACE("%p, %u, %p.\n", iface, id, attributes);
1621 return E_NOTIMPL;
1624 static HRESULT WINAPI sample_copier_transform_DeleteInputStream(IMFTransform *iface, DWORD id)
1626 TRACE("%p, %u.\n", iface, id);
1628 return E_NOTIMPL;
1631 static HRESULT WINAPI sample_copier_transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
1633 TRACE("%p, %u, %p.\n", iface, streams, ids);
1635 return E_NOTIMPL;
1638 static HRESULT WINAPI sample_copier_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
1639 IMFMediaType **type)
1641 static const GUID *types[] = { &MFMediaType_Video, &MFMediaType_Audio };
1642 HRESULT hr;
1644 TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
1646 if (id)
1647 return MF_E_INVALIDSTREAMNUMBER;
1649 if (index > ARRAY_SIZE(types) - 1)
1650 return MF_E_NO_MORE_TYPES;
1652 if (SUCCEEDED(hr = MFCreateMediaType(type)))
1653 hr = IMFMediaType_SetGUID(*type, &MF_MT_MAJOR_TYPE, types[index]);
1655 return hr;
1658 static HRESULT WINAPI sample_copier_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
1659 IMFMediaType **type)
1661 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1662 IMFMediaType *cloned_type = NULL;
1663 HRESULT hr = S_OK;
1665 TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
1667 EnterCriticalSection(&transform->cs);
1668 if (transform->buffer_type)
1670 if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type)))
1671 hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type);
1673 else if (id)
1674 hr = MF_E_INVALIDSTREAMNUMBER;
1675 else
1676 hr = MF_E_NO_MORE_TYPES;
1677 LeaveCriticalSection(&transform->cs);
1679 if (SUCCEEDED(hr))
1680 *type = cloned_type;
1681 else if (cloned_type)
1682 IMFMediaType_Release(cloned_type);
1684 return hr;
1687 static HRESULT sample_copier_get_buffer_size(IMFMediaType *type, DWORD *size)
1689 GUID major, subtype;
1690 UINT64 frame_size;
1691 HRESULT hr;
1693 *size = 0;
1695 if (FAILED(hr = IMFMediaType_GetMajorType(type, &major)))
1696 return hr;
1698 if (IsEqualGUID(&major, &MFMediaType_Video))
1700 if (SUCCEEDED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
1702 if (SUCCEEDED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
1704 if (FAILED(hr = MFCalculateImageSize(&subtype, (UINT32)(frame_size >> 32), (UINT32)frame_size, size)))
1705 WARN("Failed to get image size for video format %s.\n", debugstr_guid(&subtype));
1709 else if (IsEqualGUID(&major, &MFMediaType_Audio))
1711 FIXME("Audio formats are not handled.\n");
1712 hr = E_NOTIMPL;
1715 return hr;
1718 static HRESULT sample_copier_set_media_type(struct sample_copier *transform, BOOL input, DWORD id, IMFMediaType *type,
1719 DWORD flags)
1721 DWORD buffer_size;
1722 HRESULT hr = S_OK;
1724 if (id)
1725 return MF_E_INVALIDSTREAMNUMBER;
1727 EnterCriticalSection(&transform->cs);
1728 if (type)
1730 hr = sample_copier_get_buffer_size(type, &buffer_size);
1731 if (!(flags & MFT_SET_TYPE_TEST_ONLY) && SUCCEEDED(hr))
1733 if (!transform->buffer_type)
1734 hr = MFCreateMediaType(&transform->buffer_type);
1735 if (SUCCEEDED(hr))
1736 hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)transform->buffer_type);
1737 if (SUCCEEDED(hr))
1738 transform->buffer_size = buffer_size;
1740 if (SUCCEEDED(hr))
1742 if (input)
1744 transform->flags |= SAMPLE_COPIER_INPUT_TYPE_SET;
1745 transform->flags &= ~SAMPLE_COPIER_OUTPUT_TYPE_SET;
1747 else
1748 transform->flags |= SAMPLE_COPIER_OUTPUT_TYPE_SET;
1752 else if (transform->buffer_type)
1754 IMFMediaType_Release(transform->buffer_type);
1755 transform->buffer_type = NULL;
1757 LeaveCriticalSection(&transform->cs);
1759 return hr;
1762 static HRESULT WINAPI sample_copier_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
1764 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1766 TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
1768 return sample_copier_set_media_type(transform, TRUE, id, type, flags);
1771 static HRESULT WINAPI sample_copier_transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
1773 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1775 TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
1777 return sample_copier_set_media_type(transform, FALSE, id, type, flags);
1780 static HRESULT sample_copier_get_current_type(struct sample_copier *transform, DWORD id, DWORD flags,
1781 IMFMediaType **ret)
1783 IMFMediaType *cloned_type = NULL;
1784 HRESULT hr;
1786 if (id)
1787 return MF_E_INVALIDSTREAMNUMBER;
1789 EnterCriticalSection(&transform->cs);
1790 if (transform->flags & flags)
1792 if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type)))
1793 hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type);
1795 else
1796 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1797 LeaveCriticalSection(&transform->cs);
1799 if (SUCCEEDED(hr))
1800 *ret = cloned_type;
1801 else if (cloned_type)
1802 IMFMediaType_Release(cloned_type);
1804 return hr;
1807 static HRESULT WINAPI sample_copier_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
1809 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1811 TRACE("%p, %u, %p.\n", iface, id, type);
1813 return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_INPUT_TYPE_SET, type);
1816 static HRESULT WINAPI sample_copier_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
1818 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1820 TRACE("%p, %u, %p.\n", iface, id, type);
1822 return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_OUTPUT_TYPE_SET, type);
1825 static HRESULT WINAPI sample_copier_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
1827 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1828 HRESULT hr = S_OK;
1830 TRACE("%p, %u, %p.\n", iface, id, flags);
1832 if (id)
1833 return MF_E_INVALIDSTREAMNUMBER;
1835 EnterCriticalSection(&transform->cs);
1836 if (!(transform->flags & SAMPLE_COPIER_INPUT_TYPE_SET))
1837 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1838 else
1839 *flags = transform->sample ? 0 : MFT_INPUT_STATUS_ACCEPT_DATA;
1840 LeaveCriticalSection(&transform->cs);
1842 return hr;
1845 static HRESULT WINAPI sample_copier_transform_GetOutputStatus(IMFTransform *iface, DWORD *flags)
1847 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1848 HRESULT hr = S_OK;
1850 TRACE("%p, %p.\n", iface, flags);
1852 EnterCriticalSection(&transform->cs);
1853 if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET))
1854 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1855 else
1856 *flags = transform->sample ? MFT_OUTPUT_STATUS_SAMPLE_READY : 0;
1857 LeaveCriticalSection(&transform->cs);
1859 return hr;
1862 static HRESULT WINAPI sample_copier_transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
1864 TRACE("%p, %s, %s.\n", iface, debugstr_time(lower), debugstr_time(upper));
1866 return E_NOTIMPL;
1869 static HRESULT WINAPI sample_copier_transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
1871 FIXME("%p, %u, %p.\n", iface, id, event);
1873 return E_NOTIMPL;
1876 static HRESULT WINAPI sample_copier_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
1878 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1880 TRACE("%p, %#x, %p.\n", iface, message, (void *)param);
1882 EnterCriticalSection(&transform->cs);
1884 if (message == MFT_MESSAGE_COMMAND_FLUSH)
1886 if (transform->sample)
1888 IMFSample_Release(transform->sample);
1889 transform->sample = NULL;
1893 LeaveCriticalSection(&transform->cs);
1895 return S_OK;
1898 static HRESULT WINAPI sample_copier_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
1900 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1901 HRESULT hr = S_OK;
1903 TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags);
1905 if (id)
1906 return MF_E_INVALIDSTREAMNUMBER;
1908 EnterCriticalSection(&transform->cs);
1909 if (!transform->buffer_type)
1910 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1911 else if (transform->sample)
1912 hr = MF_E_NOTACCEPTING;
1913 else
1915 transform->sample = sample;
1916 IMFSample_AddRef(transform->sample);
1918 LeaveCriticalSection(&transform->cs);
1920 return hr;
1923 static HRESULT WINAPI sample_copier_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
1924 MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
1926 struct sample_copier *transform = impl_copier_from_IMFTransform(iface);
1927 IMFMediaBuffer *buffer;
1928 DWORD sample_flags;
1929 HRESULT hr = S_OK;
1930 LONGLONG time;
1932 TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, buffers, status);
1934 EnterCriticalSection(&transform->cs);
1935 if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET))
1936 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1937 else if (!transform->sample)
1938 hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
1939 else
1941 IMFSample_CopyAllItems(transform->sample, (IMFAttributes *)buffers->pSample);
1943 if (SUCCEEDED(IMFSample_GetSampleDuration(transform->sample, &time)))
1944 IMFSample_SetSampleDuration(buffers->pSample, time);
1946 if (SUCCEEDED(IMFSample_GetSampleTime(transform->sample, &time)))
1947 IMFSample_SetSampleTime(buffers->pSample, time);
1949 if (SUCCEEDED(IMFSample_GetSampleFlags(transform->sample, &sample_flags)))
1950 IMFSample_SetSampleFlags(buffers->pSample, sample_flags);
1952 if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(transform->sample, NULL)))
1954 if (SUCCEEDED(IMFSample_GetBufferByIndex(buffers->pSample, 0, &buffer)))
1956 if (FAILED(IMFSample_CopyToBuffer(transform->sample, buffer)))
1957 hr = MF_E_UNEXPECTED;
1958 IMFMediaBuffer_Release(buffer);
1962 IMFSample_Release(transform->sample);
1963 transform->sample = NULL;
1965 LeaveCriticalSection(&transform->cs);
1967 return hr;
1970 static const IMFTransformVtbl sample_copier_transform_vtbl =
1972 sample_copier_transform_QueryInterface,
1973 sample_copier_transform_AddRef,
1974 sample_copier_transform_Release,
1975 sample_copier_transform_GetStreamLimits,
1976 sample_copier_transform_GetStreamCount,
1977 sample_copier_transform_GetStreamIDs,
1978 sample_copier_transform_GetInputStreamInfo,
1979 sample_copier_transform_GetOutputStreamInfo,
1980 sample_copier_transform_GetAttributes,
1981 sample_copier_transform_GetInputStreamAttributes,
1982 sample_copier_transform_GetOutputStreamAttributes,
1983 sample_copier_transform_DeleteInputStream,
1984 sample_copier_transform_AddInputStreams,
1985 sample_copier_transform_GetInputAvailableType,
1986 sample_copier_transform_GetOutputAvailableType,
1987 sample_copier_transform_SetInputType,
1988 sample_copier_transform_SetOutputType,
1989 sample_copier_transform_GetInputCurrentType,
1990 sample_copier_transform_GetOutputCurrentType,
1991 sample_copier_transform_GetInputStatus,
1992 sample_copier_transform_GetOutputStatus,
1993 sample_copier_transform_SetOutputBounds,
1994 sample_copier_transform_ProcessEvent,
1995 sample_copier_transform_ProcessMessage,
1996 sample_copier_transform_ProcessInput,
1997 sample_copier_transform_ProcessOutput,
2000 HRESULT WINAPI MFCreateSampleCopierMFT(IMFTransform **transform)
2002 struct sample_copier *object;
2003 HRESULT hr;
2005 TRACE("%p.\n", transform);
2007 object = heap_alloc_zero(sizeof(*object));
2008 if (!object)
2009 return E_OUTOFMEMORY;
2011 object->IMFTransform_iface.lpVtbl = &sample_copier_transform_vtbl;
2012 object->refcount = 1;
2013 InitializeCriticalSection(&object->cs);
2015 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
2016 goto failed;
2018 IMFAttributes_SetUINT32(object->attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, 1);
2020 *transform = &object->IMFTransform_iface;
2022 return S_OK;
2024 failed:
2026 IMFTransform_Release(&object->IMFTransform_iface);
2028 return hr;