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
37 #include "mf_private.h"
39 #include "wine/debug.h"
40 #include "wine/heap.h"
41 #include "wine/list.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
45 static HINSTANCE mf_instance
;
47 struct activate_object
49 IMFActivate IMFActivate_iface
;
51 IMFAttributes
*attributes
;
53 const struct activate_funcs
*funcs
;
57 static struct activate_object
*impl_from_IMFActivate(IMFActivate
*iface
)
59 return CONTAINING_RECORD(iface
, struct activate_object
, IMFActivate_iface
);
62 static HRESULT WINAPI
activate_object_QueryInterface(IMFActivate
*iface
, REFIID riid
, void **obj
)
64 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
66 if (IsEqualIID(riid
, &IID_IMFActivate
) ||
67 IsEqualIID(riid
, &IID_IMFAttributes
) ||
68 IsEqualIID(riid
, &IID_IUnknown
))
71 IMFActivate_AddRef(iface
);
75 WARN("Unsupported %s.\n", debugstr_guid(riid
));
80 static ULONG WINAPI
activate_object_AddRef(IMFActivate
*iface
)
82 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
83 ULONG refcount
= InterlockedIncrement(&activate
->refcount
);
85 TRACE("%p, refcount %u.\n", iface
, refcount
);
90 static ULONG WINAPI
activate_object_Release(IMFActivate
*iface
)
92 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
93 ULONG refcount
= InterlockedDecrement(&activate
->refcount
);
95 TRACE("%p, refcount %u.\n", iface
, refcount
);
99 activate
->funcs
->free_private(activate
->context
);
100 if (activate
->object
)
101 IUnknown_Release(activate
->object
);
102 IMFAttributes_Release(activate
->attributes
);
109 static HRESULT WINAPI
activate_object_GetItem(IMFActivate
*iface
, REFGUID key
, PROPVARIANT
*value
)
111 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
113 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
115 return IMFAttributes_GetItem(activate
->attributes
, key
, value
);
118 static HRESULT WINAPI
activate_object_GetItemType(IMFActivate
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
120 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
122 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
124 return IMFAttributes_GetItemType(activate
->attributes
, key
, type
);
127 static HRESULT WINAPI
activate_object_CompareItem(IMFActivate
*iface
, REFGUID key
, REFPROPVARIANT value
, BOOL
*result
)
129 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
131 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
133 return IMFAttributes_CompareItem(activate
->attributes
, key
, value
, result
);
136 static HRESULT WINAPI
activate_object_Compare(IMFActivate
*iface
, IMFAttributes
*theirs
, MF_ATTRIBUTES_MATCH_TYPE type
,
139 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
141 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
143 return IMFAttributes_Compare(activate
->attributes
, theirs
, type
, result
);
146 static HRESULT WINAPI
activate_object_GetUINT32(IMFActivate
*iface
, REFGUID key
, UINT32
*value
)
148 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
150 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
152 return IMFAttributes_GetUINT32(activate
->attributes
, key
, value
);
155 static HRESULT WINAPI
activate_object_GetUINT64(IMFActivate
*iface
, REFGUID key
, UINT64
*value
)
157 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
159 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
161 return IMFAttributes_GetUINT64(activate
->attributes
, key
, value
);
164 static HRESULT WINAPI
activate_object_GetDouble(IMFActivate
*iface
, REFGUID key
, double *value
)
166 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
168 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
170 return IMFAttributes_GetDouble(activate
->attributes
, key
, value
);
173 static HRESULT WINAPI
activate_object_GetGUID(IMFActivate
*iface
, REFGUID key
, GUID
*value
)
175 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
177 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
179 return IMFAttributes_GetGUID(activate
->attributes
, key
, value
);
182 static HRESULT WINAPI
activate_object_GetStringLength(IMFActivate
*iface
, REFGUID key
, UINT32
*length
)
184 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
186 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
188 return IMFAttributes_GetStringLength(activate
->attributes
, key
, length
);
191 static HRESULT WINAPI
activate_object_GetString(IMFActivate
*iface
, REFGUID key
, WCHAR
*value
,
192 UINT32 size
, UINT32
*length
)
194 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
196 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
198 return IMFAttributes_GetString(activate
->attributes
, key
, value
, size
, length
);
201 static HRESULT WINAPI
activate_object_GetAllocatedString(IMFActivate
*iface
, REFGUID key
,
202 WCHAR
**value
, UINT32
*length
)
204 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
206 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
208 return IMFAttributes_GetAllocatedString(activate
->attributes
, key
, value
, length
);
211 static HRESULT WINAPI
activate_object_GetBlobSize(IMFActivate
*iface
, REFGUID key
, UINT32
*size
)
213 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
215 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
217 return IMFAttributes_GetBlobSize(activate
->attributes
, key
, size
);
220 static HRESULT WINAPI
activate_object_GetBlob(IMFActivate
*iface
, REFGUID key
, UINT8
*buf
,
221 UINT32 bufsize
, UINT32
*blobsize
)
223 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
225 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
227 return IMFAttributes_GetBlob(activate
->attributes
, key
, buf
, bufsize
, blobsize
);
230 static HRESULT WINAPI
activate_object_GetAllocatedBlob(IMFActivate
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
232 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
234 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
236 return IMFAttributes_GetAllocatedBlob(activate
->attributes
, key
, buf
, size
);
239 static HRESULT WINAPI
activate_object_GetUnknown(IMFActivate
*iface
, REFGUID key
, REFIID riid
, void **ppv
)
241 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
243 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), ppv
);
245 return IMFAttributes_GetUnknown(activate
->attributes
, key
, riid
, ppv
);
248 static HRESULT WINAPI
activate_object_SetItem(IMFActivate
*iface
, REFGUID key
, REFPROPVARIANT value
)
250 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
252 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
254 return IMFAttributes_SetItem(activate
->attributes
, key
, value
);
257 static HRESULT WINAPI
activate_object_DeleteItem(IMFActivate
*iface
, REFGUID key
)
259 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
261 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
263 return IMFAttributes_DeleteItem(activate
->attributes
, key
);
266 static HRESULT WINAPI
activate_object_DeleteAllItems(IMFActivate
*iface
)
268 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
270 TRACE("%p.\n", iface
);
272 return IMFAttributes_DeleteAllItems(activate
->attributes
);
275 static HRESULT WINAPI
activate_object_SetUINT32(IMFActivate
*iface
, REFGUID key
, UINT32 value
)
277 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
279 TRACE("%p, %s, %d.\n", iface
, debugstr_guid(key
), value
);
281 return IMFAttributes_SetUINT32(activate
->attributes
, key
, value
);
284 static HRESULT WINAPI
activate_object_SetUINT64(IMFActivate
*iface
, REFGUID key
, UINT64 value
)
286 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
288 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
290 return IMFAttributes_SetUINT64(activate
->attributes
, key
, value
);
293 static HRESULT WINAPI
activate_object_SetDouble(IMFActivate
*iface
, REFGUID key
, double value
)
295 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
297 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
299 return IMFAttributes_SetDouble(activate
->attributes
, key
, value
);
302 static HRESULT WINAPI
activate_object_SetGUID(IMFActivate
*iface
, REFGUID key
, REFGUID value
)
304 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
306 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
308 return IMFAttributes_SetGUID(activate
->attributes
, key
, value
);
311 static HRESULT WINAPI
activate_object_SetString(IMFActivate
*iface
, REFGUID key
, const WCHAR
*value
)
313 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
315 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
317 return IMFAttributes_SetString(activate
->attributes
, key
, value
);
320 static HRESULT WINAPI
activate_object_SetBlob(IMFActivate
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
322 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
324 TRACE("%p, %s, %p, %d.\n", iface
, debugstr_guid(key
), buf
, size
);
326 return IMFAttributes_SetBlob(activate
->attributes
, key
, buf
, size
);
329 static HRESULT WINAPI
activate_object_SetUnknown(IMFActivate
*iface
, REFGUID key
, IUnknown
*unknown
)
331 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
333 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(key
), unknown
);
335 return IMFAttributes_SetUnknown(activate
->attributes
, key
, unknown
);
338 static HRESULT WINAPI
activate_object_LockStore(IMFActivate
*iface
)
340 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
342 TRACE("%p.\n", iface
);
344 return IMFAttributes_LockStore(activate
->attributes
);
347 static HRESULT WINAPI
activate_object_UnlockStore(IMFActivate
*iface
)
349 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
351 TRACE("%p.\n", iface
);
353 return IMFAttributes_UnlockStore(activate
->attributes
);
356 static HRESULT WINAPI
activate_object_GetCount(IMFActivate
*iface
, UINT32
*count
)
358 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
360 TRACE("%p, %p.\n", iface
, count
);
362 return IMFAttributes_GetCount(activate
->attributes
, count
);
365 static HRESULT WINAPI
activate_object_GetItemByIndex(IMFActivate
*iface
, UINT32 index
, GUID
*key
, PROPVARIANT
*value
)
367 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
369 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
371 return IMFAttributes_GetItemByIndex(activate
->attributes
, index
, key
, value
);
374 static HRESULT WINAPI
activate_object_CopyAllItems(IMFActivate
*iface
, IMFAttributes
*dest
)
376 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
378 TRACE("%p, %p.\n", iface
, dest
);
380 return IMFAttributes_CopyAllItems(activate
->attributes
, dest
);
383 static HRESULT WINAPI
activate_object_ActivateObject(IMFActivate
*iface
, REFIID riid
, void **obj
)
385 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
389 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
391 if (!activate
->object
)
393 if (FAILED(hr
= activate
->funcs
->create_object((IMFAttributes
*)iface
, activate
->context
, &object
)))
396 if (InterlockedCompareExchangePointer((void **)&activate
->object
, object
, NULL
))
397 IUnknown_Release(object
);
400 return IUnknown_QueryInterface(activate
->object
, riid
, obj
);
403 static HRESULT WINAPI
activate_object_ShutdownObject(IMFActivate
*iface
)
405 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
408 TRACE("%p.\n", iface
);
410 if ((object
= InterlockedCompareExchangePointer((void **)&activate
->object
, NULL
, activate
->object
)))
412 activate
->funcs
->shutdown_object(activate
->context
, object
);
413 IUnknown_Release(object
);
419 static HRESULT WINAPI
activate_object_DetachObject(IMFActivate
*iface
)
421 TRACE("%p.\n", iface
);
426 static const IMFActivateVtbl activate_object_vtbl
=
428 activate_object_QueryInterface
,
429 activate_object_AddRef
,
430 activate_object_Release
,
431 activate_object_GetItem
,
432 activate_object_GetItemType
,
433 activate_object_CompareItem
,
434 activate_object_Compare
,
435 activate_object_GetUINT32
,
436 activate_object_GetUINT64
,
437 activate_object_GetDouble
,
438 activate_object_GetGUID
,
439 activate_object_GetStringLength
,
440 activate_object_GetString
,
441 activate_object_GetAllocatedString
,
442 activate_object_GetBlobSize
,
443 activate_object_GetBlob
,
444 activate_object_GetAllocatedBlob
,
445 activate_object_GetUnknown
,
446 activate_object_SetItem
,
447 activate_object_DeleteItem
,
448 activate_object_DeleteAllItems
,
449 activate_object_SetUINT32
,
450 activate_object_SetUINT64
,
451 activate_object_SetDouble
,
452 activate_object_SetGUID
,
453 activate_object_SetString
,
454 activate_object_SetBlob
,
455 activate_object_SetUnknown
,
456 activate_object_LockStore
,
457 activate_object_UnlockStore
,
458 activate_object_GetCount
,
459 activate_object_GetItemByIndex
,
460 activate_object_CopyAllItems
,
461 activate_object_ActivateObject
,
462 activate_object_ShutdownObject
,
463 activate_object_DetachObject
,
466 HRESULT
create_activation_object(void *context
, const struct activate_funcs
*funcs
, IMFActivate
**ret
)
468 struct activate_object
*object
;
471 object
= heap_alloc_zero(sizeof(*object
));
473 return E_OUTOFMEMORY
;
475 object
->IMFActivate_iface
.lpVtbl
= &activate_object_vtbl
;
476 object
->refcount
= 1;
477 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
482 object
->funcs
= funcs
;
483 object
->context
= context
;
485 *ret
= &object
->IMFActivate_iface
;
492 IClassFactory IClassFactory_iface
;
493 HRESULT (*create_instance
)(REFIID riid
, void **obj
);
496 static inline struct class_factory
*impl_from_IClassFactory(IClassFactory
*iface
)
498 return CONTAINING_RECORD(iface
, struct class_factory
, IClassFactory_iface
);
501 static HRESULT WINAPI
class_factory_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **obj
)
503 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
505 if (IsEqualGUID(riid
, &IID_IClassFactory
) ||
506 IsEqualGUID(riid
, &IID_IUnknown
))
509 IClassFactory_AddRef(iface
);
513 WARN("%s is not supported.\n", debugstr_guid(riid
));
515 return E_NOINTERFACE
;
518 static ULONG WINAPI
class_factory_AddRef(IClassFactory
*iface
)
523 static ULONG WINAPI
class_factory_Release(IClassFactory
*iface
)
528 static HRESULT WINAPI
class_factory_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **obj
)
530 struct class_factory
*factory
= impl_from_IClassFactory(iface
);
532 TRACE("%p, %p, %s, %p.\n", iface
, outer
, debugstr_guid(riid
), obj
);
537 return CLASS_E_NOAGGREGATION
;
540 return factory
->create_instance(riid
, obj
);
543 static HRESULT WINAPI
class_factory_LockServer(IClassFactory
*iface
, BOOL dolock
)
545 FIXME("%d.\n", dolock
);
550 static const IClassFactoryVtbl class_factory_vtbl
=
552 class_factory_QueryInterface
,
553 class_factory_AddRef
,
554 class_factory_Release
,
555 class_factory_CreateInstance
,
556 class_factory_LockServer
,
559 struct file_scheme_handler_result
562 IMFAsyncResult
*result
;
563 MF_OBJECT_TYPE obj_type
;
567 struct file_scheme_handler
569 IMFSchemeHandler IMFSchemeHandler_iface
;
570 IMFAsyncCallback IMFAsyncCallback_iface
;
572 IMFSourceResolver
*resolver
;
577 static struct file_scheme_handler
*impl_from_IMFSchemeHandler(IMFSchemeHandler
*iface
)
579 return CONTAINING_RECORD(iface
, struct file_scheme_handler
, IMFSchemeHandler_iface
);
582 static struct file_scheme_handler
*impl_from_IMFAsyncCallback(IMFAsyncCallback
*iface
)
584 return CONTAINING_RECORD(iface
, struct file_scheme_handler
, IMFAsyncCallback_iface
);
587 static HRESULT WINAPI
file_scheme_handler_QueryInterface(IMFSchemeHandler
*iface
, REFIID riid
, void **obj
)
589 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
591 if (IsEqualIID(riid
, &IID_IMFSchemeHandler
) ||
592 IsEqualIID(riid
, &IID_IUnknown
))
595 IMFSchemeHandler_AddRef(iface
);
599 WARN("Unsupported %s.\n", debugstr_guid(riid
));
601 return E_NOINTERFACE
;
604 static ULONG WINAPI
file_scheme_handler_AddRef(IMFSchemeHandler
*iface
)
606 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
607 ULONG refcount
= InterlockedIncrement(&handler
->refcount
);
609 TRACE("%p, refcount %u.\n", handler
, refcount
);
614 static ULONG WINAPI
file_scheme_handler_Release(IMFSchemeHandler
*iface
)
616 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
617 ULONG refcount
= InterlockedDecrement(&handler
->refcount
);
618 struct file_scheme_handler_result
*result
, *next
;
620 TRACE("%p, refcount %u.\n", iface
, refcount
);
624 LIST_FOR_EACH_ENTRY_SAFE(result
, next
, &handler
->results
, struct file_scheme_handler_result
, entry
)
626 list_remove(&result
->entry
);
627 IMFAsyncResult_Release(result
->result
);
629 IUnknown_Release(result
->object
);
632 DeleteCriticalSection(&handler
->cs
);
633 if (handler
->resolver
)
634 IMFSourceResolver_Release(handler
->resolver
);
641 struct create_object_context
643 IUnknown IUnknown_iface
;
646 IPropertyStore
*props
;
651 static struct create_object_context
*impl_from_IUnknown(IUnknown
*iface
)
653 return CONTAINING_RECORD(iface
, struct create_object_context
, IUnknown_iface
);
656 static HRESULT WINAPI
create_object_context_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
658 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
660 if (IsEqualIID(riid
, &IID_IUnknown
))
663 IUnknown_AddRef(iface
);
667 WARN("Unsupported %s.\n", debugstr_guid(riid
));
669 return E_NOINTERFACE
;
672 static ULONG WINAPI
create_object_context_AddRef(IUnknown
*iface
)
674 struct create_object_context
*context
= impl_from_IUnknown(iface
);
675 ULONG refcount
= InterlockedIncrement(&context
->refcount
);
677 TRACE("%p, refcount %u.\n", iface
, refcount
);
682 static ULONG WINAPI
create_object_context_Release(IUnknown
*iface
)
684 struct create_object_context
*context
= impl_from_IUnknown(iface
);
685 ULONG refcount
= InterlockedDecrement(&context
->refcount
);
687 TRACE("%p, refcount %u.\n", iface
, refcount
);
692 IPropertyStore_Release(context
->props
);
693 heap_free(context
->url
);
700 static const IUnknownVtbl create_object_context_vtbl
=
702 create_object_context_QueryInterface
,
703 create_object_context_AddRef
,
704 create_object_context_Release
,
707 static WCHAR
*heap_strdupW(const WCHAR
*str
)
715 size
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
716 ret
= heap_alloc(size
);
718 memcpy(ret
, str
, size
);
724 static HRESULT WINAPI
file_scheme_handler_BeginCreateObject(IMFSchemeHandler
*iface
, const WCHAR
*url
, DWORD flags
,
725 IPropertyStore
*props
, IUnknown
**cancel_cookie
, IMFAsyncCallback
*callback
, IUnknown
*state
)
727 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
728 struct create_object_context
*context
;
729 IMFAsyncResult
*caller
, *item
;
732 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface
, debugstr_w(url
), flags
, props
, cancel_cookie
, callback
, state
);
735 *cancel_cookie
= NULL
;
737 if (FAILED(hr
= MFCreateAsyncResult(NULL
, callback
, state
, &caller
)))
740 context
= heap_alloc(sizeof(*context
));
743 IMFAsyncResult_Release(caller
);
744 return E_OUTOFMEMORY
;
747 context
->IUnknown_iface
.lpVtbl
= &create_object_context_vtbl
;
748 context
->refcount
= 1;
749 context
->props
= props
;
751 IPropertyStore_AddRef(context
->props
);
752 context
->flags
= flags
;
753 context
->url
= heap_strdupW(url
);
756 IMFAsyncResult_Release(caller
);
757 IUnknown_Release(&context
->IUnknown_iface
);
758 return E_OUTOFMEMORY
;
761 hr
= MFCreateAsyncResult(&context
->IUnknown_iface
, &handler
->IMFAsyncCallback_iface
, (IUnknown
*)caller
, &item
);
762 IUnknown_Release(&context
->IUnknown_iface
);
763 IMFAsyncResult_Release(caller
);
766 if (SUCCEEDED(hr
= MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO
, item
)))
769 IMFAsyncResult_GetState(item
, cancel_cookie
);
772 IMFAsyncResult_Release(item
);
778 static HRESULT WINAPI
file_scheme_handler_EndCreateObject(IMFSchemeHandler
*iface
, IMFAsyncResult
*result
,
779 MF_OBJECT_TYPE
*obj_type
, IUnknown
**object
)
781 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
782 struct file_scheme_handler_result
*found
= NULL
, *cur
;
785 TRACE("%p, %p, %p, %p.\n", iface
, result
, obj_type
, object
);
787 EnterCriticalSection(&handler
->cs
);
789 LIST_FOR_EACH_ENTRY(cur
, &handler
->results
, struct file_scheme_handler_result
, entry
)
791 if (result
== cur
->result
)
793 list_remove(&cur
->entry
);
799 LeaveCriticalSection(&handler
->cs
);
803 *obj_type
= found
->obj_type
;
804 *object
= found
->object
;
805 hr
= IMFAsyncResult_GetStatus(found
->result
);
806 IMFAsyncResult_Release(found
->result
);
811 *obj_type
= MF_OBJECT_INVALID
;
813 hr
= MF_E_UNEXPECTED
;
819 static HRESULT WINAPI
file_scheme_handler_CancelObjectCreation(IMFSchemeHandler
*iface
, IUnknown
*cancel_cookie
)
821 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
822 struct file_scheme_handler_result
*found
= NULL
, *cur
;
824 TRACE("%p, %p.\n", iface
, cancel_cookie
);
826 EnterCriticalSection(&handler
->cs
);
828 LIST_FOR_EACH_ENTRY(cur
, &handler
->results
, struct file_scheme_handler_result
, entry
)
830 if (cancel_cookie
== (IUnknown
*)cur
->result
)
832 list_remove(&cur
->entry
);
838 LeaveCriticalSection(&handler
->cs
);
842 IMFAsyncResult_Release(found
->result
);
844 IUnknown_Release(found
->object
);
848 return found
? S_OK
: MF_E_UNEXPECTED
;
851 static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl
=
853 file_scheme_handler_QueryInterface
,
854 file_scheme_handler_AddRef
,
855 file_scheme_handler_Release
,
856 file_scheme_handler_BeginCreateObject
,
857 file_scheme_handler_EndCreateObject
,
858 file_scheme_handler_CancelObjectCreation
,
861 static HRESULT WINAPI
file_scheme_handler_callback_QueryInterface(IMFAsyncCallback
*iface
, REFIID riid
, void **obj
)
863 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
864 IsEqualIID(riid
, &IID_IUnknown
))
867 IMFAsyncCallback_AddRef(iface
);
871 WARN("Unsupported %s.\n", debugstr_guid(riid
));
873 return E_NOINTERFACE
;
876 static ULONG WINAPI
file_scheme_handler_callback_AddRef(IMFAsyncCallback
*iface
)
878 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
879 return IMFSchemeHandler_AddRef(&handler
->IMFSchemeHandler_iface
);
882 static ULONG WINAPI
file_scheme_handler_callback_Release(IMFAsyncCallback
*iface
)
884 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
885 return IMFSchemeHandler_Release(&handler
->IMFSchemeHandler_iface
);
888 static HRESULT WINAPI
file_scheme_handler_callback_GetParameters(IMFAsyncCallback
*iface
, DWORD
*flags
, DWORD
*queue
)
893 static HRESULT
file_scheme_handler_get_resolver(struct file_scheme_handler
*handler
, IMFSourceResolver
**resolver
)
897 if (!handler
->resolver
)
899 IMFSourceResolver
*resolver
;
901 if (FAILED(hr
= MFCreateSourceResolver(&resolver
)))
904 if (InterlockedCompareExchangePointer((void **)&handler
->resolver
, resolver
, NULL
))
905 IMFSourceResolver_Release(resolver
);
908 *resolver
= handler
->resolver
;
909 IMFSourceResolver_AddRef(*resolver
);
914 static HRESULT WINAPI
file_scheme_handler_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
916 static const WCHAR schemeW
[] = {'f','i','l','e',':','/','/'};
917 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
918 struct file_scheme_handler_result
*handler_result
;
919 MF_OBJECT_TYPE obj_type
= MF_OBJECT_INVALID
;
920 IUnknown
*object
= NULL
, *context_object
;
921 struct create_object_context
*context
;
922 IMFSourceResolver
*resolver
;
923 IMFAsyncResult
*caller
;
924 IMFByteStream
*stream
;
928 caller
= (IMFAsyncResult
*)IMFAsyncResult_GetStateNoAddRef(result
);
930 if (FAILED(hr
= IMFAsyncResult_GetObject(result
, &context_object
)))
932 WARN("Expected context set for callee result.\n");
936 context
= impl_from_IUnknown(context_object
);
938 /* Strip from scheme, MFCreateFile() won't be expecting it. */
940 if (!wcsnicmp(context
->url
, schemeW
, ARRAY_SIZE(schemeW
)))
941 url
+= ARRAY_SIZE(schemeW
);
943 hr
= MFCreateFile(context
->flags
& MF_RESOLUTION_WRITE
? MF_ACCESSMODE_READWRITE
: MF_ACCESSMODE_READ
,
944 MF_OPENMODE_FAIL_IF_NOT_EXIST
, MF_FILEFLAGS_NONE
, url
, &stream
);
947 if (context
->flags
& MF_RESOLUTION_MEDIASOURCE
)
949 if (SUCCEEDED(hr
= file_scheme_handler_get_resolver(handler
, &resolver
)))
951 hr
= IMFSourceResolver_CreateObjectFromByteStream(resolver
, stream
, context
->url
, context
->flags
,
952 context
->props
, &obj_type
, &object
);
953 IMFSourceResolver_Release(resolver
);
954 IMFByteStream_Release(stream
);
959 object
= (IUnknown
*)stream
;
960 obj_type
= MF_OBJECT_BYTESTREAM
;
964 handler_result
= heap_alloc(sizeof(*handler_result
));
967 handler_result
->result
= caller
;
968 IMFAsyncResult_AddRef(handler_result
->result
);
969 handler_result
->obj_type
= obj_type
;
970 handler_result
->object
= object
;
972 EnterCriticalSection(&handler
->cs
);
973 list_add_tail(&handler
->results
, &handler_result
->entry
);
974 LeaveCriticalSection(&handler
->cs
);
979 IUnknown_Release(object
);
983 IUnknown_Release(&context
->IUnknown_iface
);
985 IMFAsyncResult_SetStatus(caller
, hr
);
986 MFInvokeCallback(caller
);
991 static const IMFAsyncCallbackVtbl file_scheme_handler_callback_vtbl
=
993 file_scheme_handler_callback_QueryInterface
,
994 file_scheme_handler_callback_AddRef
,
995 file_scheme_handler_callback_Release
,
996 file_scheme_handler_callback_GetParameters
,
997 file_scheme_handler_callback_Invoke
,
1000 static HRESULT
file_scheme_handler_construct(REFIID riid
, void **obj
)
1002 struct file_scheme_handler
*handler
;
1005 TRACE("%s, %p.\n", debugstr_guid(riid
), obj
);
1007 handler
= heap_alloc_zero(sizeof(*handler
));
1009 return E_OUTOFMEMORY
;
1011 handler
->IMFSchemeHandler_iface
.lpVtbl
= &file_scheme_handler_vtbl
;
1012 handler
->IMFAsyncCallback_iface
.lpVtbl
= &file_scheme_handler_callback_vtbl
;
1013 handler
->refcount
= 1;
1014 list_init(&handler
->results
);
1015 InitializeCriticalSection(&handler
->cs
);
1017 hr
= IMFSchemeHandler_QueryInterface(&handler
->IMFSchemeHandler_iface
, riid
, obj
);
1018 IMFSchemeHandler_Release(&handler
->IMFSchemeHandler_iface
);
1023 static struct class_factory file_scheme_handler_factory
= { { &class_factory_vtbl
}, file_scheme_handler_construct
};
1025 static const struct class_object
1028 IClassFactory
*factory
;
1032 { &CLSID_FileSchemeHandler
, &file_scheme_handler_factory
.IClassFactory_iface
},
1035 /*******************************************************************************
1036 * DllGetClassObject (mf.@)
1038 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **obj
)
1042 TRACE("%s, %s, %p.\n", debugstr_guid(rclsid
), debugstr_guid(riid
), obj
);
1044 for (i
= 0; i
< ARRAY_SIZE(class_objects
); ++i
)
1046 if (IsEqualGUID(class_objects
[i
].clsid
, rclsid
))
1047 return IClassFactory_QueryInterface(class_objects
[i
].factory
, riid
, obj
);
1050 WARN("%s: class not found.\n", debugstr_guid(rclsid
));
1051 return CLASS_E_CLASSNOTAVAILABLE
;
1054 /******************************************************************
1055 * DllCanUnloadNow (mf.@)
1057 HRESULT WINAPI
DllCanUnloadNow(void)
1062 /***********************************************************************
1063 * DllRegisterServer (mf.@)
1065 HRESULT WINAPI
DllRegisterServer(void)
1067 return __wine_register_resources( mf_instance
);
1070 /***********************************************************************
1071 * DllUnregisterServer (mf.@)
1073 HRESULT WINAPI
DllUnregisterServer(void)
1075 return __wine_unregister_resources( mf_instance
);
1078 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, LPVOID reserved
)
1082 case DLL_WINE_PREATTACH
:
1083 return FALSE
; /* prefer native version */
1084 case DLL_PROCESS_ATTACH
:
1085 mf_instance
= instance
;
1086 DisableThreadLibraryCalls(instance
);
1093 static HRESULT
prop_string_vector_append(PROPVARIANT
*vector
, unsigned int *count
, BOOL unique
, const WCHAR
*str
)
1100 for (i
= 0; i
< vector
->calpwstr
.cElems
; ++i
)
1102 if (!lstrcmpW(vector
->calpwstr
.pElems
[i
], str
))
1107 if (!vector
->calpwstr
.cElems
|| *count
> vector
->calpwstr
.cElems
- 1)
1109 unsigned int new_count
;
1112 new_count
= *count
? *count
* 2 : 10;
1113 ptr
= CoTaskMemRealloc(vector
->calpwstr
.pElems
, new_count
* sizeof(*vector
->calpwstr
.pElems
));
1115 return E_OUTOFMEMORY
;
1116 vector
->calpwstr
.pElems
= ptr
;
1120 len
= lstrlenW(str
);
1121 if (!(vector
->calpwstr
.pElems
[vector
->calpwstr
.cElems
] = ptrW
= CoTaskMemAlloc((len
+ 1) * sizeof(WCHAR
))))
1122 return E_OUTOFMEMORY
;
1124 lstrcpyW(ptrW
, str
);
1125 vector
->calpwstr
.cElems
++;
1130 static int __cdecl
qsort_string_compare(const void *a
, const void *b
)
1132 return lstrcmpW(a
, b
);
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
};
1142 buffW
= heap_calloc(maxlen
, sizeof(*buffW
));
1144 return E_OUTOFMEMORY
;
1146 memset(dst
, 0, sizeof(*dst
));
1147 dst
->vt
= VT_VECTOR
| VT_LPWSTR
;
1149 for (i
= 0; i
< ARRAY_SIZE(hkey_roots
); ++i
)
1155 if (RegOpenKeyW(hkey_roots
[i
], path
, &hkey
))
1160 count
= dst
->calpwstr
.cElems
;
1161 while (!RegEnumKeyExW(hkey
, index
++, buffW
, &size
, NULL
, NULL
, NULL
, NULL
))
1163 if (filter
&& !wcschr(buffW
, filter
))
1165 if (FAILED(hr
= prop_string_vector_append(dst
, &count
, i
> 0, buffW
)))
1170 /* Sort last pass results. */
1171 qsort(&dst
->calpwstr
.pElems
[count
], dst
->calpwstr
.cElems
- count
, sizeof(*dst
->calpwstr
.pElems
),
1172 qsort_string_compare
);
1178 PropVariantClear(dst
);
1185 /***********************************************************************
1186 * MFGetSupportedMimeTypes (mf.@)
1188 HRESULT WINAPI
MFGetSupportedMimeTypes(PROPVARIANT
*dst
)
1190 unsigned int maxlen
;
1192 TRACE("%p.\n", dst
);
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", '/',
1203 /***********************************************************************
1204 * MFGetSupportedSchemes (mf.@)
1206 HRESULT WINAPI
MFGetSupportedSchemes(PROPVARIANT
*dst
)
1208 TRACE("%p.\n", dst
);
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
)
1224 TRACE("(%p, %s, %s, %p)\n", object
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1229 if (FAILED(hr
= IUnknown_QueryInterface(object
, &IID_IMFGetService
, (void **)&gs
)))
1232 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
1233 IMFGetService_Release(gs
);
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
);
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
;
1270 static HRESULT
evr_create_object(IMFAttributes
*attributes
, void *user_context
, IUnknown
**obj
)
1272 FIXME("%p, %p, %p.\n", attributes
, user_context
, obj
);
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
=
1288 evr_shutdown_object
,
1292 HRESULT WINAPI
MFCreateVideoRendererActivate(HWND hwnd
, IMFActivate
**activate
)
1294 TRACE("%p, %p.\n", hwnd
, activate
);
1299 return create_activation_object(hwnd
, &evr_activate_funcs
, activate
);
1302 struct simple_type_handler
1304 IMFMediaTypeHandler IMFMediaTypeHandler_iface
;
1306 IMFMediaType
*media_type
;
1307 CRITICAL_SECTION cs
;
1310 static struct simple_type_handler
*impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler
*iface
)
1312 return CONTAINING_RECORD(iface
, struct simple_type_handler
, IMFMediaTypeHandler_iface
);
1315 static HRESULT WINAPI
simple_type_handler_QueryInterface(IMFMediaTypeHandler
*iface
, REFIID riid
, void **obj
)
1317 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1319 if (IsEqualIID(riid
, &IID_IMFMediaTypeHandler
) ||
1320 IsEqualIID(riid
, &IID_IUnknown
))
1323 IMFMediaTypeHandler_AddRef(iface
);
1328 return E_NOINTERFACE
;
1331 static ULONG WINAPI
simple_type_handler_AddRef(IMFMediaTypeHandler
*iface
)
1333 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1334 ULONG refcount
= InterlockedIncrement(&handler
->refcount
);
1336 TRACE("%p, refcount %u.\n", iface
, refcount
);
1341 static ULONG WINAPI
simple_type_handler_Release(IMFMediaTypeHandler
*iface
)
1343 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1344 ULONG refcount
= InterlockedDecrement(&handler
->refcount
);
1346 TRACE("%p, refcount %u.\n", iface
, refcount
);
1350 if (handler
->media_type
)
1351 IMFMediaType_Release(handler
->media_type
);
1352 DeleteCriticalSection(&handler
->cs
);
1359 static HRESULT WINAPI
simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler
*iface
, IMFMediaType
*in_type
,
1360 IMFMediaType
**out_type
)
1362 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1366 TRACE("%p, %p, %p.\n", iface
, in_type
, out_type
);
1371 EnterCriticalSection(&handler
->cs
);
1372 if (!handler
->media_type
)
1373 hr
= MF_E_UNEXPECTED
;
1376 if (SUCCEEDED(hr
= IMFMediaType_IsEqual(handler
->media_type
, in_type
, &flags
)))
1377 hr
= (flags
& (MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
)) ==
1378 (MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
) ? S_OK
: E_FAIL
;
1380 LeaveCriticalSection(&handler
->cs
);
1385 static HRESULT WINAPI
simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler
*iface
, DWORD
*count
)
1387 TRACE("%p, %p.\n", iface
, count
);
1397 static HRESULT WINAPI
simple_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler
*iface
, DWORD index
,
1398 IMFMediaType
**type
)
1400 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1402 TRACE("%p, %u, %p.\n", iface
, index
, type
);
1405 return MF_E_NO_MORE_TYPES
;
1407 EnterCriticalSection(&handler
->cs
);
1408 *type
= handler
->media_type
;
1410 IMFMediaType_AddRef(*type
);
1411 LeaveCriticalSection(&handler
->cs
);
1416 static HRESULT WINAPI
simple_type_handler_SetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
*media_type
)
1418 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1420 TRACE("%p, %p.\n", iface
, media_type
);
1422 EnterCriticalSection(&handler
->cs
);
1423 if (handler
->media_type
)
1424 IMFMediaType_Release(handler
->media_type
);
1425 handler
->media_type
= media_type
;
1426 if (handler
->media_type
)
1427 IMFMediaType_AddRef(handler
->media_type
);
1428 LeaveCriticalSection(&handler
->cs
);
1433 static HRESULT WINAPI
simple_type_handler_GetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
**media_type
)
1435 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1437 TRACE("%p, %p.\n", iface
, media_type
);
1442 EnterCriticalSection(&handler
->cs
);
1443 *media_type
= handler
->media_type
;
1445 IMFMediaType_AddRef(*media_type
);
1446 LeaveCriticalSection(&handler
->cs
);
1451 static HRESULT WINAPI
simple_type_handler_GetMajorType(IMFMediaTypeHandler
*iface
, GUID
*type
)
1453 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1456 TRACE("%p, %p.\n", iface
, type
);
1458 EnterCriticalSection(&handler
->cs
);
1459 if (handler
->media_type
)
1460 hr
= IMFMediaType_GetGUID(handler
->media_type
, &MF_MT_MAJOR_TYPE
, type
);
1462 hr
= MF_E_NOT_INITIALIZED
;
1463 LeaveCriticalSection(&handler
->cs
);
1468 static const IMFMediaTypeHandlerVtbl simple_type_handler_vtbl
=
1470 simple_type_handler_QueryInterface
,
1471 simple_type_handler_AddRef
,
1472 simple_type_handler_Release
,
1473 simple_type_handler_IsMediaTypeSupported
,
1474 simple_type_handler_GetMediaTypeCount
,
1475 simple_type_handler_GetMediaTypeByIndex
,
1476 simple_type_handler_SetCurrentMediaType
,
1477 simple_type_handler_GetCurrentMediaType
,
1478 simple_type_handler_GetMajorType
,
1481 HRESULT WINAPI
MFCreateSimpleTypeHandler(IMFMediaTypeHandler
**handler
)
1483 struct simple_type_handler
*object
;
1485 TRACE("%p.\n", handler
);
1487 object
= heap_alloc_zero(sizeof(*object
));
1489 return E_OUTOFMEMORY
;
1491 object
->IMFMediaTypeHandler_iface
.lpVtbl
= &simple_type_handler_vtbl
;
1492 object
->refcount
= 1;
1493 InitializeCriticalSection(&object
->cs
);
1495 *handler
= &object
->IMFMediaTypeHandler_iface
;
1500 enum sample_copier_flags
1502 SAMPLE_COPIER_INPUT_TYPE_SET
= 0x1,
1503 SAMPLE_COPIER_OUTPUT_TYPE_SET
= 0x2
1506 struct sample_copier
1508 IMFTransform IMFTransform_iface
;
1511 IMFAttributes
*attributes
;
1512 IMFMediaType
*buffer_type
;
1516 CRITICAL_SECTION cs
;
1519 static struct sample_copier
*impl_copier_from_IMFTransform(IMFTransform
*iface
)
1521 return CONTAINING_RECORD(iface
, struct sample_copier
, IMFTransform_iface
);
1524 static HRESULT WINAPI
sample_copier_transform_QueryInterface(IMFTransform
*iface
, REFIID riid
, void **obj
)
1526 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1528 if (IsEqualIID(riid
, &IID_IMFTransform
) ||
1529 IsEqualIID(riid
, &IID_IUnknown
))
1532 IMFTransform_AddRef(iface
);
1536 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1538 return E_NOINTERFACE
;
1541 static ULONG WINAPI
sample_copier_transform_AddRef(IMFTransform
*iface
)
1543 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1544 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
1546 TRACE("%p, refcount %u.\n", iface
, refcount
);
1551 static ULONG WINAPI
sample_copier_transform_Release(IMFTransform
*iface
)
1553 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1554 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
1556 TRACE("%p, refcount %u.\n", iface
, refcount
);
1560 IMFAttributes_Release(transform
->attributes
);
1561 if (transform
->buffer_type
)
1562 IMFMediaType_Release(transform
->buffer_type
);
1563 DeleteCriticalSection(&transform
->cs
);
1564 heap_free(transform
);
1570 static HRESULT WINAPI
sample_copier_transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
1571 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
1573 TRACE("%p, %p, %p, %p, %p.\n", iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
1575 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
1580 static HRESULT WINAPI
sample_copier_transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
1582 TRACE("%p, %p, %p.\n", iface
, inputs
, outputs
);
1590 static HRESULT WINAPI
sample_copier_transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
1591 DWORD output_size
, DWORD
*outputs
)
1593 TRACE("%p, %u, %p, %u, %p.\n", iface
, input_size
, inputs
, output_size
, outputs
);
1598 static HRESULT WINAPI
sample_copier_transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
1600 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1602 TRACE("%p, %u, %p.\n", iface
, id
, info
);
1604 memset(info
, 0, sizeof(*info
));
1606 EnterCriticalSection(&transform
->cs
);
1607 info
->cbSize
= transform
->buffer_size
;
1608 LeaveCriticalSection(&transform
->cs
);
1613 static HRESULT WINAPI
sample_copier_transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
,
1614 MFT_OUTPUT_STREAM_INFO
*info
)
1616 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1618 TRACE("%p, %u, %p.\n", iface
, id
, info
);
1620 memset(info
, 0, sizeof(*info
));
1622 EnterCriticalSection(&transform
->cs
);
1623 info
->cbSize
= transform
->buffer_size
;
1624 LeaveCriticalSection(&transform
->cs
);
1629 static HRESULT WINAPI
sample_copier_transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
1631 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1633 TRACE("%p, %p.\n", iface
, attributes
);
1635 *attributes
= transform
->attributes
;
1636 IMFAttributes_AddRef(*attributes
);
1641 static HRESULT WINAPI
sample_copier_transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
,
1642 IMFAttributes
**attributes
)
1644 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
1649 static HRESULT WINAPI
sample_copier_transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
,
1650 IMFAttributes
**attributes
)
1652 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
1657 static HRESULT WINAPI
sample_copier_transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
1659 TRACE("%p, %u.\n", iface
, id
);
1664 static HRESULT WINAPI
sample_copier_transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
1666 TRACE("%p, %u, %p.\n", iface
, streams
, ids
);
1671 static HRESULT WINAPI
sample_copier_transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
1672 IMFMediaType
**type
)
1674 static const GUID
*types
[] = { &MFMediaType_Video
, &MFMediaType_Audio
};
1677 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
1680 return MF_E_INVALIDSTREAMNUMBER
;
1682 if (index
> ARRAY_SIZE(types
) - 1)
1683 return MF_E_NO_MORE_TYPES
;
1685 if (SUCCEEDED(hr
= MFCreateMediaType(type
)))
1686 hr
= IMFMediaType_SetGUID(*type
, &MF_MT_MAJOR_TYPE
, types
[index
]);
1691 static HRESULT WINAPI
sample_copier_transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
1692 IMFMediaType
**type
)
1694 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1695 IMFMediaType
*cloned_type
= NULL
;
1698 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
1700 EnterCriticalSection(&transform
->cs
);
1701 if (transform
->buffer_type
)
1703 if (SUCCEEDED(hr
= MFCreateMediaType(&cloned_type
)))
1704 hr
= IMFMediaType_CopyAllItems(transform
->buffer_type
, (IMFAttributes
*)cloned_type
);
1707 hr
= MF_E_INVALIDSTREAMNUMBER
;
1709 hr
= MF_E_NO_MORE_TYPES
;
1710 LeaveCriticalSection(&transform
->cs
);
1713 *type
= cloned_type
;
1714 else if (cloned_type
)
1715 IMFMediaType_Release(cloned_type
);
1720 static HRESULT
sample_copier_get_buffer_size(IMFMediaType
*type
, DWORD
*size
)
1722 GUID major
, subtype
;
1728 if (FAILED(hr
= IMFMediaType_GetMajorType(type
, &major
)))
1731 if (IsEqualGUID(&major
, &MFMediaType_Video
))
1733 if (SUCCEEDED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
1735 if (SUCCEEDED(hr
= IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
1737 if (FAILED(hr
= MFCalculateImageSize(&subtype
, (UINT32
)(frame_size
>> 32), (UINT32
)frame_size
, size
)))
1738 WARN("Failed to get image size for video format %s.\n", debugstr_guid(&subtype
));
1742 else if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1744 FIXME("Audio formats are not handled.\n");
1751 static HRESULT
sample_copier_set_media_type(struct sample_copier
*transform
, BOOL input
, DWORD id
, IMFMediaType
*type
,
1758 return MF_E_INVALIDSTREAMNUMBER
;
1760 EnterCriticalSection(&transform
->cs
);
1763 hr
= sample_copier_get_buffer_size(type
, &buffer_size
);
1764 if (!(flags
& MFT_SET_TYPE_TEST_ONLY
) && SUCCEEDED(hr
))
1766 if (!transform
->buffer_type
)
1767 hr
= MFCreateMediaType(&transform
->buffer_type
);
1769 hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)transform
->buffer_type
);
1771 transform
->buffer_size
= buffer_size
;
1777 transform
->flags
|= SAMPLE_COPIER_INPUT_TYPE_SET
;
1778 transform
->flags
&= ~SAMPLE_COPIER_OUTPUT_TYPE_SET
;
1781 transform
->flags
|= SAMPLE_COPIER_OUTPUT_TYPE_SET
;
1785 else if (transform
->buffer_type
)
1787 IMFMediaType_Release(transform
->buffer_type
);
1788 transform
->buffer_type
= NULL
;
1790 LeaveCriticalSection(&transform
->cs
);
1795 static HRESULT WINAPI
sample_copier_transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
1797 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1799 TRACE("%p, %u, %p, %#x.\n", iface
, id
, type
, flags
);
1801 return sample_copier_set_media_type(transform
, TRUE
, id
, type
, flags
);
1804 static HRESULT WINAPI
sample_copier_transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
1806 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1808 TRACE("%p, %u, %p, %#x.\n", iface
, id
, type
, flags
);
1810 return sample_copier_set_media_type(transform
, FALSE
, id
, type
, flags
);
1813 static HRESULT
sample_copier_get_current_type(struct sample_copier
*transform
, DWORD id
, DWORD flags
,
1816 IMFMediaType
*cloned_type
= NULL
;
1820 return MF_E_INVALIDSTREAMNUMBER
;
1822 EnterCriticalSection(&transform
->cs
);
1823 if (transform
->flags
& flags
)
1825 if (SUCCEEDED(hr
= MFCreateMediaType(&cloned_type
)))
1826 hr
= IMFMediaType_CopyAllItems(transform
->buffer_type
, (IMFAttributes
*)cloned_type
);
1829 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1830 LeaveCriticalSection(&transform
->cs
);
1834 else if (cloned_type
)
1835 IMFMediaType_Release(cloned_type
);
1840 static HRESULT WINAPI
sample_copier_transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1842 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1844 TRACE("%p, %u, %p.\n", iface
, id
, type
);
1846 return sample_copier_get_current_type(transform
, id
, SAMPLE_COPIER_INPUT_TYPE_SET
, type
);
1849 static HRESULT WINAPI
sample_copier_transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1851 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1853 TRACE("%p, %u, %p.\n", iface
, id
, type
);
1855 return sample_copier_get_current_type(transform
, id
, SAMPLE_COPIER_OUTPUT_TYPE_SET
, type
);
1858 static HRESULT WINAPI
sample_copier_transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
1860 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1863 TRACE("%p, %u, %p.\n", iface
, id
, flags
);
1866 return MF_E_INVALIDSTREAMNUMBER
;
1868 EnterCriticalSection(&transform
->cs
);
1869 if (!(transform
->flags
& SAMPLE_COPIER_INPUT_TYPE_SET
))
1870 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1872 *flags
= transform
->sample
? 0 : MFT_INPUT_STATUS_ACCEPT_DATA
;
1873 LeaveCriticalSection(&transform
->cs
);
1878 static HRESULT WINAPI
sample_copier_transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
1880 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1883 TRACE("%p, %p.\n", iface
, flags
);
1885 EnterCriticalSection(&transform
->cs
);
1886 if (!(transform
->flags
& SAMPLE_COPIER_OUTPUT_TYPE_SET
))
1887 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1889 *flags
= transform
->sample
? MFT_OUTPUT_STATUS_SAMPLE_READY
: 0;
1890 LeaveCriticalSection(&transform
->cs
);
1895 static HRESULT WINAPI
sample_copier_transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
1897 TRACE("%p, %s, %s.\n", iface
, wine_dbgstr_longlong(lower
), wine_dbgstr_longlong(upper
));
1902 static HRESULT WINAPI
sample_copier_transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
1904 FIXME("%p, %u, %p.\n", iface
, id
, event
);
1909 static HRESULT WINAPI
sample_copier_transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
1911 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1913 TRACE("%p, %#x, %p.\n", iface
, message
, (void *)param
);
1915 EnterCriticalSection(&transform
->cs
);
1917 if (message
== MFT_MESSAGE_COMMAND_FLUSH
)
1919 if (transform
->sample
)
1921 IMFSample_Release(transform
->sample
);
1922 transform
->sample
= NULL
;
1926 LeaveCriticalSection(&transform
->cs
);
1931 static HRESULT WINAPI
sample_copier_transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
1933 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1936 TRACE("%p, %u, %p, %#x.\n", iface
, id
, sample
, flags
);
1939 return MF_E_INVALIDSTREAMNUMBER
;
1941 EnterCriticalSection(&transform
->cs
);
1942 if (!transform
->buffer_type
)
1943 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1944 else if (transform
->sample
)
1945 hr
= MF_E_NOTACCEPTING
;
1948 transform
->sample
= sample
;
1949 IMFSample_AddRef(transform
->sample
);
1951 LeaveCriticalSection(&transform
->cs
);
1956 static HRESULT WINAPI
sample_copier_transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
1957 MFT_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
1959 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1964 TRACE("%p, %#x, %u, %p, %p.\n", iface
, flags
, count
, buffers
, status
);
1966 EnterCriticalSection(&transform
->cs
);
1967 if (!(transform
->flags
& SAMPLE_COPIER_OUTPUT_TYPE_SET
))
1968 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1969 else if (!transform
->sample
)
1970 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1973 IMFSample_CopyAllItems(transform
->sample
, (IMFAttributes
*)buffers
->pSample
);
1975 if (SUCCEEDED(IMFSample_GetSampleDuration(transform
->sample
, &time
)))
1976 IMFSample_SetSampleDuration(buffers
->pSample
, time
);
1978 if (SUCCEEDED(IMFSample_GetSampleTime(transform
->sample
, &time
)))
1979 IMFSample_SetSampleTime(buffers
->pSample
, time
);
1981 if (SUCCEEDED(IMFSample_GetSampleFlags(transform
->sample
, &sample_flags
)))
1982 IMFSample_SetSampleFlags(buffers
->pSample
, sample_flags
);
1984 FIXME("Copy buffers.\n");
1986 IMFSample_Release(transform
->sample
);
1987 transform
->sample
= NULL
;
1989 LeaveCriticalSection(&transform
->cs
);
1994 static const IMFTransformVtbl sample_copier_transform_vtbl
=
1996 sample_copier_transform_QueryInterface
,
1997 sample_copier_transform_AddRef
,
1998 sample_copier_transform_Release
,
1999 sample_copier_transform_GetStreamLimits
,
2000 sample_copier_transform_GetStreamCount
,
2001 sample_copier_transform_GetStreamIDs
,
2002 sample_copier_transform_GetInputStreamInfo
,
2003 sample_copier_transform_GetOutputStreamInfo
,
2004 sample_copier_transform_GetAttributes
,
2005 sample_copier_transform_GetInputStreamAttributes
,
2006 sample_copier_transform_GetOutputStreamAttributes
,
2007 sample_copier_transform_DeleteInputStream
,
2008 sample_copier_transform_AddInputStreams
,
2009 sample_copier_transform_GetInputAvailableType
,
2010 sample_copier_transform_GetOutputAvailableType
,
2011 sample_copier_transform_SetInputType
,
2012 sample_copier_transform_SetOutputType
,
2013 sample_copier_transform_GetInputCurrentType
,
2014 sample_copier_transform_GetOutputCurrentType
,
2015 sample_copier_transform_GetInputStatus
,
2016 sample_copier_transform_GetOutputStatus
,
2017 sample_copier_transform_SetOutputBounds
,
2018 sample_copier_transform_ProcessEvent
,
2019 sample_copier_transform_ProcessMessage
,
2020 sample_copier_transform_ProcessInput
,
2021 sample_copier_transform_ProcessOutput
,
2024 HRESULT WINAPI
MFCreateSampleCopierMFT(IMFTransform
**transform
)
2026 struct sample_copier
*object
;
2028 TRACE("%p.\n", transform
);
2030 object
= heap_alloc_zero(sizeof(*object
));
2032 return E_OUTOFMEMORY
;
2034 object
->IMFTransform_iface
.lpVtbl
= &sample_copier_transform_vtbl
;
2035 object
->refcount
= 1;
2036 MFCreateAttributes(&object
->attributes
, 0);
2037 InitializeCriticalSection(&object
->cs
);
2039 *transform
= &object
->IMFTransform_iface
;