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
32 #include "mf_private.h"
34 #include "wine/debug.h"
35 #include "wine/heap.h"
36 #include "wine/list.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
40 static HINSTANCE mf_instance
;
41 extern const GUID CLSID_FileSchemePlugin
;
43 struct activate_object
45 IMFActivate IMFActivate_iface
;
47 IMFAttributes
*attributes
;
49 const struct activate_funcs
*funcs
;
53 static struct activate_object
*impl_from_IMFActivate(IMFActivate
*iface
)
55 return CONTAINING_RECORD(iface
, struct activate_object
, IMFActivate_iface
);
58 static HRESULT WINAPI
activate_object_QueryInterface(IMFActivate
*iface
, REFIID riid
, void **obj
)
60 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
62 if (IsEqualIID(riid
, &IID_IMFActivate
) ||
63 IsEqualIID(riid
, &IID_IMFAttributes
) ||
64 IsEqualIID(riid
, &IID_IUnknown
))
67 IMFActivate_AddRef(iface
);
71 WARN("Unsupported %s.\n", debugstr_guid(riid
));
76 static ULONG WINAPI
activate_object_AddRef(IMFActivate
*iface
)
78 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
79 ULONG refcount
= InterlockedIncrement(&activate
->refcount
);
81 TRACE("%p, refcount %u.\n", iface
, refcount
);
86 static ULONG WINAPI
activate_object_Release(IMFActivate
*iface
)
88 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
89 ULONG refcount
= InterlockedDecrement(&activate
->refcount
);
91 TRACE("%p, refcount %u.\n", iface
, refcount
);
95 activate
->funcs
->free_private(activate
->context
);
97 IUnknown_Release(activate
->object
);
98 IMFAttributes_Release(activate
->attributes
);
105 static HRESULT WINAPI
activate_object_GetItem(IMFActivate
*iface
, REFGUID key
, PROPVARIANT
*value
)
107 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
109 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
111 return IMFAttributes_GetItem(activate
->attributes
, key
, value
);
114 static HRESULT WINAPI
activate_object_GetItemType(IMFActivate
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
116 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
118 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
120 return IMFAttributes_GetItemType(activate
->attributes
, key
, type
);
123 static HRESULT WINAPI
activate_object_CompareItem(IMFActivate
*iface
, REFGUID key
, REFPROPVARIANT value
, BOOL
*result
)
125 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
127 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
129 return IMFAttributes_CompareItem(activate
->attributes
, key
, value
, result
);
132 static HRESULT WINAPI
activate_object_Compare(IMFActivate
*iface
, IMFAttributes
*theirs
, MF_ATTRIBUTES_MATCH_TYPE type
,
135 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
137 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
139 return IMFAttributes_Compare(activate
->attributes
, theirs
, type
, result
);
142 static HRESULT WINAPI
activate_object_GetUINT32(IMFActivate
*iface
, REFGUID key
, UINT32
*value
)
144 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
146 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
148 return IMFAttributes_GetUINT32(activate
->attributes
, key
, value
);
151 static HRESULT WINAPI
activate_object_GetUINT64(IMFActivate
*iface
, REFGUID key
, UINT64
*value
)
153 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
155 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
157 return IMFAttributes_GetUINT64(activate
->attributes
, key
, value
);
160 static HRESULT WINAPI
activate_object_GetDouble(IMFActivate
*iface
, REFGUID key
, double *value
)
162 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
164 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
166 return IMFAttributes_GetDouble(activate
->attributes
, key
, value
);
169 static HRESULT WINAPI
activate_object_GetGUID(IMFActivate
*iface
, REFGUID key
, GUID
*value
)
171 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
173 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
175 return IMFAttributes_GetGUID(activate
->attributes
, key
, value
);
178 static HRESULT WINAPI
activate_object_GetStringLength(IMFActivate
*iface
, REFGUID key
, UINT32
*length
)
180 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
182 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
184 return IMFAttributes_GetStringLength(activate
->attributes
, key
, length
);
187 static HRESULT WINAPI
activate_object_GetString(IMFActivate
*iface
, REFGUID key
, WCHAR
*value
,
188 UINT32 size
, UINT32
*length
)
190 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
192 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
194 return IMFAttributes_GetString(activate
->attributes
, key
, value
, size
, length
);
197 static HRESULT WINAPI
activate_object_GetAllocatedString(IMFActivate
*iface
, REFGUID key
,
198 WCHAR
**value
, UINT32
*length
)
200 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
202 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
204 return IMFAttributes_GetAllocatedString(activate
->attributes
, key
, value
, length
);
207 static HRESULT WINAPI
activate_object_GetBlobSize(IMFActivate
*iface
, REFGUID key
, UINT32
*size
)
209 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
211 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
213 return IMFAttributes_GetBlobSize(activate
->attributes
, key
, size
);
216 static HRESULT WINAPI
activate_object_GetBlob(IMFActivate
*iface
, REFGUID key
, UINT8
*buf
,
217 UINT32 bufsize
, UINT32
*blobsize
)
219 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
221 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
223 return IMFAttributes_GetBlob(activate
->attributes
, key
, buf
, bufsize
, blobsize
);
226 static HRESULT WINAPI
activate_object_GetAllocatedBlob(IMFActivate
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
228 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
230 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
232 return IMFAttributes_GetAllocatedBlob(activate
->attributes
, key
, buf
, size
);
235 static HRESULT WINAPI
activate_object_GetUnknown(IMFActivate
*iface
, REFGUID key
, REFIID riid
, void **ppv
)
237 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
239 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), ppv
);
241 return IMFAttributes_GetUnknown(activate
->attributes
, key
, riid
, ppv
);
244 static HRESULT WINAPI
activate_object_SetItem(IMFActivate
*iface
, REFGUID key
, REFPROPVARIANT value
)
246 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
248 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
250 return IMFAttributes_SetItem(activate
->attributes
, key
, value
);
253 static HRESULT WINAPI
activate_object_DeleteItem(IMFActivate
*iface
, REFGUID key
)
255 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
257 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
259 return IMFAttributes_DeleteItem(activate
->attributes
, key
);
262 static HRESULT WINAPI
activate_object_DeleteAllItems(IMFActivate
*iface
)
264 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
266 TRACE("%p.\n", iface
);
268 return IMFAttributes_DeleteAllItems(activate
->attributes
);
271 static HRESULT WINAPI
activate_object_SetUINT32(IMFActivate
*iface
, REFGUID key
, UINT32 value
)
273 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
275 TRACE("%p, %s, %d.\n", iface
, debugstr_guid(key
), value
);
277 return IMFAttributes_SetUINT32(activate
->attributes
, key
, value
);
280 static HRESULT WINAPI
activate_object_SetUINT64(IMFActivate
*iface
, REFGUID key
, UINT64 value
)
282 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
284 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
286 return IMFAttributes_SetUINT64(activate
->attributes
, key
, value
);
289 static HRESULT WINAPI
activate_object_SetDouble(IMFActivate
*iface
, REFGUID key
, double value
)
291 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
293 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
295 return IMFAttributes_SetDouble(activate
->attributes
, key
, value
);
298 static HRESULT WINAPI
activate_object_SetGUID(IMFActivate
*iface
, REFGUID key
, REFGUID value
)
300 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
302 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
304 return IMFAttributes_SetGUID(activate
->attributes
, key
, value
);
307 static HRESULT WINAPI
activate_object_SetString(IMFActivate
*iface
, REFGUID key
, const WCHAR
*value
)
309 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
311 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
313 return IMFAttributes_SetString(activate
->attributes
, key
, value
);
316 static HRESULT WINAPI
activate_object_SetBlob(IMFActivate
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
318 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
320 TRACE("%p, %s, %p, %d.\n", iface
, debugstr_guid(key
), buf
, size
);
322 return IMFAttributes_SetBlob(activate
->attributes
, key
, buf
, size
);
325 static HRESULT WINAPI
activate_object_SetUnknown(IMFActivate
*iface
, REFGUID key
, IUnknown
*unknown
)
327 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
329 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(key
), unknown
);
331 return IMFAttributes_SetUnknown(activate
->attributes
, key
, unknown
);
334 static HRESULT WINAPI
activate_object_LockStore(IMFActivate
*iface
)
336 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
338 TRACE("%p.\n", iface
);
340 return IMFAttributes_LockStore(activate
->attributes
);
343 static HRESULT WINAPI
activate_object_UnlockStore(IMFActivate
*iface
)
345 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
347 TRACE("%p.\n", iface
);
349 return IMFAttributes_UnlockStore(activate
->attributes
);
352 static HRESULT WINAPI
activate_object_GetCount(IMFActivate
*iface
, UINT32
*count
)
354 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
356 TRACE("%p, %p.\n", iface
, count
);
358 return IMFAttributes_GetCount(activate
->attributes
, count
);
361 static HRESULT WINAPI
activate_object_GetItemByIndex(IMFActivate
*iface
, UINT32 index
, GUID
*key
, PROPVARIANT
*value
)
363 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
365 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
367 return IMFAttributes_GetItemByIndex(activate
->attributes
, index
, key
, value
);
370 static HRESULT WINAPI
activate_object_CopyAllItems(IMFActivate
*iface
, IMFAttributes
*dest
)
372 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
374 TRACE("%p, %p.\n", iface
, dest
);
376 return IMFAttributes_CopyAllItems(activate
->attributes
, dest
);
379 static HRESULT WINAPI
activate_object_ActivateObject(IMFActivate
*iface
, REFIID riid
, void **obj
)
381 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
385 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
387 if (!activate
->object
)
389 if (FAILED(hr
= activate
->funcs
->create_object((IMFAttributes
*)iface
, activate
->context
, &object
)))
392 if (InterlockedCompareExchangePointer((void **)&activate
->object
, object
, NULL
))
393 IUnknown_Release(object
);
396 return IUnknown_QueryInterface(activate
->object
, riid
, obj
);
399 static HRESULT WINAPI
activate_object_ShutdownObject(IMFActivate
*iface
)
401 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
404 TRACE("%p.\n", iface
);
406 if ((object
= InterlockedCompareExchangePointer((void **)&activate
->object
, NULL
, activate
->object
)))
408 activate
->funcs
->shutdown_object(activate
->context
, object
);
409 IUnknown_Release(object
);
415 static HRESULT WINAPI
activate_object_DetachObject(IMFActivate
*iface
)
417 TRACE("%p.\n", iface
);
422 static const IMFActivateVtbl activate_object_vtbl
=
424 activate_object_QueryInterface
,
425 activate_object_AddRef
,
426 activate_object_Release
,
427 activate_object_GetItem
,
428 activate_object_GetItemType
,
429 activate_object_CompareItem
,
430 activate_object_Compare
,
431 activate_object_GetUINT32
,
432 activate_object_GetUINT64
,
433 activate_object_GetDouble
,
434 activate_object_GetGUID
,
435 activate_object_GetStringLength
,
436 activate_object_GetString
,
437 activate_object_GetAllocatedString
,
438 activate_object_GetBlobSize
,
439 activate_object_GetBlob
,
440 activate_object_GetAllocatedBlob
,
441 activate_object_GetUnknown
,
442 activate_object_SetItem
,
443 activate_object_DeleteItem
,
444 activate_object_DeleteAllItems
,
445 activate_object_SetUINT32
,
446 activate_object_SetUINT64
,
447 activate_object_SetDouble
,
448 activate_object_SetGUID
,
449 activate_object_SetString
,
450 activate_object_SetBlob
,
451 activate_object_SetUnknown
,
452 activate_object_LockStore
,
453 activate_object_UnlockStore
,
454 activate_object_GetCount
,
455 activate_object_GetItemByIndex
,
456 activate_object_CopyAllItems
,
457 activate_object_ActivateObject
,
458 activate_object_ShutdownObject
,
459 activate_object_DetachObject
,
462 HRESULT
create_activation_object(void *context
, const struct activate_funcs
*funcs
, IMFActivate
**ret
)
464 struct activate_object
*object
;
467 object
= heap_alloc_zero(sizeof(*object
));
469 return E_OUTOFMEMORY
;
471 object
->IMFActivate_iface
.lpVtbl
= &activate_object_vtbl
;
472 object
->refcount
= 1;
473 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
478 object
->funcs
= funcs
;
479 object
->context
= context
;
481 *ret
= &object
->IMFActivate_iface
;
488 IClassFactory IClassFactory_iface
;
489 HRESULT (*create_instance
)(REFIID riid
, void **obj
);
492 static inline struct class_factory
*impl_from_IClassFactory(IClassFactory
*iface
)
494 return CONTAINING_RECORD(iface
, struct class_factory
, IClassFactory_iface
);
497 static HRESULT WINAPI
class_factory_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **obj
)
499 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
501 if (IsEqualGUID(riid
, &IID_IClassFactory
) ||
502 IsEqualGUID(riid
, &IID_IUnknown
))
505 IClassFactory_AddRef(iface
);
509 WARN("%s is not supported.\n", debugstr_guid(riid
));
511 return E_NOINTERFACE
;
514 static ULONG WINAPI
class_factory_AddRef(IClassFactory
*iface
)
519 static ULONG WINAPI
class_factory_Release(IClassFactory
*iface
)
524 static HRESULT WINAPI
class_factory_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **obj
)
526 struct class_factory
*factory
= impl_from_IClassFactory(iface
);
528 TRACE("%p, %p, %s, %p.\n", iface
, outer
, debugstr_guid(riid
), obj
);
533 return CLASS_E_NOAGGREGATION
;
536 return factory
->create_instance(riid
, obj
);
539 static HRESULT WINAPI
class_factory_LockServer(IClassFactory
*iface
, BOOL dolock
)
541 FIXME("%d.\n", dolock
);
546 static const IClassFactoryVtbl class_factory_vtbl
=
548 class_factory_QueryInterface
,
549 class_factory_AddRef
,
550 class_factory_Release
,
551 class_factory_CreateInstance
,
552 class_factory_LockServer
,
555 struct file_scheme_handler_result
558 IMFAsyncResult
*result
;
559 MF_OBJECT_TYPE obj_type
;
563 struct file_scheme_handler
565 IMFSchemeHandler IMFSchemeHandler_iface
;
566 IMFAsyncCallback IMFAsyncCallback_iface
;
568 IMFSourceResolver
*resolver
;
573 static struct file_scheme_handler
*impl_from_IMFSchemeHandler(IMFSchemeHandler
*iface
)
575 return CONTAINING_RECORD(iface
, struct file_scheme_handler
, IMFSchemeHandler_iface
);
578 static struct file_scheme_handler
*impl_from_IMFAsyncCallback(IMFAsyncCallback
*iface
)
580 return CONTAINING_RECORD(iface
, struct file_scheme_handler
, IMFAsyncCallback_iface
);
583 static HRESULT WINAPI
file_scheme_handler_QueryInterface(IMFSchemeHandler
*iface
, REFIID riid
, void **obj
)
585 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
587 if (IsEqualIID(riid
, &IID_IMFSchemeHandler
) ||
588 IsEqualIID(riid
, &IID_IUnknown
))
591 IMFSchemeHandler_AddRef(iface
);
595 WARN("Unsupported %s.\n", debugstr_guid(riid
));
597 return E_NOINTERFACE
;
600 static ULONG WINAPI
file_scheme_handler_AddRef(IMFSchemeHandler
*iface
)
602 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
603 ULONG refcount
= InterlockedIncrement(&handler
->refcount
);
605 TRACE("%p, refcount %u.\n", handler
, refcount
);
610 static ULONG WINAPI
file_scheme_handler_Release(IMFSchemeHandler
*iface
)
612 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
613 ULONG refcount
= InterlockedDecrement(&handler
->refcount
);
614 struct file_scheme_handler_result
*result
, *next
;
616 TRACE("%p, refcount %u.\n", iface
, refcount
);
620 LIST_FOR_EACH_ENTRY_SAFE(result
, next
, &handler
->results
, struct file_scheme_handler_result
, entry
)
622 list_remove(&result
->entry
);
623 IMFAsyncResult_Release(result
->result
);
625 IUnknown_Release(result
->object
);
628 DeleteCriticalSection(&handler
->cs
);
629 if (handler
->resolver
)
630 IMFSourceResolver_Release(handler
->resolver
);
637 struct create_object_context
639 IUnknown IUnknown_iface
;
642 IPropertyStore
*props
;
647 static struct create_object_context
*impl_from_IUnknown(IUnknown
*iface
)
649 return CONTAINING_RECORD(iface
, struct create_object_context
, IUnknown_iface
);
652 static HRESULT WINAPI
create_object_context_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
654 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
656 if (IsEqualIID(riid
, &IID_IUnknown
))
659 IUnknown_AddRef(iface
);
663 WARN("Unsupported %s.\n", debugstr_guid(riid
));
665 return E_NOINTERFACE
;
668 static ULONG WINAPI
create_object_context_AddRef(IUnknown
*iface
)
670 struct create_object_context
*context
= impl_from_IUnknown(iface
);
671 ULONG refcount
= InterlockedIncrement(&context
->refcount
);
673 TRACE("%p, refcount %u.\n", iface
, refcount
);
678 static ULONG WINAPI
create_object_context_Release(IUnknown
*iface
)
680 struct create_object_context
*context
= impl_from_IUnknown(iface
);
681 ULONG refcount
= InterlockedDecrement(&context
->refcount
);
683 TRACE("%p, refcount %u.\n", iface
, refcount
);
688 IPropertyStore_Release(context
->props
);
689 heap_free(context
->url
);
696 static const IUnknownVtbl create_object_context_vtbl
=
698 create_object_context_QueryInterface
,
699 create_object_context_AddRef
,
700 create_object_context_Release
,
703 static WCHAR
*heap_strdupW(const WCHAR
*str
)
711 size
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
712 ret
= heap_alloc(size
);
714 memcpy(ret
, str
, size
);
720 static HRESULT WINAPI
file_scheme_handler_BeginCreateObject(IMFSchemeHandler
*iface
, const WCHAR
*url
, DWORD flags
,
721 IPropertyStore
*props
, IUnknown
**cancel_cookie
, IMFAsyncCallback
*callback
, IUnknown
*state
)
723 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
724 struct create_object_context
*context
;
725 IMFAsyncResult
*caller
, *item
;
728 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface
, debugstr_w(url
), flags
, props
, cancel_cookie
, callback
, state
);
731 *cancel_cookie
= NULL
;
733 if (FAILED(hr
= MFCreateAsyncResult(NULL
, callback
, state
, &caller
)))
736 context
= heap_alloc(sizeof(*context
));
739 IMFAsyncResult_Release(caller
);
740 return E_OUTOFMEMORY
;
743 context
->IUnknown_iface
.lpVtbl
= &create_object_context_vtbl
;
744 context
->refcount
= 1;
745 context
->props
= props
;
747 IPropertyStore_AddRef(context
->props
);
748 context
->flags
= flags
;
749 context
->url
= heap_strdupW(url
);
752 IMFAsyncResult_Release(caller
);
753 IUnknown_Release(&context
->IUnknown_iface
);
754 return E_OUTOFMEMORY
;
757 hr
= MFCreateAsyncResult(&context
->IUnknown_iface
, &handler
->IMFAsyncCallback_iface
, (IUnknown
*)caller
, &item
);
758 IUnknown_Release(&context
->IUnknown_iface
);
761 if (SUCCEEDED(hr
= MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO
, item
)))
765 *cancel_cookie
= (IUnknown
*)caller
;
766 IUnknown_AddRef(*cancel_cookie
);
770 IMFAsyncResult_Release(item
);
772 IMFAsyncResult_Release(caller
);
777 static HRESULT WINAPI
file_scheme_handler_EndCreateObject(IMFSchemeHandler
*iface
, IMFAsyncResult
*result
,
778 MF_OBJECT_TYPE
*obj_type
, IUnknown
**object
)
780 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
781 struct file_scheme_handler_result
*found
= NULL
, *cur
;
784 TRACE("%p, %p, %p, %p.\n", iface
, result
, obj_type
, object
);
786 EnterCriticalSection(&handler
->cs
);
788 LIST_FOR_EACH_ENTRY(cur
, &handler
->results
, struct file_scheme_handler_result
, entry
)
790 if (result
== cur
->result
)
792 list_remove(&cur
->entry
);
798 LeaveCriticalSection(&handler
->cs
);
802 *obj_type
= found
->obj_type
;
803 *object
= found
->object
;
804 hr
= IMFAsyncResult_GetStatus(found
->result
);
805 IMFAsyncResult_Release(found
->result
);
810 *obj_type
= MF_OBJECT_INVALID
;
812 hr
= MF_E_UNEXPECTED
;
818 static HRESULT WINAPI
file_scheme_handler_CancelObjectCreation(IMFSchemeHandler
*iface
, IUnknown
*cancel_cookie
)
820 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
821 struct file_scheme_handler_result
*found
= NULL
, *cur
;
823 TRACE("%p, %p.\n", iface
, cancel_cookie
);
825 EnterCriticalSection(&handler
->cs
);
827 LIST_FOR_EACH_ENTRY(cur
, &handler
->results
, struct file_scheme_handler_result
, entry
)
829 if (cancel_cookie
== (IUnknown
*)cur
->result
)
831 list_remove(&cur
->entry
);
837 LeaveCriticalSection(&handler
->cs
);
841 IMFAsyncResult_Release(found
->result
);
843 IUnknown_Release(found
->object
);
847 return found
? S_OK
: MF_E_UNEXPECTED
;
850 static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl
=
852 file_scheme_handler_QueryInterface
,
853 file_scheme_handler_AddRef
,
854 file_scheme_handler_Release
,
855 file_scheme_handler_BeginCreateObject
,
856 file_scheme_handler_EndCreateObject
,
857 file_scheme_handler_CancelObjectCreation
,
860 static HRESULT WINAPI
file_scheme_handler_callback_QueryInterface(IMFAsyncCallback
*iface
, REFIID riid
, void **obj
)
862 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
863 IsEqualIID(riid
, &IID_IUnknown
))
866 IMFAsyncCallback_AddRef(iface
);
870 WARN("Unsupported %s.\n", debugstr_guid(riid
));
872 return E_NOINTERFACE
;
875 static ULONG WINAPI
file_scheme_handler_callback_AddRef(IMFAsyncCallback
*iface
)
877 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
878 return IMFSchemeHandler_AddRef(&handler
->IMFSchemeHandler_iface
);
881 static ULONG WINAPI
file_scheme_handler_callback_Release(IMFAsyncCallback
*iface
)
883 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
884 return IMFSchemeHandler_Release(&handler
->IMFSchemeHandler_iface
);
887 static HRESULT WINAPI
file_scheme_handler_callback_GetParameters(IMFAsyncCallback
*iface
, DWORD
*flags
, DWORD
*queue
)
892 static HRESULT
file_scheme_handler_get_resolver(struct file_scheme_handler
*handler
, IMFSourceResolver
**resolver
)
896 if (!handler
->resolver
)
898 IMFSourceResolver
*resolver
;
900 if (FAILED(hr
= MFCreateSourceResolver(&resolver
)))
903 if (InterlockedCompareExchangePointer((void **)&handler
->resolver
, resolver
, NULL
))
904 IMFSourceResolver_Release(resolver
);
907 *resolver
= handler
->resolver
;
908 IMFSourceResolver_AddRef(*resolver
);
913 static HRESULT WINAPI
file_scheme_handler_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
915 static const WCHAR schemeW
[] = {'f','i','l','e',':','/','/'};
916 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
917 struct file_scheme_handler_result
*handler_result
;
918 MF_OBJECT_TYPE obj_type
= MF_OBJECT_INVALID
;
919 IUnknown
*object
= NULL
, *context_object
;
920 struct create_object_context
*context
;
921 IMFSourceResolver
*resolver
;
922 IMFAsyncResult
*caller
;
923 IMFByteStream
*stream
;
927 caller
= (IMFAsyncResult
*)IMFAsyncResult_GetStateNoAddRef(result
);
929 if (FAILED(hr
= IMFAsyncResult_GetObject(result
, &context_object
)))
931 WARN("Expected context set for callee result.\n");
935 context
= impl_from_IUnknown(context_object
);
937 /* Strip from scheme, MFCreateFile() won't be expecting it. */
939 if (!wcsnicmp(context
->url
, schemeW
, ARRAY_SIZE(schemeW
)))
940 url
+= ARRAY_SIZE(schemeW
);
942 hr
= MFCreateFile(context
->flags
& MF_RESOLUTION_WRITE
? MF_ACCESSMODE_READWRITE
: MF_ACCESSMODE_READ
,
943 MF_OPENMODE_FAIL_IF_NOT_EXIST
, MF_FILEFLAGS_NONE
, url
, &stream
);
946 if (context
->flags
& MF_RESOLUTION_MEDIASOURCE
)
948 if (SUCCEEDED(hr
= file_scheme_handler_get_resolver(handler
, &resolver
)))
950 hr
= IMFSourceResolver_CreateObjectFromByteStream(resolver
, stream
, context
->url
, context
->flags
,
951 context
->props
, &obj_type
, &object
);
952 IMFSourceResolver_Release(resolver
);
953 IMFByteStream_Release(stream
);
958 object
= (IUnknown
*)stream
;
959 obj_type
= MF_OBJECT_BYTESTREAM
;
963 handler_result
= heap_alloc(sizeof(*handler_result
));
966 handler_result
->result
= caller
;
967 IMFAsyncResult_AddRef(handler_result
->result
);
968 handler_result
->obj_type
= obj_type
;
969 handler_result
->object
= object
;
971 EnterCriticalSection(&handler
->cs
);
972 list_add_tail(&handler
->results
, &handler_result
->entry
);
973 LeaveCriticalSection(&handler
->cs
);
978 IUnknown_Release(object
);
982 IUnknown_Release(&context
->IUnknown_iface
);
984 IMFAsyncResult_SetStatus(caller
, hr
);
985 MFInvokeCallback(caller
);
990 static const IMFAsyncCallbackVtbl file_scheme_handler_callback_vtbl
=
992 file_scheme_handler_callback_QueryInterface
,
993 file_scheme_handler_callback_AddRef
,
994 file_scheme_handler_callback_Release
,
995 file_scheme_handler_callback_GetParameters
,
996 file_scheme_handler_callback_Invoke
,
999 static HRESULT
file_scheme_handler_construct(REFIID riid
, void **obj
)
1001 struct file_scheme_handler
*handler
;
1004 TRACE("%s, %p.\n", debugstr_guid(riid
), obj
);
1006 handler
= heap_alloc_zero(sizeof(*handler
));
1008 return E_OUTOFMEMORY
;
1010 handler
->IMFSchemeHandler_iface
.lpVtbl
= &file_scheme_handler_vtbl
;
1011 handler
->IMFAsyncCallback_iface
.lpVtbl
= &file_scheme_handler_callback_vtbl
;
1012 handler
->refcount
= 1;
1013 list_init(&handler
->results
);
1014 InitializeCriticalSection(&handler
->cs
);
1016 hr
= IMFSchemeHandler_QueryInterface(&handler
->IMFSchemeHandler_iface
, riid
, obj
);
1017 IMFSchemeHandler_Release(&handler
->IMFSchemeHandler_iface
);
1022 static struct class_factory file_scheme_handler_factory
= { { &class_factory_vtbl
}, file_scheme_handler_construct
};
1024 static const struct class_object
1027 IClassFactory
*factory
;
1031 { &CLSID_FileSchemePlugin
, &file_scheme_handler_factory
.IClassFactory_iface
},
1034 /*******************************************************************************
1035 * DllGetClassObject (mf.@)
1037 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **obj
)
1041 TRACE("%s, %s, %p.\n", debugstr_guid(rclsid
), debugstr_guid(riid
), obj
);
1043 for (i
= 0; i
< ARRAY_SIZE(class_objects
); ++i
)
1045 if (IsEqualGUID(class_objects
[i
].clsid
, rclsid
))
1046 return IClassFactory_QueryInterface(class_objects
[i
].factory
, riid
, obj
);
1049 WARN("%s: class not found.\n", debugstr_guid(rclsid
));
1050 return CLASS_E_CLASSNOTAVAILABLE
;
1053 /******************************************************************
1054 * DllCanUnloadNow (mf.@)
1056 HRESULT WINAPI
DllCanUnloadNow(void)
1061 /***********************************************************************
1062 * DllRegisterServer (mf.@)
1064 HRESULT WINAPI
DllRegisterServer(void)
1066 return __wine_register_resources( mf_instance
);
1069 /***********************************************************************
1070 * DllUnregisterServer (mf.@)
1072 HRESULT WINAPI
DllUnregisterServer(void)
1074 return __wine_unregister_resources( mf_instance
);
1077 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, LPVOID reserved
)
1081 case DLL_WINE_PREATTACH
:
1082 return FALSE
; /* prefer native version */
1083 case DLL_PROCESS_ATTACH
:
1084 mf_instance
= instance
;
1085 DisableThreadLibraryCalls(instance
);
1092 static HRESULT
prop_string_vector_append(PROPVARIANT
*vector
, unsigned int *capacity
, BOOL unique
, const WCHAR
*str
)
1099 for (i
= 0; i
< vector
->calpwstr
.cElems
; ++i
)
1101 if (!lstrcmpW(vector
->calpwstr
.pElems
[i
], str
))
1106 if (!*capacity
|| *capacity
- 1 < vector
->calpwstr
.cElems
)
1108 unsigned int new_count
;
1111 new_count
= *capacity
? *capacity
* 2 : 10;
1112 ptr
= CoTaskMemRealloc(vector
->calpwstr
.pElems
, new_count
* sizeof(*vector
->calpwstr
.pElems
));
1114 return E_OUTOFMEMORY
;
1115 vector
->calpwstr
.pElems
= ptr
;
1116 *capacity
= new_count
;
1119 len
= lstrlenW(str
);
1120 if (!(vector
->calpwstr
.pElems
[vector
->calpwstr
.cElems
] = ptrW
= CoTaskMemAlloc((len
+ 1) * sizeof(WCHAR
))))
1121 return E_OUTOFMEMORY
;
1123 lstrcpyW(ptrW
, str
);
1124 vector
->calpwstr
.cElems
++;
1129 static int __cdecl
qsort_string_compare(const void *a
, const void *b
)
1131 const WCHAR
*left
= *(const WCHAR
**)a
, *right
= *(const WCHAR
**)b
;
1132 return lstrcmpW(left
, right
);
1135 static HRESULT
mf_get_handler_strings(const WCHAR
*path
, WCHAR filter
, unsigned int maxlen
, PROPVARIANT
*dst
)
1137 static const HKEY hkey_roots
[2] = { HKEY_CURRENT_USER
, HKEY_LOCAL_MACHINE
};
1138 unsigned int capacity
= 0, count
, size
;
1143 buffW
= heap_calloc(maxlen
, sizeof(*buffW
));
1145 return E_OUTOFMEMORY
;
1147 memset(dst
, 0, sizeof(*dst
));
1148 dst
->vt
= VT_VECTOR
| VT_LPWSTR
;
1150 for (i
= 0; i
< ARRAY_SIZE(hkey_roots
); ++i
)
1154 if (RegOpenKeyW(hkey_roots
[i
], path
, &hkey
))
1159 count
= dst
->calpwstr
.cElems
;
1160 while (!RegEnumKeyExW(hkey
, index
++, buffW
, &size
, NULL
, NULL
, NULL
, NULL
))
1162 if (filter
&& !wcschr(buffW
, filter
))
1165 if (FAILED(hr
= prop_string_vector_append(dst
, &capacity
, 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
)
1296 TRACE("%p, %p.\n", hwnd
, activate
);
1301 hr
= create_activation_object(hwnd
, &evr_activate_funcs
, activate
);
1303 IMFActivate_SetUINT64(*activate
, &MF_ACTIVATE_VIDEO_WINDOW
, (ULONG_PTR
)hwnd
);
1308 struct simple_type_handler
1310 IMFMediaTypeHandler IMFMediaTypeHandler_iface
;
1312 IMFMediaType
*media_type
;
1313 CRITICAL_SECTION cs
;
1316 static struct simple_type_handler
*impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler
*iface
)
1318 return CONTAINING_RECORD(iface
, struct simple_type_handler
, IMFMediaTypeHandler_iface
);
1321 static HRESULT WINAPI
simple_type_handler_QueryInterface(IMFMediaTypeHandler
*iface
, REFIID riid
, void **obj
)
1323 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1325 if (IsEqualIID(riid
, &IID_IMFMediaTypeHandler
) ||
1326 IsEqualIID(riid
, &IID_IUnknown
))
1329 IMFMediaTypeHandler_AddRef(iface
);
1334 return E_NOINTERFACE
;
1337 static ULONG WINAPI
simple_type_handler_AddRef(IMFMediaTypeHandler
*iface
)
1339 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1340 ULONG refcount
= InterlockedIncrement(&handler
->refcount
);
1342 TRACE("%p, refcount %u.\n", iface
, refcount
);
1347 static ULONG WINAPI
simple_type_handler_Release(IMFMediaTypeHandler
*iface
)
1349 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1350 ULONG refcount
= InterlockedDecrement(&handler
->refcount
);
1352 TRACE("%p, refcount %u.\n", iface
, refcount
);
1356 if (handler
->media_type
)
1357 IMFMediaType_Release(handler
->media_type
);
1358 DeleteCriticalSection(&handler
->cs
);
1365 static HRESULT WINAPI
simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler
*iface
, IMFMediaType
*in_type
,
1366 IMFMediaType
**out_type
)
1368 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1372 TRACE("%p, %p, %p.\n", iface
, in_type
, out_type
);
1377 EnterCriticalSection(&handler
->cs
);
1378 if (!handler
->media_type
)
1379 hr
= MF_E_UNEXPECTED
;
1382 if (SUCCEEDED(hr
= IMFMediaType_IsEqual(handler
->media_type
, in_type
, &flags
)))
1383 hr
= (flags
& (MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
)) ==
1384 (MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
) ? S_OK
: E_FAIL
;
1386 LeaveCriticalSection(&handler
->cs
);
1391 static HRESULT WINAPI
simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler
*iface
, DWORD
*count
)
1393 TRACE("%p, %p.\n", iface
, count
);
1403 static HRESULT WINAPI
simple_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler
*iface
, DWORD index
,
1404 IMFMediaType
**type
)
1406 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1408 TRACE("%p, %u, %p.\n", iface
, index
, type
);
1411 return MF_E_NO_MORE_TYPES
;
1413 EnterCriticalSection(&handler
->cs
);
1414 *type
= handler
->media_type
;
1416 IMFMediaType_AddRef(*type
);
1417 LeaveCriticalSection(&handler
->cs
);
1422 static HRESULT WINAPI
simple_type_handler_SetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
*media_type
)
1424 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1426 TRACE("%p, %p.\n", iface
, media_type
);
1428 EnterCriticalSection(&handler
->cs
);
1429 if (handler
->media_type
)
1430 IMFMediaType_Release(handler
->media_type
);
1431 handler
->media_type
= media_type
;
1432 if (handler
->media_type
)
1433 IMFMediaType_AddRef(handler
->media_type
);
1434 LeaveCriticalSection(&handler
->cs
);
1439 static HRESULT WINAPI
simple_type_handler_GetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
**media_type
)
1441 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1443 TRACE("%p, %p.\n", iface
, media_type
);
1448 EnterCriticalSection(&handler
->cs
);
1449 *media_type
= handler
->media_type
;
1451 IMFMediaType_AddRef(*media_type
);
1452 LeaveCriticalSection(&handler
->cs
);
1457 static HRESULT WINAPI
simple_type_handler_GetMajorType(IMFMediaTypeHandler
*iface
, GUID
*type
)
1459 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1462 TRACE("%p, %p.\n", iface
, type
);
1464 EnterCriticalSection(&handler
->cs
);
1465 if (handler
->media_type
)
1466 hr
= IMFMediaType_GetGUID(handler
->media_type
, &MF_MT_MAJOR_TYPE
, type
);
1468 hr
= MF_E_NOT_INITIALIZED
;
1469 LeaveCriticalSection(&handler
->cs
);
1474 static const IMFMediaTypeHandlerVtbl simple_type_handler_vtbl
=
1476 simple_type_handler_QueryInterface
,
1477 simple_type_handler_AddRef
,
1478 simple_type_handler_Release
,
1479 simple_type_handler_IsMediaTypeSupported
,
1480 simple_type_handler_GetMediaTypeCount
,
1481 simple_type_handler_GetMediaTypeByIndex
,
1482 simple_type_handler_SetCurrentMediaType
,
1483 simple_type_handler_GetCurrentMediaType
,
1484 simple_type_handler_GetMajorType
,
1487 HRESULT WINAPI
MFCreateSimpleTypeHandler(IMFMediaTypeHandler
**handler
)
1489 struct simple_type_handler
*object
;
1491 TRACE("%p.\n", handler
);
1493 object
= heap_alloc_zero(sizeof(*object
));
1495 return E_OUTOFMEMORY
;
1497 object
->IMFMediaTypeHandler_iface
.lpVtbl
= &simple_type_handler_vtbl
;
1498 object
->refcount
= 1;
1499 InitializeCriticalSection(&object
->cs
);
1501 *handler
= &object
->IMFMediaTypeHandler_iface
;
1506 enum sample_copier_flags
1508 SAMPLE_COPIER_INPUT_TYPE_SET
= 0x1,
1509 SAMPLE_COPIER_OUTPUT_TYPE_SET
= 0x2
1512 struct sample_copier
1514 IMFTransform IMFTransform_iface
;
1517 IMFAttributes
*attributes
;
1518 IMFMediaType
*buffer_type
;
1522 CRITICAL_SECTION cs
;
1525 static struct sample_copier
*impl_copier_from_IMFTransform(IMFTransform
*iface
)
1527 return CONTAINING_RECORD(iface
, struct sample_copier
, IMFTransform_iface
);
1530 static HRESULT WINAPI
sample_copier_transform_QueryInterface(IMFTransform
*iface
, REFIID riid
, void **obj
)
1532 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1534 if (IsEqualIID(riid
, &IID_IMFTransform
) ||
1535 IsEqualIID(riid
, &IID_IUnknown
))
1538 IMFTransform_AddRef(iface
);
1542 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1544 return E_NOINTERFACE
;
1547 static ULONG WINAPI
sample_copier_transform_AddRef(IMFTransform
*iface
)
1549 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1550 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
1552 TRACE("%p, refcount %u.\n", iface
, refcount
);
1557 static ULONG WINAPI
sample_copier_transform_Release(IMFTransform
*iface
)
1559 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1560 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
1562 TRACE("%p, refcount %u.\n", iface
, refcount
);
1566 IMFAttributes_Release(transform
->attributes
);
1567 if (transform
->buffer_type
)
1568 IMFMediaType_Release(transform
->buffer_type
);
1569 DeleteCriticalSection(&transform
->cs
);
1570 heap_free(transform
);
1576 static HRESULT WINAPI
sample_copier_transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
1577 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
1579 TRACE("%p, %p, %p, %p, %p.\n", iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
1581 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
1586 static HRESULT WINAPI
sample_copier_transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
1588 TRACE("%p, %p, %p.\n", iface
, inputs
, outputs
);
1596 static HRESULT WINAPI
sample_copier_transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
1597 DWORD output_size
, DWORD
*outputs
)
1599 TRACE("%p, %u, %p, %u, %p.\n", iface
, input_size
, inputs
, output_size
, outputs
);
1604 static HRESULT WINAPI
sample_copier_transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
1606 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1608 TRACE("%p, %u, %p.\n", iface
, id
, info
);
1610 memset(info
, 0, sizeof(*info
));
1612 EnterCriticalSection(&transform
->cs
);
1613 info
->cbSize
= transform
->buffer_size
;
1614 LeaveCriticalSection(&transform
->cs
);
1619 static HRESULT WINAPI
sample_copier_transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
,
1620 MFT_OUTPUT_STREAM_INFO
*info
)
1622 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1624 TRACE("%p, %u, %p.\n", iface
, id
, info
);
1626 memset(info
, 0, sizeof(*info
));
1628 EnterCriticalSection(&transform
->cs
);
1629 info
->cbSize
= transform
->buffer_size
;
1630 LeaveCriticalSection(&transform
->cs
);
1635 static HRESULT WINAPI
sample_copier_transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
1637 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1639 TRACE("%p, %p.\n", iface
, attributes
);
1641 *attributes
= transform
->attributes
;
1642 IMFAttributes_AddRef(*attributes
);
1647 static HRESULT WINAPI
sample_copier_transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
,
1648 IMFAttributes
**attributes
)
1650 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
1655 static HRESULT WINAPI
sample_copier_transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
,
1656 IMFAttributes
**attributes
)
1658 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
1663 static HRESULT WINAPI
sample_copier_transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
1665 TRACE("%p, %u.\n", iface
, id
);
1670 static HRESULT WINAPI
sample_copier_transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
1672 TRACE("%p, %u, %p.\n", iface
, streams
, ids
);
1677 static HRESULT WINAPI
sample_copier_transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
1678 IMFMediaType
**type
)
1680 static const GUID
*types
[] = { &MFMediaType_Video
, &MFMediaType_Audio
};
1683 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
1686 return MF_E_INVALIDSTREAMNUMBER
;
1688 if (index
> ARRAY_SIZE(types
) - 1)
1689 return MF_E_NO_MORE_TYPES
;
1691 if (SUCCEEDED(hr
= MFCreateMediaType(type
)))
1692 hr
= IMFMediaType_SetGUID(*type
, &MF_MT_MAJOR_TYPE
, types
[index
]);
1697 static HRESULT WINAPI
sample_copier_transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
1698 IMFMediaType
**type
)
1700 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1701 IMFMediaType
*cloned_type
= NULL
;
1704 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
1706 EnterCriticalSection(&transform
->cs
);
1707 if (transform
->buffer_type
)
1709 if (SUCCEEDED(hr
= MFCreateMediaType(&cloned_type
)))
1710 hr
= IMFMediaType_CopyAllItems(transform
->buffer_type
, (IMFAttributes
*)cloned_type
);
1713 hr
= MF_E_INVALIDSTREAMNUMBER
;
1715 hr
= MF_E_NO_MORE_TYPES
;
1716 LeaveCriticalSection(&transform
->cs
);
1719 *type
= cloned_type
;
1720 else if (cloned_type
)
1721 IMFMediaType_Release(cloned_type
);
1726 static HRESULT
sample_copier_get_buffer_size(IMFMediaType
*type
, DWORD
*size
)
1728 GUID major
, subtype
;
1734 if (FAILED(hr
= IMFMediaType_GetMajorType(type
, &major
)))
1737 if (IsEqualGUID(&major
, &MFMediaType_Video
))
1739 if (SUCCEEDED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
1741 if (SUCCEEDED(hr
= IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
1743 if (FAILED(hr
= MFCalculateImageSize(&subtype
, (UINT32
)(frame_size
>> 32), (UINT32
)frame_size
, size
)))
1744 WARN("Failed to get image size for video format %s.\n", debugstr_guid(&subtype
));
1748 else if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1750 FIXME("Audio formats are not handled.\n");
1757 static HRESULT
sample_copier_set_media_type(struct sample_copier
*transform
, BOOL input
, DWORD id
, IMFMediaType
*type
,
1764 return MF_E_INVALIDSTREAMNUMBER
;
1766 EnterCriticalSection(&transform
->cs
);
1769 hr
= sample_copier_get_buffer_size(type
, &buffer_size
);
1770 if (!(flags
& MFT_SET_TYPE_TEST_ONLY
) && SUCCEEDED(hr
))
1772 if (!transform
->buffer_type
)
1773 hr
= MFCreateMediaType(&transform
->buffer_type
);
1775 hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)transform
->buffer_type
);
1777 transform
->buffer_size
= buffer_size
;
1783 transform
->flags
|= SAMPLE_COPIER_INPUT_TYPE_SET
;
1784 transform
->flags
&= ~SAMPLE_COPIER_OUTPUT_TYPE_SET
;
1787 transform
->flags
|= SAMPLE_COPIER_OUTPUT_TYPE_SET
;
1791 else if (transform
->buffer_type
)
1793 IMFMediaType_Release(transform
->buffer_type
);
1794 transform
->buffer_type
= NULL
;
1796 LeaveCriticalSection(&transform
->cs
);
1801 static HRESULT WINAPI
sample_copier_transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
1803 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1805 TRACE("%p, %u, %p, %#x.\n", iface
, id
, type
, flags
);
1807 return sample_copier_set_media_type(transform
, TRUE
, id
, type
, flags
);
1810 static HRESULT WINAPI
sample_copier_transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
1812 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1814 TRACE("%p, %u, %p, %#x.\n", iface
, id
, type
, flags
);
1816 return sample_copier_set_media_type(transform
, FALSE
, id
, type
, flags
);
1819 static HRESULT
sample_copier_get_current_type(struct sample_copier
*transform
, DWORD id
, DWORD flags
,
1822 IMFMediaType
*cloned_type
= NULL
;
1826 return MF_E_INVALIDSTREAMNUMBER
;
1828 EnterCriticalSection(&transform
->cs
);
1829 if (transform
->flags
& flags
)
1831 if (SUCCEEDED(hr
= MFCreateMediaType(&cloned_type
)))
1832 hr
= IMFMediaType_CopyAllItems(transform
->buffer_type
, (IMFAttributes
*)cloned_type
);
1835 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1836 LeaveCriticalSection(&transform
->cs
);
1840 else if (cloned_type
)
1841 IMFMediaType_Release(cloned_type
);
1846 static HRESULT WINAPI
sample_copier_transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1848 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1850 TRACE("%p, %u, %p.\n", iface
, id
, type
);
1852 return sample_copier_get_current_type(transform
, id
, SAMPLE_COPIER_INPUT_TYPE_SET
, type
);
1855 static HRESULT WINAPI
sample_copier_transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1857 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1859 TRACE("%p, %u, %p.\n", iface
, id
, type
);
1861 return sample_copier_get_current_type(transform
, id
, SAMPLE_COPIER_OUTPUT_TYPE_SET
, type
);
1864 static HRESULT WINAPI
sample_copier_transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
1866 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1869 TRACE("%p, %u, %p.\n", iface
, id
, flags
);
1872 return MF_E_INVALIDSTREAMNUMBER
;
1874 EnterCriticalSection(&transform
->cs
);
1875 if (!(transform
->flags
& SAMPLE_COPIER_INPUT_TYPE_SET
))
1876 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1878 *flags
= transform
->sample
? 0 : MFT_INPUT_STATUS_ACCEPT_DATA
;
1879 LeaveCriticalSection(&transform
->cs
);
1884 static HRESULT WINAPI
sample_copier_transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
1886 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1889 TRACE("%p, %p.\n", iface
, flags
);
1891 EnterCriticalSection(&transform
->cs
);
1892 if (!(transform
->flags
& SAMPLE_COPIER_OUTPUT_TYPE_SET
))
1893 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1895 *flags
= transform
->sample
? MFT_OUTPUT_STATUS_SAMPLE_READY
: 0;
1896 LeaveCriticalSection(&transform
->cs
);
1901 static HRESULT WINAPI
sample_copier_transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
1903 TRACE("%p, %s, %s.\n", iface
, debugstr_time(lower
), debugstr_time(upper
));
1908 static HRESULT WINAPI
sample_copier_transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
1910 FIXME("%p, %u, %p.\n", iface
, id
, event
);
1915 static HRESULT WINAPI
sample_copier_transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
1917 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1919 TRACE("%p, %#x, %p.\n", iface
, message
, (void *)param
);
1921 EnterCriticalSection(&transform
->cs
);
1923 if (message
== MFT_MESSAGE_COMMAND_FLUSH
)
1925 if (transform
->sample
)
1927 IMFSample_Release(transform
->sample
);
1928 transform
->sample
= NULL
;
1932 LeaveCriticalSection(&transform
->cs
);
1937 static HRESULT WINAPI
sample_copier_transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
1939 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1942 TRACE("%p, %u, %p, %#x.\n", iface
, id
, sample
, flags
);
1945 return MF_E_INVALIDSTREAMNUMBER
;
1947 EnterCriticalSection(&transform
->cs
);
1948 if (!transform
->buffer_type
)
1949 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1950 else if (transform
->sample
)
1951 hr
= MF_E_NOTACCEPTING
;
1954 transform
->sample
= sample
;
1955 IMFSample_AddRef(transform
->sample
);
1957 LeaveCriticalSection(&transform
->cs
);
1962 static HRESULT WINAPI
sample_copier_transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
1963 MFT_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
1965 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1966 IMFMediaBuffer
*buffer
;
1971 TRACE("%p, %#x, %u, %p, %p.\n", iface
, flags
, count
, buffers
, status
);
1973 EnterCriticalSection(&transform
->cs
);
1974 if (!(transform
->flags
& SAMPLE_COPIER_OUTPUT_TYPE_SET
))
1975 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1976 else if (!transform
->sample
)
1977 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1980 IMFSample_CopyAllItems(transform
->sample
, (IMFAttributes
*)buffers
->pSample
);
1982 if (SUCCEEDED(IMFSample_GetSampleDuration(transform
->sample
, &time
)))
1983 IMFSample_SetSampleDuration(buffers
->pSample
, time
);
1985 if (SUCCEEDED(IMFSample_GetSampleTime(transform
->sample
, &time
)))
1986 IMFSample_SetSampleTime(buffers
->pSample
, time
);
1988 if (SUCCEEDED(IMFSample_GetSampleFlags(transform
->sample
, &sample_flags
)))
1989 IMFSample_SetSampleFlags(buffers
->pSample
, sample_flags
);
1991 if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(transform
->sample
, NULL
)))
1993 if (SUCCEEDED(IMFSample_GetBufferByIndex(buffers
->pSample
, 0, &buffer
)))
1995 if (FAILED(IMFSample_CopyToBuffer(transform
->sample
, buffer
)))
1996 hr
= MF_E_UNEXPECTED
;
1997 IMFMediaBuffer_Release(buffer
);
2001 IMFSample_Release(transform
->sample
);
2002 transform
->sample
= NULL
;
2004 LeaveCriticalSection(&transform
->cs
);
2009 static const IMFTransformVtbl sample_copier_transform_vtbl
=
2011 sample_copier_transform_QueryInterface
,
2012 sample_copier_transform_AddRef
,
2013 sample_copier_transform_Release
,
2014 sample_copier_transform_GetStreamLimits
,
2015 sample_copier_transform_GetStreamCount
,
2016 sample_copier_transform_GetStreamIDs
,
2017 sample_copier_transform_GetInputStreamInfo
,
2018 sample_copier_transform_GetOutputStreamInfo
,
2019 sample_copier_transform_GetAttributes
,
2020 sample_copier_transform_GetInputStreamAttributes
,
2021 sample_copier_transform_GetOutputStreamAttributes
,
2022 sample_copier_transform_DeleteInputStream
,
2023 sample_copier_transform_AddInputStreams
,
2024 sample_copier_transform_GetInputAvailableType
,
2025 sample_copier_transform_GetOutputAvailableType
,
2026 sample_copier_transform_SetInputType
,
2027 sample_copier_transform_SetOutputType
,
2028 sample_copier_transform_GetInputCurrentType
,
2029 sample_copier_transform_GetOutputCurrentType
,
2030 sample_copier_transform_GetInputStatus
,
2031 sample_copier_transform_GetOutputStatus
,
2032 sample_copier_transform_SetOutputBounds
,
2033 sample_copier_transform_ProcessEvent
,
2034 sample_copier_transform_ProcessMessage
,
2035 sample_copier_transform_ProcessInput
,
2036 sample_copier_transform_ProcessOutput
,
2039 HRESULT WINAPI
MFCreateSampleCopierMFT(IMFTransform
**transform
)
2041 struct sample_copier
*object
;
2043 TRACE("%p.\n", transform
);
2045 object
= heap_alloc_zero(sizeof(*object
));
2047 return E_OUTOFMEMORY
;
2049 object
->IMFTransform_iface
.lpVtbl
= &sample_copier_transform_vtbl
;
2050 object
->refcount
= 1;
2051 MFCreateAttributes(&object
->attributes
, 0);
2052 InitializeCriticalSection(&object
->cs
);
2054 *transform
= &object
->IMFTransform_iface
;