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
29 #include "mf_private.h"
31 #include "wine/debug.h"
32 #include "wine/heap.h"
33 #include "wine/list.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
37 static HINSTANCE mf_instance
;
38 extern const GUID CLSID_FileSchemePlugin
;
40 struct activate_object
42 IMFActivate IMFActivate_iface
;
44 IMFAttributes
*attributes
;
46 const struct activate_funcs
*funcs
;
50 static struct activate_object
*impl_from_IMFActivate(IMFActivate
*iface
)
52 return CONTAINING_RECORD(iface
, struct activate_object
, IMFActivate_iface
);
55 static HRESULT WINAPI
activate_object_QueryInterface(IMFActivate
*iface
, REFIID riid
, void **obj
)
57 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
59 if (IsEqualIID(riid
, &IID_IMFActivate
) ||
60 IsEqualIID(riid
, &IID_IMFAttributes
) ||
61 IsEqualIID(riid
, &IID_IUnknown
))
64 IMFActivate_AddRef(iface
);
68 WARN("Unsupported %s.\n", debugstr_guid(riid
));
73 static ULONG WINAPI
activate_object_AddRef(IMFActivate
*iface
)
75 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
76 ULONG refcount
= InterlockedIncrement(&activate
->refcount
);
78 TRACE("%p, refcount %u.\n", iface
, refcount
);
83 static ULONG WINAPI
activate_object_Release(IMFActivate
*iface
)
85 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
86 ULONG refcount
= InterlockedDecrement(&activate
->refcount
);
88 TRACE("%p, refcount %u.\n", iface
, refcount
);
92 if (activate
->funcs
->free_private
)
93 activate
->funcs
->free_private(activate
->context
);
95 IUnknown_Release(activate
->object
);
96 IMFAttributes_Release(activate
->attributes
);
103 static HRESULT WINAPI
activate_object_GetItem(IMFActivate
*iface
, REFGUID key
, PROPVARIANT
*value
)
105 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
107 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
109 return IMFAttributes_GetItem(activate
->attributes
, key
, value
);
112 static HRESULT WINAPI
activate_object_GetItemType(IMFActivate
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
114 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
116 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
118 return IMFAttributes_GetItemType(activate
->attributes
, key
, type
);
121 static HRESULT WINAPI
activate_object_CompareItem(IMFActivate
*iface
, REFGUID key
, REFPROPVARIANT value
, BOOL
*result
)
123 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
125 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
127 return IMFAttributes_CompareItem(activate
->attributes
, key
, value
, result
);
130 static HRESULT WINAPI
activate_object_Compare(IMFActivate
*iface
, IMFAttributes
*theirs
, MF_ATTRIBUTES_MATCH_TYPE type
,
133 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
135 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
137 return IMFAttributes_Compare(activate
->attributes
, theirs
, type
, result
);
140 static HRESULT WINAPI
activate_object_GetUINT32(IMFActivate
*iface
, REFGUID key
, UINT32
*value
)
142 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
144 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
146 return IMFAttributes_GetUINT32(activate
->attributes
, key
, value
);
149 static HRESULT WINAPI
activate_object_GetUINT64(IMFActivate
*iface
, REFGUID key
, UINT64
*value
)
151 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
153 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
155 return IMFAttributes_GetUINT64(activate
->attributes
, key
, value
);
158 static HRESULT WINAPI
activate_object_GetDouble(IMFActivate
*iface
, REFGUID key
, double *value
)
160 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
162 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
164 return IMFAttributes_GetDouble(activate
->attributes
, key
, value
);
167 static HRESULT WINAPI
activate_object_GetGUID(IMFActivate
*iface
, REFGUID key
, GUID
*value
)
169 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
171 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
173 return IMFAttributes_GetGUID(activate
->attributes
, key
, value
);
176 static HRESULT WINAPI
activate_object_GetStringLength(IMFActivate
*iface
, REFGUID key
, UINT32
*length
)
178 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
180 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
182 return IMFAttributes_GetStringLength(activate
->attributes
, key
, length
);
185 static HRESULT WINAPI
activate_object_GetString(IMFActivate
*iface
, REFGUID key
, WCHAR
*value
,
186 UINT32 size
, UINT32
*length
)
188 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
190 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
192 return IMFAttributes_GetString(activate
->attributes
, key
, value
, size
, length
);
195 static HRESULT WINAPI
activate_object_GetAllocatedString(IMFActivate
*iface
, REFGUID key
,
196 WCHAR
**value
, UINT32
*length
)
198 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
200 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
202 return IMFAttributes_GetAllocatedString(activate
->attributes
, key
, value
, length
);
205 static HRESULT WINAPI
activate_object_GetBlobSize(IMFActivate
*iface
, REFGUID key
, UINT32
*size
)
207 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
209 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
211 return IMFAttributes_GetBlobSize(activate
->attributes
, key
, size
);
214 static HRESULT WINAPI
activate_object_GetBlob(IMFActivate
*iface
, REFGUID key
, UINT8
*buf
,
215 UINT32 bufsize
, UINT32
*blobsize
)
217 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
219 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
221 return IMFAttributes_GetBlob(activate
->attributes
, key
, buf
, bufsize
, blobsize
);
224 static HRESULT WINAPI
activate_object_GetAllocatedBlob(IMFActivate
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
226 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
228 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
230 return IMFAttributes_GetAllocatedBlob(activate
->attributes
, key
, buf
, size
);
233 static HRESULT WINAPI
activate_object_GetUnknown(IMFActivate
*iface
, REFGUID key
, REFIID riid
, void **ppv
)
235 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
237 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), ppv
);
239 return IMFAttributes_GetUnknown(activate
->attributes
, key
, riid
, ppv
);
242 static HRESULT WINAPI
activate_object_SetItem(IMFActivate
*iface
, REFGUID key
, REFPROPVARIANT value
)
244 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
246 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
248 return IMFAttributes_SetItem(activate
->attributes
, key
, value
);
251 static HRESULT WINAPI
activate_object_DeleteItem(IMFActivate
*iface
, REFGUID key
)
253 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
255 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
257 return IMFAttributes_DeleteItem(activate
->attributes
, key
);
260 static HRESULT WINAPI
activate_object_DeleteAllItems(IMFActivate
*iface
)
262 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
264 TRACE("%p.\n", iface
);
266 return IMFAttributes_DeleteAllItems(activate
->attributes
);
269 static HRESULT WINAPI
activate_object_SetUINT32(IMFActivate
*iface
, REFGUID key
, UINT32 value
)
271 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
273 TRACE("%p, %s, %d.\n", iface
, debugstr_guid(key
), value
);
275 return IMFAttributes_SetUINT32(activate
->attributes
, key
, value
);
278 static HRESULT WINAPI
activate_object_SetUINT64(IMFActivate
*iface
, REFGUID key
, UINT64 value
)
280 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
282 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
284 return IMFAttributes_SetUINT64(activate
->attributes
, key
, value
);
287 static HRESULT WINAPI
activate_object_SetDouble(IMFActivate
*iface
, REFGUID key
, double value
)
289 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
291 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
293 return IMFAttributes_SetDouble(activate
->attributes
, key
, value
);
296 static HRESULT WINAPI
activate_object_SetGUID(IMFActivate
*iface
, REFGUID key
, REFGUID value
)
298 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
300 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
302 return IMFAttributes_SetGUID(activate
->attributes
, key
, value
);
305 static HRESULT WINAPI
activate_object_SetString(IMFActivate
*iface
, REFGUID key
, const WCHAR
*value
)
307 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
309 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
311 return IMFAttributes_SetString(activate
->attributes
, key
, value
);
314 static HRESULT WINAPI
activate_object_SetBlob(IMFActivate
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
316 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
318 TRACE("%p, %s, %p, %d.\n", iface
, debugstr_guid(key
), buf
, size
);
320 return IMFAttributes_SetBlob(activate
->attributes
, key
, buf
, size
);
323 static HRESULT WINAPI
activate_object_SetUnknown(IMFActivate
*iface
, REFGUID key
, IUnknown
*unknown
)
325 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
327 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(key
), unknown
);
329 return IMFAttributes_SetUnknown(activate
->attributes
, key
, unknown
);
332 static HRESULT WINAPI
activate_object_LockStore(IMFActivate
*iface
)
334 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
336 TRACE("%p.\n", iface
);
338 return IMFAttributes_LockStore(activate
->attributes
);
341 static HRESULT WINAPI
activate_object_UnlockStore(IMFActivate
*iface
)
343 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
345 TRACE("%p.\n", iface
);
347 return IMFAttributes_UnlockStore(activate
->attributes
);
350 static HRESULT WINAPI
activate_object_GetCount(IMFActivate
*iface
, UINT32
*count
)
352 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
354 TRACE("%p, %p.\n", iface
, count
);
356 return IMFAttributes_GetCount(activate
->attributes
, count
);
359 static HRESULT WINAPI
activate_object_GetItemByIndex(IMFActivate
*iface
, UINT32 index
, GUID
*key
, PROPVARIANT
*value
)
361 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
363 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
365 return IMFAttributes_GetItemByIndex(activate
->attributes
, index
, key
, value
);
368 static HRESULT WINAPI
activate_object_CopyAllItems(IMFActivate
*iface
, IMFAttributes
*dest
)
370 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
372 TRACE("%p, %p.\n", iface
, dest
);
374 return IMFAttributes_CopyAllItems(activate
->attributes
, dest
);
377 static HRESULT WINAPI
activate_object_ActivateObject(IMFActivate
*iface
, REFIID riid
, void **obj
)
379 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
383 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
385 if (!activate
->object
)
387 if (FAILED(hr
= activate
->funcs
->create_object((IMFAttributes
*)iface
, activate
->context
, &object
)))
390 if (InterlockedCompareExchangePointer((void **)&activate
->object
, object
, NULL
))
391 IUnknown_Release(object
);
394 return IUnknown_QueryInterface(activate
->object
, riid
, obj
);
397 static HRESULT WINAPI
activate_object_ShutdownObject(IMFActivate
*iface
)
399 struct activate_object
*activate
= impl_from_IMFActivate(iface
);
402 TRACE("%p.\n", iface
);
404 if ((object
= InterlockedCompareExchangePointer((void **)&activate
->object
, NULL
, activate
->object
)))
406 activate
->funcs
->shutdown_object(activate
->context
, object
);
407 IUnknown_Release(object
);
413 static HRESULT WINAPI
activate_object_DetachObject(IMFActivate
*iface
)
415 TRACE("%p.\n", iface
);
420 static const IMFActivateVtbl activate_object_vtbl
=
422 activate_object_QueryInterface
,
423 activate_object_AddRef
,
424 activate_object_Release
,
425 activate_object_GetItem
,
426 activate_object_GetItemType
,
427 activate_object_CompareItem
,
428 activate_object_Compare
,
429 activate_object_GetUINT32
,
430 activate_object_GetUINT64
,
431 activate_object_GetDouble
,
432 activate_object_GetGUID
,
433 activate_object_GetStringLength
,
434 activate_object_GetString
,
435 activate_object_GetAllocatedString
,
436 activate_object_GetBlobSize
,
437 activate_object_GetBlob
,
438 activate_object_GetAllocatedBlob
,
439 activate_object_GetUnknown
,
440 activate_object_SetItem
,
441 activate_object_DeleteItem
,
442 activate_object_DeleteAllItems
,
443 activate_object_SetUINT32
,
444 activate_object_SetUINT64
,
445 activate_object_SetDouble
,
446 activate_object_SetGUID
,
447 activate_object_SetString
,
448 activate_object_SetBlob
,
449 activate_object_SetUnknown
,
450 activate_object_LockStore
,
451 activate_object_UnlockStore
,
452 activate_object_GetCount
,
453 activate_object_GetItemByIndex
,
454 activate_object_CopyAllItems
,
455 activate_object_ActivateObject
,
456 activate_object_ShutdownObject
,
457 activate_object_DetachObject
,
460 HRESULT
create_activation_object(void *context
, const struct activate_funcs
*funcs
, IMFActivate
**ret
)
462 struct activate_object
*object
;
465 object
= heap_alloc_zero(sizeof(*object
));
467 return E_OUTOFMEMORY
;
469 object
->IMFActivate_iface
.lpVtbl
= &activate_object_vtbl
;
470 object
->refcount
= 1;
471 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
476 object
->funcs
= funcs
;
477 object
->context
= context
;
479 *ret
= &object
->IMFActivate_iface
;
486 IClassFactory IClassFactory_iface
;
487 HRESULT (*create_instance
)(REFIID riid
, void **obj
);
490 static inline struct class_factory
*impl_from_IClassFactory(IClassFactory
*iface
)
492 return CONTAINING_RECORD(iface
, struct class_factory
, IClassFactory_iface
);
495 static HRESULT WINAPI
class_factory_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **obj
)
497 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
499 if (IsEqualGUID(riid
, &IID_IClassFactory
) ||
500 IsEqualGUID(riid
, &IID_IUnknown
))
503 IClassFactory_AddRef(iface
);
507 WARN("%s is not supported.\n", debugstr_guid(riid
));
509 return E_NOINTERFACE
;
512 static ULONG WINAPI
class_factory_AddRef(IClassFactory
*iface
)
517 static ULONG WINAPI
class_factory_Release(IClassFactory
*iface
)
522 static HRESULT WINAPI
class_factory_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **obj
)
524 struct class_factory
*factory
= impl_from_IClassFactory(iface
);
526 TRACE("%p, %p, %s, %p.\n", iface
, outer
, debugstr_guid(riid
), obj
);
531 return CLASS_E_NOAGGREGATION
;
534 return factory
->create_instance(riid
, obj
);
537 static HRESULT WINAPI
class_factory_LockServer(IClassFactory
*iface
, BOOL dolock
)
539 FIXME("%d.\n", dolock
);
544 static const IClassFactoryVtbl class_factory_vtbl
=
546 class_factory_QueryInterface
,
547 class_factory_AddRef
,
548 class_factory_Release
,
549 class_factory_CreateInstance
,
550 class_factory_LockServer
,
553 struct file_scheme_handler_result
556 IMFAsyncResult
*result
;
557 MF_OBJECT_TYPE obj_type
;
561 struct file_scheme_handler
563 IMFSchemeHandler IMFSchemeHandler_iface
;
564 IMFAsyncCallback IMFAsyncCallback_iface
;
566 IMFSourceResolver
*resolver
;
571 static struct file_scheme_handler
*impl_from_IMFSchemeHandler(IMFSchemeHandler
*iface
)
573 return CONTAINING_RECORD(iface
, struct file_scheme_handler
, IMFSchemeHandler_iface
);
576 static struct file_scheme_handler
*impl_from_IMFAsyncCallback(IMFAsyncCallback
*iface
)
578 return CONTAINING_RECORD(iface
, struct file_scheme_handler
, IMFAsyncCallback_iface
);
581 static HRESULT WINAPI
file_scheme_handler_QueryInterface(IMFSchemeHandler
*iface
, REFIID riid
, void **obj
)
583 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
585 if (IsEqualIID(riid
, &IID_IMFSchemeHandler
) ||
586 IsEqualIID(riid
, &IID_IUnknown
))
589 IMFSchemeHandler_AddRef(iface
);
593 WARN("Unsupported %s.\n", debugstr_guid(riid
));
595 return E_NOINTERFACE
;
598 static ULONG WINAPI
file_scheme_handler_AddRef(IMFSchemeHandler
*iface
)
600 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
601 ULONG refcount
= InterlockedIncrement(&handler
->refcount
);
603 TRACE("%p, refcount %u.\n", handler
, refcount
);
608 static ULONG WINAPI
file_scheme_handler_Release(IMFSchemeHandler
*iface
)
610 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
611 ULONG refcount
= InterlockedDecrement(&handler
->refcount
);
612 struct file_scheme_handler_result
*result
, *next
;
614 TRACE("%p, refcount %u.\n", iface
, refcount
);
618 LIST_FOR_EACH_ENTRY_SAFE(result
, next
, &handler
->results
, struct file_scheme_handler_result
, entry
)
620 list_remove(&result
->entry
);
621 IMFAsyncResult_Release(result
->result
);
623 IUnknown_Release(result
->object
);
626 DeleteCriticalSection(&handler
->cs
);
627 if (handler
->resolver
)
628 IMFSourceResolver_Release(handler
->resolver
);
635 struct create_object_context
637 IUnknown IUnknown_iface
;
640 IPropertyStore
*props
;
645 static struct create_object_context
*impl_from_IUnknown(IUnknown
*iface
)
647 return CONTAINING_RECORD(iface
, struct create_object_context
, IUnknown_iface
);
650 static HRESULT WINAPI
create_object_context_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
652 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
654 if (IsEqualIID(riid
, &IID_IUnknown
))
657 IUnknown_AddRef(iface
);
661 WARN("Unsupported %s.\n", debugstr_guid(riid
));
663 return E_NOINTERFACE
;
666 static ULONG WINAPI
create_object_context_AddRef(IUnknown
*iface
)
668 struct create_object_context
*context
= impl_from_IUnknown(iface
);
669 ULONG refcount
= InterlockedIncrement(&context
->refcount
);
671 TRACE("%p, refcount %u.\n", iface
, refcount
);
676 static ULONG WINAPI
create_object_context_Release(IUnknown
*iface
)
678 struct create_object_context
*context
= impl_from_IUnknown(iface
);
679 ULONG refcount
= InterlockedDecrement(&context
->refcount
);
681 TRACE("%p, refcount %u.\n", iface
, refcount
);
686 IPropertyStore_Release(context
->props
);
687 heap_free(context
->url
);
694 static const IUnknownVtbl create_object_context_vtbl
=
696 create_object_context_QueryInterface
,
697 create_object_context_AddRef
,
698 create_object_context_Release
,
701 static WCHAR
*heap_strdupW(const WCHAR
*str
)
709 size
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
710 ret
= heap_alloc(size
);
712 memcpy(ret
, str
, size
);
718 static HRESULT WINAPI
file_scheme_handler_BeginCreateObject(IMFSchemeHandler
*iface
, const WCHAR
*url
, DWORD flags
,
719 IPropertyStore
*props
, IUnknown
**cancel_cookie
, IMFAsyncCallback
*callback
, IUnknown
*state
)
721 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
722 struct create_object_context
*context
;
723 IMFAsyncResult
*caller
, *item
;
726 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface
, debugstr_w(url
), flags
, props
, cancel_cookie
, callback
, state
);
729 *cancel_cookie
= NULL
;
731 if (FAILED(hr
= MFCreateAsyncResult(NULL
, callback
, state
, &caller
)))
734 context
= heap_alloc(sizeof(*context
));
737 IMFAsyncResult_Release(caller
);
738 return E_OUTOFMEMORY
;
741 context
->IUnknown_iface
.lpVtbl
= &create_object_context_vtbl
;
742 context
->refcount
= 1;
743 context
->props
= props
;
745 IPropertyStore_AddRef(context
->props
);
746 context
->flags
= flags
;
747 context
->url
= heap_strdupW(url
);
750 IMFAsyncResult_Release(caller
);
751 IUnknown_Release(&context
->IUnknown_iface
);
752 return E_OUTOFMEMORY
;
755 hr
= MFCreateAsyncResult(&context
->IUnknown_iface
, &handler
->IMFAsyncCallback_iface
, (IUnknown
*)caller
, &item
);
756 IUnknown_Release(&context
->IUnknown_iface
);
759 if (SUCCEEDED(hr
= MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO
, item
)))
763 *cancel_cookie
= (IUnknown
*)caller
;
764 IUnknown_AddRef(*cancel_cookie
);
768 IMFAsyncResult_Release(item
);
770 IMFAsyncResult_Release(caller
);
775 static HRESULT WINAPI
file_scheme_handler_EndCreateObject(IMFSchemeHandler
*iface
, IMFAsyncResult
*result
,
776 MF_OBJECT_TYPE
*obj_type
, IUnknown
**object
)
778 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
779 struct file_scheme_handler_result
*found
= NULL
, *cur
;
782 TRACE("%p, %p, %p, %p.\n", iface
, result
, obj_type
, object
);
784 EnterCriticalSection(&handler
->cs
);
786 LIST_FOR_EACH_ENTRY(cur
, &handler
->results
, struct file_scheme_handler_result
, entry
)
788 if (result
== cur
->result
)
790 list_remove(&cur
->entry
);
796 LeaveCriticalSection(&handler
->cs
);
800 *obj_type
= found
->obj_type
;
801 *object
= found
->object
;
802 hr
= IMFAsyncResult_GetStatus(found
->result
);
803 IMFAsyncResult_Release(found
->result
);
808 *obj_type
= MF_OBJECT_INVALID
;
810 hr
= MF_E_UNEXPECTED
;
816 static HRESULT WINAPI
file_scheme_handler_CancelObjectCreation(IMFSchemeHandler
*iface
, IUnknown
*cancel_cookie
)
818 struct file_scheme_handler
*handler
= impl_from_IMFSchemeHandler(iface
);
819 struct file_scheme_handler_result
*found
= NULL
, *cur
;
821 TRACE("%p, %p.\n", iface
, cancel_cookie
);
823 EnterCriticalSection(&handler
->cs
);
825 LIST_FOR_EACH_ENTRY(cur
, &handler
->results
, struct file_scheme_handler_result
, entry
)
827 if (cancel_cookie
== (IUnknown
*)cur
->result
)
829 list_remove(&cur
->entry
);
835 LeaveCriticalSection(&handler
->cs
);
839 IMFAsyncResult_Release(found
->result
);
841 IUnknown_Release(found
->object
);
845 return found
? S_OK
: MF_E_UNEXPECTED
;
848 static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl
=
850 file_scheme_handler_QueryInterface
,
851 file_scheme_handler_AddRef
,
852 file_scheme_handler_Release
,
853 file_scheme_handler_BeginCreateObject
,
854 file_scheme_handler_EndCreateObject
,
855 file_scheme_handler_CancelObjectCreation
,
858 static HRESULT WINAPI
file_scheme_handler_callback_QueryInterface(IMFAsyncCallback
*iface
, REFIID riid
, void **obj
)
860 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
861 IsEqualIID(riid
, &IID_IUnknown
))
864 IMFAsyncCallback_AddRef(iface
);
868 WARN("Unsupported %s.\n", debugstr_guid(riid
));
870 return E_NOINTERFACE
;
873 static ULONG WINAPI
file_scheme_handler_callback_AddRef(IMFAsyncCallback
*iface
)
875 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
876 return IMFSchemeHandler_AddRef(&handler
->IMFSchemeHandler_iface
);
879 static ULONG WINAPI
file_scheme_handler_callback_Release(IMFAsyncCallback
*iface
)
881 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
882 return IMFSchemeHandler_Release(&handler
->IMFSchemeHandler_iface
);
885 static HRESULT WINAPI
file_scheme_handler_callback_GetParameters(IMFAsyncCallback
*iface
, DWORD
*flags
, DWORD
*queue
)
890 static HRESULT
file_scheme_handler_get_resolver(struct file_scheme_handler
*handler
, IMFSourceResolver
**resolver
)
894 if (!handler
->resolver
)
896 IMFSourceResolver
*resolver
;
898 if (FAILED(hr
= MFCreateSourceResolver(&resolver
)))
901 if (InterlockedCompareExchangePointer((void **)&handler
->resolver
, resolver
, NULL
))
902 IMFSourceResolver_Release(resolver
);
905 *resolver
= handler
->resolver
;
906 IMFSourceResolver_AddRef(*resolver
);
911 static HRESULT WINAPI
file_scheme_handler_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
913 static const WCHAR schemeW
[] = {'f','i','l','e',':','/','/'};
914 struct file_scheme_handler
*handler
= impl_from_IMFAsyncCallback(iface
);
915 struct file_scheme_handler_result
*handler_result
;
916 MF_OBJECT_TYPE obj_type
= MF_OBJECT_INVALID
;
917 IUnknown
*object
= NULL
, *context_object
;
918 struct create_object_context
*context
;
919 IMFSourceResolver
*resolver
;
920 IMFAsyncResult
*caller
;
921 IMFByteStream
*stream
;
925 caller
= (IMFAsyncResult
*)IMFAsyncResult_GetStateNoAddRef(result
);
927 if (FAILED(hr
= IMFAsyncResult_GetObject(result
, &context_object
)))
929 WARN("Expected context set for callee result.\n");
933 context
= impl_from_IUnknown(context_object
);
935 /* Strip from scheme, MFCreateFile() won't be expecting it. */
937 if (!wcsnicmp(context
->url
, schemeW
, ARRAY_SIZE(schemeW
)))
938 url
+= ARRAY_SIZE(schemeW
);
940 hr
= MFCreateFile(context
->flags
& MF_RESOLUTION_WRITE
? MF_ACCESSMODE_READWRITE
: MF_ACCESSMODE_READ
,
941 MF_OPENMODE_FAIL_IF_NOT_EXIST
, MF_FILEFLAGS_NONE
, url
, &stream
);
944 if (context
->flags
& MF_RESOLUTION_MEDIASOURCE
)
946 if (SUCCEEDED(hr
= file_scheme_handler_get_resolver(handler
, &resolver
)))
948 hr
= IMFSourceResolver_CreateObjectFromByteStream(resolver
, stream
, context
->url
, context
->flags
,
949 context
->props
, &obj_type
, &object
);
950 IMFSourceResolver_Release(resolver
);
951 IMFByteStream_Release(stream
);
956 object
= (IUnknown
*)stream
;
957 obj_type
= MF_OBJECT_BYTESTREAM
;
961 handler_result
= heap_alloc(sizeof(*handler_result
));
964 handler_result
->result
= caller
;
965 IMFAsyncResult_AddRef(handler_result
->result
);
966 handler_result
->obj_type
= obj_type
;
967 handler_result
->object
= object
;
969 EnterCriticalSection(&handler
->cs
);
970 list_add_tail(&handler
->results
, &handler_result
->entry
);
971 LeaveCriticalSection(&handler
->cs
);
976 IUnknown_Release(object
);
980 IUnknown_Release(&context
->IUnknown_iface
);
982 IMFAsyncResult_SetStatus(caller
, hr
);
983 MFInvokeCallback(caller
);
988 static const IMFAsyncCallbackVtbl file_scheme_handler_callback_vtbl
=
990 file_scheme_handler_callback_QueryInterface
,
991 file_scheme_handler_callback_AddRef
,
992 file_scheme_handler_callback_Release
,
993 file_scheme_handler_callback_GetParameters
,
994 file_scheme_handler_callback_Invoke
,
997 static HRESULT
file_scheme_handler_construct(REFIID riid
, void **obj
)
999 struct file_scheme_handler
*handler
;
1002 TRACE("%s, %p.\n", debugstr_guid(riid
), obj
);
1004 handler
= heap_alloc_zero(sizeof(*handler
));
1006 return E_OUTOFMEMORY
;
1008 handler
->IMFSchemeHandler_iface
.lpVtbl
= &file_scheme_handler_vtbl
;
1009 handler
->IMFAsyncCallback_iface
.lpVtbl
= &file_scheme_handler_callback_vtbl
;
1010 handler
->refcount
= 1;
1011 list_init(&handler
->results
);
1012 InitializeCriticalSection(&handler
->cs
);
1014 hr
= IMFSchemeHandler_QueryInterface(&handler
->IMFSchemeHandler_iface
, riid
, obj
);
1015 IMFSchemeHandler_Release(&handler
->IMFSchemeHandler_iface
);
1020 static struct class_factory file_scheme_handler_factory
= { { &class_factory_vtbl
}, file_scheme_handler_construct
};
1022 static const struct class_object
1025 IClassFactory
*factory
;
1029 { &CLSID_FileSchemePlugin
, &file_scheme_handler_factory
.IClassFactory_iface
},
1032 /*******************************************************************************
1033 * DllGetClassObject (mf.@)
1035 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **obj
)
1039 TRACE("%s, %s, %p.\n", debugstr_guid(rclsid
), debugstr_guid(riid
), obj
);
1041 for (i
= 0; i
< ARRAY_SIZE(class_objects
); ++i
)
1043 if (IsEqualGUID(class_objects
[i
].clsid
, rclsid
))
1044 return IClassFactory_QueryInterface(class_objects
[i
].factory
, riid
, obj
);
1047 WARN("%s: class not found.\n", debugstr_guid(rclsid
));
1048 return CLASS_E_CLASSNOTAVAILABLE
;
1051 /******************************************************************
1052 * DllCanUnloadNow (mf.@)
1054 HRESULT WINAPI
DllCanUnloadNow(void)
1059 /***********************************************************************
1060 * DllRegisterServer (mf.@)
1062 HRESULT WINAPI
DllRegisterServer(void)
1064 return __wine_register_resources( mf_instance
);
1067 /***********************************************************************
1068 * DllUnregisterServer (mf.@)
1070 HRESULT WINAPI
DllUnregisterServer(void)
1072 return __wine_unregister_resources( mf_instance
);
1075 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, LPVOID reserved
)
1079 case DLL_WINE_PREATTACH
:
1080 return FALSE
; /* prefer native version */
1081 case DLL_PROCESS_ATTACH
:
1082 mf_instance
= instance
;
1083 DisableThreadLibraryCalls(instance
);
1090 static HRESULT
prop_string_vector_append(PROPVARIANT
*vector
, unsigned int *capacity
, BOOL unique
, const WCHAR
*str
)
1097 for (i
= 0; i
< vector
->calpwstr
.cElems
; ++i
)
1099 if (!lstrcmpW(vector
->calpwstr
.pElems
[i
], str
))
1104 if (!*capacity
|| *capacity
- 1 < vector
->calpwstr
.cElems
)
1106 unsigned int new_count
;
1109 new_count
= *capacity
? *capacity
* 2 : 10;
1110 ptr
= CoTaskMemRealloc(vector
->calpwstr
.pElems
, new_count
* sizeof(*vector
->calpwstr
.pElems
));
1112 return E_OUTOFMEMORY
;
1113 vector
->calpwstr
.pElems
= ptr
;
1114 *capacity
= new_count
;
1117 len
= lstrlenW(str
);
1118 if (!(vector
->calpwstr
.pElems
[vector
->calpwstr
.cElems
] = ptrW
= CoTaskMemAlloc((len
+ 1) * sizeof(WCHAR
))))
1119 return E_OUTOFMEMORY
;
1121 lstrcpyW(ptrW
, str
);
1122 vector
->calpwstr
.cElems
++;
1127 static int __cdecl
qsort_string_compare(const void *a
, const void *b
)
1129 const WCHAR
*left
= *(const WCHAR
**)a
, *right
= *(const WCHAR
**)b
;
1130 return lstrcmpW(left
, right
);
1133 static HRESULT
mf_get_handler_strings(const WCHAR
*path
, WCHAR filter
, unsigned int maxlen
, PROPVARIANT
*dst
)
1135 static const HKEY hkey_roots
[2] = { HKEY_CURRENT_USER
, HKEY_LOCAL_MACHINE
};
1136 unsigned int capacity
= 0, count
, size
;
1141 buffW
= heap_calloc(maxlen
, sizeof(*buffW
));
1143 return E_OUTOFMEMORY
;
1145 memset(dst
, 0, sizeof(*dst
));
1146 dst
->vt
= VT_VECTOR
| VT_LPWSTR
;
1148 for (i
= 0; i
< ARRAY_SIZE(hkey_roots
); ++i
)
1152 if (RegOpenKeyW(hkey_roots
[i
], path
, &hkey
))
1157 count
= dst
->calpwstr
.cElems
;
1158 while (!RegEnumKeyExW(hkey
, index
++, buffW
, &size
, NULL
, NULL
, NULL
, NULL
))
1160 if (filter
&& !wcschr(buffW
, filter
))
1163 if (FAILED(hr
= prop_string_vector_append(dst
, &capacity
, i
> 0, buffW
)))
1168 /* Sort last pass results. */
1169 qsort(&dst
->calpwstr
.pElems
[count
], dst
->calpwstr
.cElems
- count
, sizeof(*dst
->calpwstr
.pElems
),
1170 qsort_string_compare
);
1176 PropVariantClear(dst
);
1183 /***********************************************************************
1184 * MFGetSupportedMimeTypes (mf.@)
1186 HRESULT WINAPI
MFGetSupportedMimeTypes(PROPVARIANT
*dst
)
1188 unsigned int maxlen
;
1190 TRACE("%p.\n", dst
);
1195 /* According to RFC4288 it's 127/127 characters. */
1196 maxlen
= 127 /* type */ + 1 /* / */ + 127 /* subtype */ + 1;
1197 return mf_get_handler_strings(L
"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", '/',
1201 /***********************************************************************
1202 * MFGetSupportedSchemes (mf.@)
1204 HRESULT WINAPI
MFGetSupportedSchemes(PROPVARIANT
*dst
)
1206 TRACE("%p.\n", dst
);
1211 return mf_get_handler_strings(L
"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", 0, 64, dst
);
1214 /***********************************************************************
1215 * MFGetService (mf.@)
1217 HRESULT WINAPI
MFGetService(IUnknown
*object
, REFGUID service
, REFIID riid
, void **obj
)
1222 TRACE("(%p, %s, %s, %p)\n", object
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1227 if (FAILED(hr
= IUnknown_QueryInterface(object
, &IID_IMFGetService
, (void **)&gs
)))
1230 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
1231 IMFGetService_Release(gs
);
1235 /***********************************************************************
1236 * MFShutdownObject (mf.@)
1238 HRESULT WINAPI
MFShutdownObject(IUnknown
*object
)
1240 IMFShutdown
*shutdown
;
1242 TRACE("%p.\n", object
);
1244 if (object
&& SUCCEEDED(IUnknown_QueryInterface(object
, &IID_IMFShutdown
, (void **)&shutdown
)))
1246 IMFShutdown_Shutdown(shutdown
);
1247 IMFShutdown_Release(shutdown
);
1253 /***********************************************************************
1254 * MFEnumDeviceSources (mf.@)
1256 HRESULT WINAPI
MFEnumDeviceSources(IMFAttributes
*attributes
, IMFActivate
***sources
, UINT32
*count
)
1258 FIXME("%p, %p, %p.\n", attributes
, sources
, count
);
1260 if (!attributes
|| !sources
|| !count
)
1261 return E_INVALIDARG
;
1268 struct simple_type_handler
1270 IMFMediaTypeHandler IMFMediaTypeHandler_iface
;
1272 IMFMediaType
*media_type
;
1273 CRITICAL_SECTION cs
;
1276 static struct simple_type_handler
*impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler
*iface
)
1278 return CONTAINING_RECORD(iface
, struct simple_type_handler
, IMFMediaTypeHandler_iface
);
1281 static HRESULT WINAPI
simple_type_handler_QueryInterface(IMFMediaTypeHandler
*iface
, REFIID riid
, void **obj
)
1283 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1285 if (IsEqualIID(riid
, &IID_IMFMediaTypeHandler
) ||
1286 IsEqualIID(riid
, &IID_IUnknown
))
1289 IMFMediaTypeHandler_AddRef(iface
);
1294 return E_NOINTERFACE
;
1297 static ULONG WINAPI
simple_type_handler_AddRef(IMFMediaTypeHandler
*iface
)
1299 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1300 ULONG refcount
= InterlockedIncrement(&handler
->refcount
);
1302 TRACE("%p, refcount %u.\n", iface
, refcount
);
1307 static ULONG WINAPI
simple_type_handler_Release(IMFMediaTypeHandler
*iface
)
1309 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1310 ULONG refcount
= InterlockedDecrement(&handler
->refcount
);
1312 TRACE("%p, refcount %u.\n", iface
, refcount
);
1316 if (handler
->media_type
)
1317 IMFMediaType_Release(handler
->media_type
);
1318 DeleteCriticalSection(&handler
->cs
);
1325 static HRESULT WINAPI
simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler
*iface
, IMFMediaType
*in_type
,
1326 IMFMediaType
**out_type
)
1328 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1332 TRACE("%p, %p, %p.\n", iface
, in_type
, out_type
);
1337 EnterCriticalSection(&handler
->cs
);
1338 if (!handler
->media_type
)
1339 hr
= MF_E_UNEXPECTED
;
1342 if (SUCCEEDED(hr
= IMFMediaType_IsEqual(handler
->media_type
, in_type
, &flags
)))
1343 hr
= (flags
& (MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
)) ==
1344 (MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
) ? S_OK
: E_FAIL
;
1346 LeaveCriticalSection(&handler
->cs
);
1351 static HRESULT WINAPI
simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler
*iface
, DWORD
*count
)
1353 TRACE("%p, %p.\n", iface
, count
);
1363 static HRESULT WINAPI
simple_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler
*iface
, DWORD index
,
1364 IMFMediaType
**type
)
1366 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1368 TRACE("%p, %u, %p.\n", iface
, index
, type
);
1371 return MF_E_NO_MORE_TYPES
;
1373 EnterCriticalSection(&handler
->cs
);
1374 *type
= handler
->media_type
;
1376 IMFMediaType_AddRef(*type
);
1377 LeaveCriticalSection(&handler
->cs
);
1382 static HRESULT WINAPI
simple_type_handler_SetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
*media_type
)
1384 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1386 TRACE("%p, %p.\n", iface
, media_type
);
1388 EnterCriticalSection(&handler
->cs
);
1389 if (handler
->media_type
)
1390 IMFMediaType_Release(handler
->media_type
);
1391 handler
->media_type
= media_type
;
1392 if (handler
->media_type
)
1393 IMFMediaType_AddRef(handler
->media_type
);
1394 LeaveCriticalSection(&handler
->cs
);
1399 static HRESULT WINAPI
simple_type_handler_GetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
**media_type
)
1401 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1403 TRACE("%p, %p.\n", iface
, media_type
);
1408 EnterCriticalSection(&handler
->cs
);
1409 *media_type
= handler
->media_type
;
1411 IMFMediaType_AddRef(*media_type
);
1412 LeaveCriticalSection(&handler
->cs
);
1417 static HRESULT WINAPI
simple_type_handler_GetMajorType(IMFMediaTypeHandler
*iface
, GUID
*type
)
1419 struct simple_type_handler
*handler
= impl_from_IMFMediaTypeHandler(iface
);
1422 TRACE("%p, %p.\n", iface
, type
);
1424 EnterCriticalSection(&handler
->cs
);
1425 if (handler
->media_type
)
1426 hr
= IMFMediaType_GetGUID(handler
->media_type
, &MF_MT_MAJOR_TYPE
, type
);
1428 hr
= MF_E_NOT_INITIALIZED
;
1429 LeaveCriticalSection(&handler
->cs
);
1434 static const IMFMediaTypeHandlerVtbl simple_type_handler_vtbl
=
1436 simple_type_handler_QueryInterface
,
1437 simple_type_handler_AddRef
,
1438 simple_type_handler_Release
,
1439 simple_type_handler_IsMediaTypeSupported
,
1440 simple_type_handler_GetMediaTypeCount
,
1441 simple_type_handler_GetMediaTypeByIndex
,
1442 simple_type_handler_SetCurrentMediaType
,
1443 simple_type_handler_GetCurrentMediaType
,
1444 simple_type_handler_GetMajorType
,
1447 HRESULT WINAPI
MFCreateSimpleTypeHandler(IMFMediaTypeHandler
**handler
)
1449 struct simple_type_handler
*object
;
1451 TRACE("%p.\n", handler
);
1453 object
= heap_alloc_zero(sizeof(*object
));
1455 return E_OUTOFMEMORY
;
1457 object
->IMFMediaTypeHandler_iface
.lpVtbl
= &simple_type_handler_vtbl
;
1458 object
->refcount
= 1;
1459 InitializeCriticalSection(&object
->cs
);
1461 *handler
= &object
->IMFMediaTypeHandler_iface
;
1466 enum sample_copier_flags
1468 SAMPLE_COPIER_INPUT_TYPE_SET
= 0x1,
1469 SAMPLE_COPIER_OUTPUT_TYPE_SET
= 0x2
1472 struct sample_copier
1474 IMFTransform IMFTransform_iface
;
1477 IMFAttributes
*attributes
;
1478 IMFMediaType
*buffer_type
;
1482 CRITICAL_SECTION cs
;
1485 static struct sample_copier
*impl_copier_from_IMFTransform(IMFTransform
*iface
)
1487 return CONTAINING_RECORD(iface
, struct sample_copier
, IMFTransform_iface
);
1490 static HRESULT WINAPI
sample_copier_transform_QueryInterface(IMFTransform
*iface
, REFIID riid
, void **obj
)
1492 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1494 if (IsEqualIID(riid
, &IID_IMFTransform
) ||
1495 IsEqualIID(riid
, &IID_IUnknown
))
1498 IMFTransform_AddRef(iface
);
1502 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1504 return E_NOINTERFACE
;
1507 static ULONG WINAPI
sample_copier_transform_AddRef(IMFTransform
*iface
)
1509 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1510 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
1512 TRACE("%p, refcount %u.\n", iface
, refcount
);
1517 static ULONG WINAPI
sample_copier_transform_Release(IMFTransform
*iface
)
1519 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1520 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
1522 TRACE("%p, refcount %u.\n", iface
, refcount
);
1526 IMFAttributes_Release(transform
->attributes
);
1527 if (transform
->buffer_type
)
1528 IMFMediaType_Release(transform
->buffer_type
);
1529 DeleteCriticalSection(&transform
->cs
);
1530 heap_free(transform
);
1536 static HRESULT WINAPI
sample_copier_transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
1537 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
1539 TRACE("%p, %p, %p, %p, %p.\n", iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
1541 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
1546 static HRESULT WINAPI
sample_copier_transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
1548 TRACE("%p, %p, %p.\n", iface
, inputs
, outputs
);
1556 static HRESULT WINAPI
sample_copier_transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
1557 DWORD output_size
, DWORD
*outputs
)
1559 TRACE("%p, %u, %p, %u, %p.\n", iface
, input_size
, inputs
, output_size
, outputs
);
1564 static HRESULT WINAPI
sample_copier_transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
1566 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1568 TRACE("%p, %u, %p.\n", iface
, id
, info
);
1570 memset(info
, 0, sizeof(*info
));
1572 EnterCriticalSection(&transform
->cs
);
1573 info
->cbSize
= transform
->buffer_size
;
1574 LeaveCriticalSection(&transform
->cs
);
1579 static HRESULT WINAPI
sample_copier_transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
,
1580 MFT_OUTPUT_STREAM_INFO
*info
)
1582 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1584 TRACE("%p, %u, %p.\n", iface
, id
, info
);
1586 memset(info
, 0, sizeof(*info
));
1588 EnterCriticalSection(&transform
->cs
);
1589 info
->cbSize
= transform
->buffer_size
;
1590 LeaveCriticalSection(&transform
->cs
);
1595 static HRESULT WINAPI
sample_copier_transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
1597 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1599 TRACE("%p, %p.\n", iface
, attributes
);
1601 *attributes
= transform
->attributes
;
1602 IMFAttributes_AddRef(*attributes
);
1607 static HRESULT WINAPI
sample_copier_transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
,
1608 IMFAttributes
**attributes
)
1610 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
1615 static HRESULT WINAPI
sample_copier_transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
,
1616 IMFAttributes
**attributes
)
1618 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
1623 static HRESULT WINAPI
sample_copier_transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
1625 TRACE("%p, %u.\n", iface
, id
);
1630 static HRESULT WINAPI
sample_copier_transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
1632 TRACE("%p, %u, %p.\n", iface
, streams
, ids
);
1637 static HRESULT WINAPI
sample_copier_transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
1638 IMFMediaType
**type
)
1640 static const GUID
*types
[] = { &MFMediaType_Video
, &MFMediaType_Audio
};
1643 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
1646 return MF_E_INVALIDSTREAMNUMBER
;
1648 if (index
> ARRAY_SIZE(types
) - 1)
1649 return MF_E_NO_MORE_TYPES
;
1651 if (SUCCEEDED(hr
= MFCreateMediaType(type
)))
1652 hr
= IMFMediaType_SetGUID(*type
, &MF_MT_MAJOR_TYPE
, types
[index
]);
1657 static HRESULT WINAPI
sample_copier_transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
1658 IMFMediaType
**type
)
1660 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1661 IMFMediaType
*cloned_type
= NULL
;
1664 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
1666 EnterCriticalSection(&transform
->cs
);
1667 if (transform
->buffer_type
)
1669 if (SUCCEEDED(hr
= MFCreateMediaType(&cloned_type
)))
1670 hr
= IMFMediaType_CopyAllItems(transform
->buffer_type
, (IMFAttributes
*)cloned_type
);
1673 hr
= MF_E_INVALIDSTREAMNUMBER
;
1675 hr
= MF_E_NO_MORE_TYPES
;
1676 LeaveCriticalSection(&transform
->cs
);
1679 *type
= cloned_type
;
1680 else if (cloned_type
)
1681 IMFMediaType_Release(cloned_type
);
1686 static HRESULT
sample_copier_get_buffer_size(IMFMediaType
*type
, DWORD
*size
)
1688 GUID major
, subtype
;
1694 if (FAILED(hr
= IMFMediaType_GetMajorType(type
, &major
)))
1697 if (IsEqualGUID(&major
, &MFMediaType_Video
))
1699 if (SUCCEEDED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
1701 if (SUCCEEDED(hr
= IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
1703 if (FAILED(hr
= MFCalculateImageSize(&subtype
, (UINT32
)(frame_size
>> 32), (UINT32
)frame_size
, size
)))
1704 WARN("Failed to get image size for video format %s.\n", debugstr_guid(&subtype
));
1708 else if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1710 FIXME("Audio formats are not handled.\n");
1717 static HRESULT
sample_copier_set_media_type(struct sample_copier
*transform
, BOOL input
, DWORD id
, IMFMediaType
*type
,
1724 return MF_E_INVALIDSTREAMNUMBER
;
1726 EnterCriticalSection(&transform
->cs
);
1729 hr
= sample_copier_get_buffer_size(type
, &buffer_size
);
1730 if (!(flags
& MFT_SET_TYPE_TEST_ONLY
) && SUCCEEDED(hr
))
1732 if (!transform
->buffer_type
)
1733 hr
= MFCreateMediaType(&transform
->buffer_type
);
1735 hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)transform
->buffer_type
);
1737 transform
->buffer_size
= buffer_size
;
1743 transform
->flags
|= SAMPLE_COPIER_INPUT_TYPE_SET
;
1744 transform
->flags
&= ~SAMPLE_COPIER_OUTPUT_TYPE_SET
;
1747 transform
->flags
|= SAMPLE_COPIER_OUTPUT_TYPE_SET
;
1751 else if (transform
->buffer_type
)
1753 IMFMediaType_Release(transform
->buffer_type
);
1754 transform
->buffer_type
= NULL
;
1756 LeaveCriticalSection(&transform
->cs
);
1761 static HRESULT WINAPI
sample_copier_transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
1763 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1765 TRACE("%p, %u, %p, %#x.\n", iface
, id
, type
, flags
);
1767 return sample_copier_set_media_type(transform
, TRUE
, id
, type
, flags
);
1770 static HRESULT WINAPI
sample_copier_transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
1772 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1774 TRACE("%p, %u, %p, %#x.\n", iface
, id
, type
, flags
);
1776 return sample_copier_set_media_type(transform
, FALSE
, id
, type
, flags
);
1779 static HRESULT
sample_copier_get_current_type(struct sample_copier
*transform
, DWORD id
, DWORD flags
,
1782 IMFMediaType
*cloned_type
= NULL
;
1786 return MF_E_INVALIDSTREAMNUMBER
;
1788 EnterCriticalSection(&transform
->cs
);
1789 if (transform
->flags
& flags
)
1791 if (SUCCEEDED(hr
= MFCreateMediaType(&cloned_type
)))
1792 hr
= IMFMediaType_CopyAllItems(transform
->buffer_type
, (IMFAttributes
*)cloned_type
);
1795 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1796 LeaveCriticalSection(&transform
->cs
);
1800 else if (cloned_type
)
1801 IMFMediaType_Release(cloned_type
);
1806 static HRESULT WINAPI
sample_copier_transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1808 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1810 TRACE("%p, %u, %p.\n", iface
, id
, type
);
1812 return sample_copier_get_current_type(transform
, id
, SAMPLE_COPIER_INPUT_TYPE_SET
, type
);
1815 static HRESULT WINAPI
sample_copier_transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1817 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1819 TRACE("%p, %u, %p.\n", iface
, id
, type
);
1821 return sample_copier_get_current_type(transform
, id
, SAMPLE_COPIER_OUTPUT_TYPE_SET
, type
);
1824 static HRESULT WINAPI
sample_copier_transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
1826 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1829 TRACE("%p, %u, %p.\n", iface
, id
, flags
);
1832 return MF_E_INVALIDSTREAMNUMBER
;
1834 EnterCriticalSection(&transform
->cs
);
1835 if (!(transform
->flags
& SAMPLE_COPIER_INPUT_TYPE_SET
))
1836 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1838 *flags
= transform
->sample
? 0 : MFT_INPUT_STATUS_ACCEPT_DATA
;
1839 LeaveCriticalSection(&transform
->cs
);
1844 static HRESULT WINAPI
sample_copier_transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
1846 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1849 TRACE("%p, %p.\n", iface
, flags
);
1851 EnterCriticalSection(&transform
->cs
);
1852 if (!(transform
->flags
& SAMPLE_COPIER_OUTPUT_TYPE_SET
))
1853 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1855 *flags
= transform
->sample
? MFT_OUTPUT_STATUS_SAMPLE_READY
: 0;
1856 LeaveCriticalSection(&transform
->cs
);
1861 static HRESULT WINAPI
sample_copier_transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
1863 TRACE("%p, %s, %s.\n", iface
, debugstr_time(lower
), debugstr_time(upper
));
1868 static HRESULT WINAPI
sample_copier_transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
1870 FIXME("%p, %u, %p.\n", iface
, id
, event
);
1875 static HRESULT WINAPI
sample_copier_transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
1877 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1879 TRACE("%p, %#x, %p.\n", iface
, message
, (void *)param
);
1881 EnterCriticalSection(&transform
->cs
);
1883 if (message
== MFT_MESSAGE_COMMAND_FLUSH
)
1885 if (transform
->sample
)
1887 IMFSample_Release(transform
->sample
);
1888 transform
->sample
= NULL
;
1892 LeaveCriticalSection(&transform
->cs
);
1897 static HRESULT WINAPI
sample_copier_transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
1899 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1902 TRACE("%p, %u, %p, %#x.\n", iface
, id
, sample
, flags
);
1905 return MF_E_INVALIDSTREAMNUMBER
;
1907 EnterCriticalSection(&transform
->cs
);
1908 if (!transform
->buffer_type
)
1909 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1910 else if (transform
->sample
)
1911 hr
= MF_E_NOTACCEPTING
;
1914 transform
->sample
= sample
;
1915 IMFSample_AddRef(transform
->sample
);
1917 LeaveCriticalSection(&transform
->cs
);
1922 static HRESULT WINAPI
sample_copier_transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
1923 MFT_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
1925 struct sample_copier
*transform
= impl_copier_from_IMFTransform(iface
);
1926 IMFMediaBuffer
*buffer
;
1931 TRACE("%p, %#x, %u, %p, %p.\n", iface
, flags
, count
, buffers
, status
);
1933 EnterCriticalSection(&transform
->cs
);
1934 if (!(transform
->flags
& SAMPLE_COPIER_OUTPUT_TYPE_SET
))
1935 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1936 else if (!transform
->sample
)
1937 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1940 IMFSample_CopyAllItems(transform
->sample
, (IMFAttributes
*)buffers
->pSample
);
1942 if (SUCCEEDED(IMFSample_GetSampleDuration(transform
->sample
, &time
)))
1943 IMFSample_SetSampleDuration(buffers
->pSample
, time
);
1945 if (SUCCEEDED(IMFSample_GetSampleTime(transform
->sample
, &time
)))
1946 IMFSample_SetSampleTime(buffers
->pSample
, time
);
1948 if (SUCCEEDED(IMFSample_GetSampleFlags(transform
->sample
, &sample_flags
)))
1949 IMFSample_SetSampleFlags(buffers
->pSample
, sample_flags
);
1951 if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(transform
->sample
, NULL
)))
1953 if (SUCCEEDED(IMFSample_GetBufferByIndex(buffers
->pSample
, 0, &buffer
)))
1955 if (FAILED(IMFSample_CopyToBuffer(transform
->sample
, buffer
)))
1956 hr
= MF_E_UNEXPECTED
;
1957 IMFMediaBuffer_Release(buffer
);
1961 IMFSample_Release(transform
->sample
);
1962 transform
->sample
= NULL
;
1964 LeaveCriticalSection(&transform
->cs
);
1969 static const IMFTransformVtbl sample_copier_transform_vtbl
=
1971 sample_copier_transform_QueryInterface
,
1972 sample_copier_transform_AddRef
,
1973 sample_copier_transform_Release
,
1974 sample_copier_transform_GetStreamLimits
,
1975 sample_copier_transform_GetStreamCount
,
1976 sample_copier_transform_GetStreamIDs
,
1977 sample_copier_transform_GetInputStreamInfo
,
1978 sample_copier_transform_GetOutputStreamInfo
,
1979 sample_copier_transform_GetAttributes
,
1980 sample_copier_transform_GetInputStreamAttributes
,
1981 sample_copier_transform_GetOutputStreamAttributes
,
1982 sample_copier_transform_DeleteInputStream
,
1983 sample_copier_transform_AddInputStreams
,
1984 sample_copier_transform_GetInputAvailableType
,
1985 sample_copier_transform_GetOutputAvailableType
,
1986 sample_copier_transform_SetInputType
,
1987 sample_copier_transform_SetOutputType
,
1988 sample_copier_transform_GetInputCurrentType
,
1989 sample_copier_transform_GetOutputCurrentType
,
1990 sample_copier_transform_GetInputStatus
,
1991 sample_copier_transform_GetOutputStatus
,
1992 sample_copier_transform_SetOutputBounds
,
1993 sample_copier_transform_ProcessEvent
,
1994 sample_copier_transform_ProcessMessage
,
1995 sample_copier_transform_ProcessInput
,
1996 sample_copier_transform_ProcessOutput
,
1999 HRESULT WINAPI
MFCreateSampleCopierMFT(IMFTransform
**transform
)
2001 struct sample_copier
*object
;
2003 TRACE("%p.\n", transform
);
2005 object
= heap_alloc_zero(sizeof(*object
));
2007 return E_OUTOFMEMORY
;
2009 object
->IMFTransform_iface
.lpVtbl
= &sample_copier_transform_vtbl
;
2010 object
->refcount
= 1;
2011 MFCreateAttributes(&object
->attributes
, 0);
2012 InitializeCriticalSection(&object
->cs
);
2014 *transform
= &object
->IMFTransform_iface
;