mfplat: Implement DXGI device manager handle management.
[wine.git] / dlls / mfplat / main.c
blob68aa2cdaa2deaff9d7cf80381612d48752d599c5
1 /*
2 * Copyright 2014 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
19 #include <stdarg.h>
20 #include <string.h>
21 #include <math.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winreg.h"
31 #include "initguid.h"
32 #include "rtworkq.h"
33 #include "ole2.h"
34 #include "propsys.h"
35 #include "dxgi.h"
37 #include "wine/debug.h"
38 #include "wine/list.h"
40 #include "mfplat_private.h"
41 #include "mfreadwrite.h"
42 #include "mfmediaengine.h"
43 #include "propvarutil.h"
44 #include "strsafe.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
48 static HRESULT heap_strdupW(const WCHAR *str, WCHAR **dest)
50 HRESULT hr = S_OK;
52 if (str)
54 unsigned int size;
56 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
57 *dest = heap_alloc(size);
58 if (*dest)
59 memcpy(*dest, str, size);
60 else
61 hr = E_OUTOFMEMORY;
63 else
64 *dest = NULL;
66 return hr;
69 struct local_handler
71 struct list entry;
72 union
74 WCHAR *scheme;
75 struct
77 WCHAR *extension;
78 WCHAR *mime;
79 } bytestream;
80 } u;
81 IMFActivate *activate;
84 static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
86 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
87 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
89 struct mft_registration
91 struct list entry;
92 IClassFactory *factory;
93 CLSID clsid;
94 GUID category;
95 WCHAR *name;
96 DWORD flags;
97 MFT_REGISTER_TYPE_INFO *input_types;
98 UINT32 input_types_count;
99 MFT_REGISTER_TYPE_INFO *output_types;
100 UINT32 output_types_count;
101 BOOL local;
104 static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
106 static struct list local_mfts = LIST_INIT(local_mfts);
108 struct transform_activate
110 struct attributes attributes;
111 IMFActivate IMFActivate_iface;
112 IClassFactory *factory;
113 IMFTransform *transform;
116 struct system_clock
118 IMFClock IMFClock_iface;
119 LONG refcount;
122 struct system_time_source
124 IMFPresentationTimeSource IMFPresentationTimeSource_iface;
125 IMFClockStateSink IMFClockStateSink_iface;
126 LONG refcount;
127 MFCLOCK_STATE state;
128 IMFClock *clock;
129 LONGLONG start_offset;
130 float rate;
131 int i_rate;
132 CRITICAL_SECTION cs;
135 static void system_time_source_apply_rate(const struct system_time_source *source, LONGLONG *value)
137 if (source->i_rate)
138 *value *= source->i_rate;
139 else
140 *value *= source->rate;
143 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
145 return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
148 static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
150 return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
153 static struct system_clock *impl_from_IMFClock(IMFClock *iface)
155 return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
158 static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface)
160 return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface);
163 static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out)
165 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
167 if (IsEqualIID(riid, &IID_IMFActivate) ||
168 IsEqualIID(riid, &IID_IMFAttributes) ||
169 IsEqualIID(riid, &IID_IUnknown))
171 *out = iface;
172 IMFActivate_AddRef(iface);
173 return S_OK;
176 WARN("Unsupported %s.\n", debugstr_guid(riid));
177 *out = NULL;
178 return E_NOINTERFACE;
181 static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface)
183 struct transform_activate *activate = impl_from_IMFActivate(iface);
184 ULONG refcount = InterlockedIncrement(&activate->attributes.ref);
186 TRACE("%p, refcount %u.\n", iface, refcount);
188 return refcount;
191 static ULONG WINAPI transform_activate_Release(IMFActivate *iface)
193 struct transform_activate *activate = impl_from_IMFActivate(iface);
194 ULONG refcount = InterlockedDecrement(&activate->attributes.ref);
196 TRACE("%p, refcount %u.\n", iface, refcount);
198 if (!refcount)
200 clear_attributes_object(&activate->attributes);
201 if (activate->factory)
202 IClassFactory_Release(activate->factory);
203 if (activate->transform)
204 IMFTransform_Release(activate->transform);
205 heap_free(activate);
208 return refcount;
211 static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
213 struct transform_activate *activate = impl_from_IMFActivate(iface);
215 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
217 return attributes_GetItem(&activate->attributes, key, value);
220 static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
222 struct transform_activate *activate = impl_from_IMFActivate(iface);
224 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
226 return attributes_GetItemType(&activate->attributes, key, type);
229 static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value,
230 BOOL *result)
232 struct transform_activate *activate = impl_from_IMFActivate(iface);
234 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
236 return attributes_CompareItem(&activate->attributes, key, value, result);
239 static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs,
240 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
242 struct transform_activate *activate = impl_from_IMFActivate(iface);
244 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
246 return attributes_Compare(&activate->attributes, theirs, match_type, ret);
249 static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
251 struct transform_activate *activate = impl_from_IMFActivate(iface);
253 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
255 return attributes_GetUINT32(&activate->attributes, key, value);
258 static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
260 struct transform_activate *activate = impl_from_IMFActivate(iface);
262 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
264 return attributes_GetUINT64(&activate->attributes, key, value);
267 static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value)
269 struct transform_activate *activate = impl_from_IMFActivate(iface);
271 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
273 return attributes_GetDouble(&activate->attributes, key, value);
276 static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
278 struct transform_activate *activate = impl_from_IMFActivate(iface);
280 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
282 return attributes_GetGUID(&activate->attributes, key, value);
285 static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
287 struct transform_activate *activate = impl_from_IMFActivate(iface);
289 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
291 return attributes_GetStringLength(&activate->attributes, key, length);
294 static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
295 UINT32 size, UINT32 *length)
297 struct transform_activate *activate = impl_from_IMFActivate(iface);
299 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
301 return attributes_GetString(&activate->attributes, key, value, size, length);
304 static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value,
305 UINT32 *length)
307 struct transform_activate *activate = impl_from_IMFActivate(iface);
309 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
311 return attributes_GetAllocatedString(&activate->attributes, key, value, length);
314 static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
316 struct transform_activate *activate = impl_from_IMFActivate(iface);
318 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
320 return attributes_GetBlobSize(&activate->attributes, key, size);
323 static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize,
324 UINT32 *blobsize)
326 struct transform_activate *activate = impl_from_IMFActivate(iface);
328 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
330 return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize);
333 static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
335 struct transform_activate *activate = impl_from_IMFActivate(iface);
337 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
339 return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size);
342 static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out)
344 struct transform_activate *activate = impl_from_IMFActivate(iface);
346 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
348 return attributes_GetUnknown(&activate->attributes, key, riid, out);
351 static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
353 struct transform_activate *activate = impl_from_IMFActivate(iface);
355 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
357 return attributes_SetItem(&activate->attributes, key, value);
360 static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key)
362 struct transform_activate *activate = impl_from_IMFActivate(iface);
364 TRACE("%p, %s.\n", iface, debugstr_attr(key));
366 return attributes_DeleteItem(&activate->attributes, key);
369 static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface)
371 struct transform_activate *activate = impl_from_IMFActivate(iface);
373 TRACE("%p.\n", iface);
375 return attributes_DeleteAllItems(&activate->attributes);
378 static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
380 struct transform_activate *activate = impl_from_IMFActivate(iface);
382 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
384 return attributes_SetUINT32(&activate->attributes, key, value);
387 static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
389 struct transform_activate *activate = impl_from_IMFActivate(iface);
391 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
393 return attributes_SetUINT64(&activate->attributes, key, value);
396 static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value)
398 struct transform_activate *activate = impl_from_IMFActivate(iface);
400 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
402 return attributes_SetDouble(&activate->attributes, key, value);
405 static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
407 struct transform_activate *activate = impl_from_IMFActivate(iface);
409 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
411 return attributes_SetGUID(&activate->attributes, key, value);
414 static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
416 struct transform_activate *activate = impl_from_IMFActivate(iface);
418 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
420 return attributes_SetString(&activate->attributes, key, value);
423 static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
425 struct transform_activate *activate = impl_from_IMFActivate(iface);
427 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
429 return attributes_SetBlob(&activate->attributes, key, buf, size);
432 static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
434 struct transform_activate *activate = impl_from_IMFActivate(iface);
436 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
438 return attributes_SetUnknown(&activate->attributes, key, unknown);
441 static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface)
443 struct transform_activate *activate = impl_from_IMFActivate(iface);
445 TRACE("%p.\n", iface);
447 return attributes_LockStore(&activate->attributes);
450 static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface)
452 struct transform_activate *activate = impl_from_IMFActivate(iface);
454 TRACE("%p.\n", iface);
456 return attributes_UnlockStore(&activate->attributes);
459 static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count)
461 struct transform_activate *activate = impl_from_IMFActivate(iface);
463 TRACE("%p, %p.\n", iface, count);
465 return attributes_GetCount(&activate->attributes, count);
468 static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key,
469 PROPVARIANT *value)
471 struct transform_activate *activate = impl_from_IMFActivate(iface);
473 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
475 return attributes_GetItemByIndex(&activate->attributes, index, key, value);
478 static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
480 struct transform_activate *activate = impl_from_IMFActivate(iface);
482 TRACE("%p, %p.\n", iface, dest);
484 return attributes_CopyAllItems(&activate->attributes, dest);
487 static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
489 struct transform_activate *activate = impl_from_IMFActivate(iface);
490 CLSID clsid;
491 HRESULT hr;
493 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
495 EnterCriticalSection(&activate->attributes.cs);
497 if (!activate->transform)
499 if (activate->factory)
501 if (FAILED(hr = IClassFactory_CreateInstance(activate->factory, NULL, &IID_IMFTransform,
502 (void **)&activate->transform)))
504 hr = MF_E_INVALIDREQUEST;
507 else
509 if (SUCCEEDED(hr = attributes_GetGUID(&activate->attributes, &MFT_TRANSFORM_CLSID_Attribute, &clsid)))
511 if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
512 (void **)&activate->transform)))
514 hr = MF_E_INVALIDREQUEST;
520 if (activate->transform)
521 hr = IMFTransform_QueryInterface(activate->transform, riid, obj);
523 LeaveCriticalSection(&activate->attributes.cs);
525 return hr;
528 static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface)
530 struct transform_activate *activate = impl_from_IMFActivate(iface);
532 TRACE("%p.\n", iface);
534 EnterCriticalSection(&activate->attributes.cs);
536 if (activate->transform)
538 IMFTransform_Release(activate->transform);
539 activate->transform = NULL;
542 LeaveCriticalSection(&activate->attributes.cs);
544 return S_OK;
547 static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface)
549 TRACE("%p.\n", iface);
551 return E_NOTIMPL;
554 static const IMFActivateVtbl transform_activate_vtbl =
556 transform_activate_QueryInterface,
557 transform_activate_AddRef,
558 transform_activate_Release,
559 transform_activate_GetItem,
560 transform_activate_GetItemType,
561 transform_activate_CompareItem,
562 transform_activate_Compare,
563 transform_activate_GetUINT32,
564 transform_activate_GetUINT64,
565 transform_activate_GetDouble,
566 transform_activate_GetGUID,
567 transform_activate_GetStringLength,
568 transform_activate_GetString,
569 transform_activate_GetAllocatedString,
570 transform_activate_GetBlobSize,
571 transform_activate_GetBlob,
572 transform_activate_GetAllocatedBlob,
573 transform_activate_GetUnknown,
574 transform_activate_SetItem,
575 transform_activate_DeleteItem,
576 transform_activate_DeleteAllItems,
577 transform_activate_SetUINT32,
578 transform_activate_SetUINT64,
579 transform_activate_SetDouble,
580 transform_activate_SetGUID,
581 transform_activate_SetString,
582 transform_activate_SetBlob,
583 transform_activate_SetUnknown,
584 transform_activate_LockStore,
585 transform_activate_UnlockStore,
586 transform_activate_GetCount,
587 transform_activate_GetItemByIndex,
588 transform_activate_CopyAllItems,
589 transform_activate_ActivateObject,
590 transform_activate_ShutdownObject,
591 transform_activate_DetachObject,
594 static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate)
596 struct transform_activate *object;
597 HRESULT hr;
599 object = heap_alloc_zero(sizeof(*object));
600 if (!object)
601 return E_OUTOFMEMORY;
603 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
605 heap_free(object);
606 return hr;
609 object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl;
610 object->factory = factory;
611 if (object->factory)
612 IClassFactory_AddRef(object->factory);
614 *activate = &object->IMFActivate_iface;
616 return S_OK;
619 HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate)
621 TRACE("%p.\n", activate);
623 return create_transform_activate(NULL, activate);
626 static const WCHAR transform_keyW[] = {'M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\\',
627 'T','r','a','n','s','f','o','r','m','s',0};
628 static const WCHAR categories_keyW[] = {'M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\\',
629 'T','r','a','n','s','f','o','r','m','s','\\',
630 'C','a','t','e','g','o','r','i','e','s',0};
631 static const WCHAR inputtypesW[] = {'I','n','p','u','t','T','y','p','e','s',0};
632 static const WCHAR outputtypesW[] = {'O','u','t','p','u','t','T','y','p','e','s',0};
633 static const WCHAR attributesW[] = {'A','t','t','r','i','b','u','t','e','s',0};
634 static const WCHAR mftflagsW[] = {'M','F','T','F','l','a','g','s',0};
635 static const WCHAR szGUIDFmt[] =
637 '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0',
638 '2','x','%','0','2','x','-','%','0','2','x','%','0','2','x','%','0','2',
639 'x','%','0','2','x','%','0','2','x','%','0','2','x',0
642 static const BYTE guid_conv_table[256] =
644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
645 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
646 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
647 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
648 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
649 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
650 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
653 static WCHAR* GUIDToString(WCHAR *str, REFGUID guid)
655 swprintf(str, 39, szGUIDFmt, guid->Data1, guid->Data2,
656 guid->Data3, guid->Data4[0], guid->Data4[1],
657 guid->Data4[2], guid->Data4[3], guid->Data4[4],
658 guid->Data4[5], guid->Data4[6], guid->Data4[7]);
660 return str;
663 static inline BOOL is_valid_hex(WCHAR c)
665 if (!(((c >= '0') && (c <= '9')) ||
666 ((c >= 'a') && (c <= 'f')) ||
667 ((c >= 'A') && (c <= 'F'))))
668 return FALSE;
669 return TRUE;
672 static BOOL GUIDFromString(LPCWSTR s, GUID *id)
674 int i;
676 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
678 id->Data1 = 0;
679 for (i = 0; i < 8; i++)
681 if (!is_valid_hex(s[i])) return FALSE;
682 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
684 if (s[8]!='-') return FALSE;
686 id->Data2 = 0;
687 for (i = 9; i < 13; i++)
689 if (!is_valid_hex(s[i])) return FALSE;
690 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
692 if (s[13]!='-') return FALSE;
694 id->Data3 = 0;
695 for (i = 14; i < 18; i++)
697 if (!is_valid_hex(s[i])) return FALSE;
698 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
700 if (s[18]!='-') return FALSE;
702 for (i = 19; i < 36; i+=2)
704 if (i == 23)
706 if (s[i]!='-') return FALSE;
707 i++;
709 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
710 id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
713 if (!s[36]) return TRUE;
714 return FALSE;
717 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
719 switch (reason)
721 case DLL_WINE_PREATTACH:
722 return FALSE; /* prefer native version */
723 case DLL_PROCESS_ATTACH:
724 DisableThreadLibraryCalls(instance);
725 break;
728 return TRUE;
731 static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags,
732 UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
733 const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
735 static const WCHAR reg_format[] = {'%','s','\\','%','s',0};
736 HRESULT hr = S_OK;
737 HKEY hclsid = 0;
738 WCHAR buffer[64];
739 DWORD size, ret;
740 WCHAR str[250];
741 UINT8 *blob;
743 GUIDToString(buffer, clsid);
744 swprintf(str, ARRAY_SIZE(str), reg_format, transform_keyW, buffer);
746 if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)))
747 hr = HRESULT_FROM_WIN32(ret);
749 if (SUCCEEDED(hr))
751 size = (lstrlenW(name) + 1) * sizeof(WCHAR);
752 if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)))
753 hr = HRESULT_FROM_WIN32(ret);
756 if (SUCCEEDED(hr) && cinput && input_types)
758 size = cinput * sizeof(MFT_REGISTER_TYPE_INFO);
759 if ((ret = RegSetValueExW(hclsid, inputtypesW, 0, REG_BINARY, (BYTE *)input_types, size)))
760 hr = HRESULT_FROM_WIN32(ret);
763 if (SUCCEEDED(hr) && coutput && output_types)
765 size = coutput * sizeof(MFT_REGISTER_TYPE_INFO);
766 if ((ret = RegSetValueExW(hclsid, outputtypesW, 0, REG_BINARY, (BYTE *)output_types, size)))
767 hr = HRESULT_FROM_WIN32(ret);
770 if (SUCCEEDED(hr) && attributes)
772 if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size)))
774 if ((blob = heap_alloc(size)))
776 if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size)))
778 if ((ret = RegSetValueExW(hclsid, attributesW, 0, REG_BINARY, blob, size)))
779 hr = HRESULT_FROM_WIN32(ret);
781 heap_free(blob);
783 else
784 hr = E_OUTOFMEMORY;
788 if (SUCCEEDED(hr) && flags)
790 if ((ret = RegSetValueExW(hclsid, mftflagsW, 0, REG_DWORD, (BYTE *)&flags, sizeof(flags))))
791 hr = HRESULT_FROM_WIN32(ret);
794 RegCloseKey(hclsid);
795 return hr;
798 static HRESULT register_category(CLSID *clsid, GUID *category)
800 static const WCHAR reg_format[] = {'%','s','\\','%','s','\\','%','s',0};
801 HKEY htmp1;
802 WCHAR guid1[64], guid2[64];
803 WCHAR str[350];
805 GUIDToString(guid1, category);
806 GUIDToString(guid2, clsid);
808 swprintf(str, ARRAY_SIZE(str), reg_format, categories_keyW, guid1, guid2);
810 if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &htmp1))
811 return E_FAIL;
813 RegCloseKey(htmp1);
814 return S_OK;
817 /***********************************************************************
818 * MFTRegister (mfplat.@)
820 HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
821 MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
822 MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
824 HRESULT hr;
826 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category),
827 debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
829 hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes);
830 if(FAILED(hr))
831 ERR("Failed to write register transform\n");
833 if (SUCCEEDED(hr))
834 hr = register_category(&clsid, &category);
836 return hr;
839 static void release_mft_registration(struct mft_registration *mft)
841 if (mft->factory)
842 IClassFactory_Release(mft->factory);
843 heap_free(mft->name);
844 heap_free(mft->input_types);
845 heap_free(mft->output_types);
846 heap_free(mft);
849 static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
850 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
851 const MFT_REGISTER_TYPE_INFO *output_types)
853 struct mft_registration *mft, *cur, *unreg_mft = NULL;
854 HRESULT hr;
856 if (!factory && !clsid)
858 WARN("Can't register without factory or CLSID.\n");
859 return E_FAIL;
862 mft = heap_alloc_zero(sizeof(*mft));
863 if (!mft)
864 return E_OUTOFMEMORY;
866 mft->factory = factory;
867 if (mft->factory)
868 IClassFactory_AddRef(mft->factory);
869 if (clsid)
870 mft->clsid = *clsid;
871 mft->category = *category;
872 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
873 flags |= MFT_ENUM_FLAG_SYNCMFT;
874 mft->flags = flags;
875 mft->local = TRUE;
876 if (FAILED(hr = heap_strdupW(name, &mft->name)))
877 goto failed;
879 if (input_count && input_types)
881 mft->input_types_count = input_count;
882 if (!(mft->input_types = heap_calloc(mft->input_types_count, sizeof(*input_types))))
884 hr = E_OUTOFMEMORY;
885 goto failed;
887 memcpy(mft->input_types, input_types, mft->input_types_count * sizeof(*input_types));
890 if (output_count && output_types)
892 mft->output_types_count = output_count;
893 if (!(mft->output_types = heap_calloc(mft->output_types_count, sizeof(*output_types))))
895 hr = E_OUTOFMEMORY;
896 goto failed;
898 memcpy(mft->output_types, output_types, mft->output_types_count * sizeof(*output_types));
901 EnterCriticalSection(&local_mfts_section);
903 LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct mft_registration, entry)
905 if (cur->factory == factory)
907 unreg_mft = cur;
908 list_remove(&cur->entry);
909 break;
912 list_add_tail(&local_mfts, &mft->entry);
914 LeaveCriticalSection(&local_mfts_section);
916 if (unreg_mft)
917 release_mft_registration(unreg_mft);
919 failed:
920 if (FAILED(hr))
921 release_mft_registration(mft);
923 return hr;
926 HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name, UINT32 flags,
927 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
928 const MFT_REGISTER_TYPE_INFO *output_types)
930 TRACE("%p, %s, %s, %#x, %u, %p, %u, %p.\n", factory, debugstr_guid(category), debugstr_w(name), flags, input_count,
931 input_types, output_count, output_types);
933 return mft_register_local(factory, NULL, category, name, flags, input_count, input_types, output_count, output_types);
936 HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
937 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
938 const MFT_REGISTER_TYPE_INFO *output_types)
940 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
941 input_count, input_types, output_count, output_types);
943 return mft_register_local(NULL, clsid, category, name, flags, input_count, input_types, output_count, output_types);
946 static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
948 struct mft_registration *cur, *cur2;
949 BOOL unregister_all = !factory && !clsid;
950 struct list unreg;
952 list_init(&unreg);
954 EnterCriticalSection(&local_mfts_section);
956 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct mft_registration, entry)
958 if (!unregister_all)
960 if ((factory && cur->factory == factory) || IsEqualCLSID(&cur->clsid, clsid))
962 list_remove(&cur->entry);
963 list_add_tail(&unreg, &cur->entry);
964 break;
967 else
969 list_remove(&cur->entry);
970 list_add_tail(&unreg, &cur->entry);
974 LeaveCriticalSection(&local_mfts_section);
976 if (!unregister_all && list_empty(&unreg))
977 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
979 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct mft_registration, entry)
981 list_remove(&cur->entry);
982 release_mft_registration(cur);
985 return S_OK;
988 HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid)
990 TRACE("%s.\n", debugstr_guid(&clsid));
992 return mft_unregister_local(NULL, &clsid);
995 HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
997 TRACE("%p.\n", factory);
999 return mft_unregister_local(factory, NULL);
1002 MFTIME WINAPI MFGetSystemTime(void)
1004 MFTIME mf;
1006 GetSystemTimeAsFileTime( (FILETIME*)&mf );
1008 return mf;
1011 static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *category, UINT32 flags,
1012 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1013 const MFT_REGISTER_TYPE_INFO *output_type)
1015 BOOL matching = TRUE;
1016 DWORD model;
1017 int i;
1019 if (!IsEqualGUID(category, &mft->category))
1020 return FALSE;
1022 /* Default model is synchronous. */
1023 model = mft->flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE);
1024 if (!model)
1025 model = MFT_ENUM_FLAG_SYNCMFT;
1026 if (!(model & flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1027 return FALSE;
1029 /* These flags should be explicitly enabled. */
1030 if (mft->flags & ~flags & (MFT_ENUM_FLAG_FIELDOFUSE | MFT_ENUM_FLAG_TRANSCODE_ONLY))
1031 return FALSE;
1033 if (flags & MFT_ENUM_FLAG_SORTANDFILTER && !mft->factory && plugin_control
1034 && IMFPluginControl_IsDisabled(plugin_control, MF_Plugin_Type_MFT, &mft->clsid) == S_OK)
1036 return FALSE;
1039 if (input_type)
1041 for (i = 0, matching = FALSE; input_type && i < mft->input_types_count; ++i)
1043 if (!memcmp(&mft->input_types[i], input_type, sizeof(*input_type)))
1045 matching = TRUE;
1046 break;
1051 if (output_type && matching)
1053 for (i = 0, matching = FALSE; i < mft->output_types_count; ++i)
1055 if (!memcmp(&mft->output_types[i], output_type, sizeof(*output_type)))
1057 matching = TRUE;
1058 break;
1063 return matching;
1066 static void mft_get_reg_type_info(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type,
1067 UINT32 *count)
1069 HKEY htransform, hfilter;
1070 DWORD reg_type, size;
1072 *type = NULL;
1073 *count = 0;
1075 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1076 return;
1078 if (RegOpenKeyW(htransform, clsidW, &hfilter))
1080 RegCloseKey(htransform);
1081 return;
1084 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, NULL, &size))
1085 goto out;
1087 if (reg_type != REG_BINARY)
1088 goto out;
1090 if (!size || size % sizeof(**type))
1091 goto out;
1093 if (!(*type = heap_alloc(size)))
1094 goto out;
1096 *count = size / sizeof(**type);
1098 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, (BYTE *)*type, &size))
1100 heap_free(*type);
1101 *type = NULL;
1102 *count = 0;
1105 out:
1106 RegCloseKey(hfilter);
1107 RegCloseKey(htransform);
1110 static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags)
1112 DWORD ret, reg_type, size;
1113 HKEY hroot, hmft;
1115 *flags = 0;
1117 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot))
1118 return;
1120 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1121 RegCloseKey(hroot);
1122 if (ret)
1123 return;
1125 reg_type = 0;
1126 if (!RegQueryValueExW(hmft, nameW, NULL, &reg_type, NULL, &size) && reg_type == REG_DWORD)
1127 RegQueryValueExW(hmft, nameW, NULL, &reg_type, (BYTE *)flags, &size);
1129 RegCloseKey(hmft);
1132 static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, UINT32 flags,
1133 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1134 const MFT_REGISTER_TYPE_INFO *output_type)
1136 struct mft_registration mft, *cur;
1137 HKEY hcategory, hlist;
1138 WCHAR clsidW[64];
1139 DWORD ret, size;
1140 int index = 0;
1142 if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1143 return E_FAIL;
1145 GUIDToString(clsidW, category);
1146 ret = RegOpenKeyW(hcategory, clsidW, &hlist);
1147 RegCloseKey(hcategory);
1148 if (ret)
1149 return E_FAIL;
1151 size = ARRAY_SIZE(clsidW);
1152 while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL))
1154 memset(&mft, 0, sizeof(mft));
1155 mft.category = *category;
1156 if (!GUIDFromString(clsidW, &mft.clsid))
1157 goto next;
1159 mft_get_reg_flags(clsidW, mftflagsW, &mft.flags);
1161 if (output_type)
1162 mft_get_reg_type_info(clsidW, outputtypesW, &mft.output_types, &mft.output_types_count);
1164 if (input_type)
1165 mft_get_reg_type_info(clsidW, inputtypesW, &mft.input_types, &mft.input_types_count);
1167 if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type))
1169 heap_free(mft.input_types);
1170 heap_free(mft.output_types);
1171 goto next;
1174 cur = heap_alloc(sizeof(*cur));
1175 /* Reuse allocated type arrays. */
1176 *cur = mft;
1177 list_add_tail(mfts, &cur->entry);
1179 next:
1180 size = ARRAY_SIZE(clsidW);
1181 index++;
1184 return S_OK;
1187 static BOOL mft_is_preferred(IMFPluginControl *plugin_control, const CLSID *clsid)
1189 CLSID preferred;
1190 WCHAR *selector;
1191 int index = 0;
1193 while (SUCCEEDED(IMFPluginControl_GetPreferredClsidByIndex(plugin_control, MF_Plugin_Type_MFT, index++, &selector,
1194 &preferred)))
1196 CoTaskMemFree(selector);
1198 if (IsEqualGUID(&preferred, clsid))
1199 return TRUE;
1202 return FALSE;
1205 static HRESULT mft_enum(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1206 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1208 IMFPluginControl *plugin_control = NULL;
1209 struct list mfts, mfts_sorted, *result = &mfts;
1210 struct mft_registration *mft, *mft2;
1211 unsigned int obj_count;
1212 HRESULT hr;
1214 *count = 0;
1215 *activate = NULL;
1217 if (!flags)
1218 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER;
1220 /* Synchronous processing is default. */
1221 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1222 flags |= MFT_ENUM_FLAG_SYNCMFT;
1224 if (FAILED(hr = MFGetPluginControl(&plugin_control)))
1226 WARN("Failed to get plugin control instance, hr %#x.\n", hr);
1227 return hr;
1230 list_init(&mfts);
1232 /* Collect from registry */
1233 mft_collect_machine_reg(&mfts, &category, flags, plugin_control, input_type, output_type);
1235 /* Collect locally registered ones. */
1236 if (flags & MFT_ENUM_FLAG_LOCALMFT)
1238 struct mft_registration *local;
1240 EnterCriticalSection(&local_mfts_section);
1242 LIST_FOR_EACH_ENTRY(local, &local_mfts, struct mft_registration, entry)
1244 if (mft_is_type_info_match(local, &category, flags, plugin_control, input_type, output_type))
1246 mft = heap_alloc_zero(sizeof(*mft));
1248 mft->clsid = local->clsid;
1249 mft->factory = local->factory;
1250 if (mft->factory)
1251 IClassFactory_AddRef(mft->factory);
1252 mft->flags = local->flags;
1253 mft->local = local->local;
1255 list_add_tail(&mfts, &mft->entry);
1259 LeaveCriticalSection(&local_mfts_section);
1262 list_init(&mfts_sorted);
1264 if (flags & MFT_ENUM_FLAG_SORTANDFILTER)
1266 /* Local registrations. */
1267 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1269 if (mft->local)
1271 list_remove(&mft->entry);
1272 list_add_tail(&mfts_sorted, &mft->entry);
1276 /* FIXME: Sort by merit value, for the ones that got it. Currently not handled. */
1278 /* Preferred transforms. */
1279 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1281 if (!mft->factory && mft_is_preferred(plugin_control, &mft->clsid))
1283 list_remove(&mft->entry);
1284 list_add_tail(&mfts_sorted, &mft->entry);
1288 /* Append the rest. */
1289 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1291 list_remove(&mft->entry);
1292 list_add_tail(&mfts_sorted, &mft->entry);
1295 result = &mfts_sorted;
1298 IMFPluginControl_Release(plugin_control);
1300 /* Create activation objects from CLSID/IClassFactory. */
1302 obj_count = list_count(result);
1304 if (obj_count)
1306 if (!(*activate = CoTaskMemAlloc(obj_count * sizeof(**activate))))
1307 hr = E_OUTOFMEMORY;
1309 obj_count = 0;
1311 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, result, struct mft_registration, entry)
1313 IMFActivate *mft_activate;
1315 if (*activate)
1317 if (SUCCEEDED(create_transform_activate(mft->factory, &mft_activate)))
1319 (*activate)[obj_count] = mft_activate;
1321 if (mft->local)
1323 IMFActivate_SetUINT32(mft_activate, &MFT_PROCESS_LOCAL_Attribute, 1);
1325 else
1327 if (mft->name)
1328 IMFActivate_SetString(mft_activate, &MFT_FRIENDLY_NAME_Attribute, mft->name);
1329 if (mft->input_types)
1330 IMFActivate_SetBlob(mft_activate, &MFT_INPUT_TYPES_Attributes, (const UINT8 *)mft->input_types,
1331 sizeof(*mft->input_types) * mft->input_types_count);
1332 if (mft->output_types)
1333 IMFActivate_SetBlob(mft_activate, &MFT_OUTPUT_TYPES_Attributes, (const UINT8 *)mft->output_types,
1334 sizeof(*mft->output_types) * mft->output_types_count);
1337 if (!mft->factory)
1338 IMFActivate_SetGUID(mft_activate, &MFT_TRANSFORM_CLSID_Attribute, &mft->clsid);
1340 IMFActivate_SetUINT32(mft_activate, &MF_TRANSFORM_FLAGS_Attribute, mft->flags);
1341 IMFActivate_SetGUID(mft_activate, &MF_TRANSFORM_CATEGORY_Attribute, &mft->category);
1343 obj_count++;
1347 list_remove(&mft->entry);
1348 release_mft_registration(mft);
1352 if (!obj_count)
1354 CoTaskMemFree(*activate);
1355 *activate = NULL;
1357 *count = obj_count;
1359 return hr;
1362 /***********************************************************************
1363 * MFTEnum (mfplat.@)
1365 HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
1366 MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count)
1368 struct mft_registration *mft, *mft2;
1369 unsigned int mft_count;
1370 struct list mfts;
1371 HRESULT hr;
1373 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1374 clsids, count);
1376 if (!clsids || !count)
1377 return E_INVALIDARG;
1379 *count = 0;
1381 list_init(&mfts);
1383 if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
1384 return hr;
1386 mft_count = list_count(&mfts);
1388 if (mft_count)
1390 if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
1391 hr = E_OUTOFMEMORY;
1393 mft_count = 0;
1394 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1396 if (*clsids)
1397 (*clsids)[mft_count++] = mft->clsid;
1398 list_remove(&mft->entry);
1399 release_mft_registration(mft);
1403 if (!mft_count)
1405 CoTaskMemFree(*clsids);
1406 *clsids = NULL;
1408 *count = mft_count;
1410 return hr;
1413 /***********************************************************************
1414 * MFTEnumEx (mfplat.@)
1416 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1417 const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count)
1419 TRACE("%s, %#x, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, activate, count);
1421 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1424 /***********************************************************************
1425 * MFTEnum2 (mfplat.@)
1427 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1428 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1430 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1431 activate, count);
1433 if (attributes)
1434 FIXME("Ignoring attributes.\n");
1436 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1439 /***********************************************************************
1440 * MFTUnregister (mfplat.@)
1442 HRESULT WINAPI MFTUnregister(CLSID clsid)
1444 WCHAR buffer[64], category[MAX_PATH];
1445 HKEY htransform, hcategory, htmp;
1446 DWORD size = MAX_PATH;
1447 DWORD index = 0;
1449 TRACE("(%s)\n", debugstr_guid(&clsid));
1451 GUIDToString(buffer, &clsid);
1453 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1455 RegDeleteKeyW(htransform, buffer);
1456 RegCloseKey(htransform);
1459 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1461 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1463 if (!RegOpenKeyW(hcategory, category, &htmp))
1465 RegDeleteKeyW(htmp, buffer);
1466 RegCloseKey(htmp);
1468 size = MAX_PATH;
1469 index++;
1471 RegCloseKey(hcategory);
1474 return S_OK;
1477 /***********************************************************************
1478 * MFStartup (mfplat.@)
1480 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1482 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1483 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1485 TRACE("%#x, %#x.\n", version, flags);
1487 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1488 return MF_E_BAD_STARTUP_VERSION;
1490 RtwqStartup();
1492 return S_OK;
1495 /***********************************************************************
1496 * MFShutdown (mfplat.@)
1498 HRESULT WINAPI MFShutdown(void)
1500 TRACE("\n");
1502 RtwqShutdown();
1504 return S_OK;
1507 /***********************************************************************
1508 * MFCopyImage (mfplat.@)
1510 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1512 TRACE("%p, %d, %p, %d, %u, %u.\n", dest, deststride, src, srcstride, width, lines);
1514 while (lines--)
1516 memcpy(dest, src, width);
1517 dest += deststride;
1518 src += srcstride;
1521 return S_OK;
1524 struct guid_def
1526 const GUID *guid;
1527 const char *name;
1530 static int __cdecl debug_compare_guid(const void *a, const void *b)
1532 const GUID *guid = a;
1533 const struct guid_def *guid_def = b;
1534 return memcmp(guid, guid_def->guid, sizeof(*guid));
1537 const char *debugstr_attr(const GUID *guid)
1539 static const struct guid_def guid_defs[] =
1541 #define X(g) { &(g), #g }
1542 X(MF_READWRITE_MMCSS_CLASS),
1543 X(MF_TOPONODE_MARKIN_HERE),
1544 X(MF_MT_H264_SUPPORTED_SYNC_FRAME_TYPES),
1545 X(MF_TOPONODE_MARKOUT_HERE),
1546 X(MF_TOPONODE_DECODER),
1547 X(MF_TOPOLOGY_PROJECTSTART),
1548 X(MF_VIDEO_MAX_MB_PER_SEC),
1549 X(MF_TOPOLOGY_PROJECTSTOP),
1550 X(MF_SINK_WRITER_ENCODER_CONFIG),
1551 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1552 X(MF_MT_H264_CAPABILITIES),
1553 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1554 X(MFT_PREFERRED_ENCODER_PROFILE),
1555 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1556 X(MF_MT_MPEG2_PROFILE),
1557 X(MF_MT_VIDEO_PROFILE),
1558 X(MF_MT_DV_AAUX_CTRL_PACK_1),
1559 X(MF_MT_ALPHA_MODE),
1560 X(MF_MT_MPEG2_TIMECODE),
1561 X(MF_PMP_SERVER_CONTEXT),
1562 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1563 X(MF_MEDIA_ENGINE_TRACK_ID),
1564 X(MF_MT_CUSTOM_VIDEO_PRIMARIES),
1565 X(MF_MT_TIMESTAMP_CAN_BE_DTS),
1566 X(MFT_CODEC_MERIT_Attribute),
1567 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1568 X(MF_LOW_LATENCY),
1569 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1570 X(MF_MT_MPEG2_FLAGS),
1571 X(MF_MEDIA_ENGINE_AUDIO_CATEGORY),
1572 X(MF_MT_PIXEL_ASPECT_RATIO),
1573 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1574 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1575 X(MF_MT_REALTIME_CONTENT),
1576 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS),
1577 X(MF_MT_WRAPPED_TYPE),
1578 X(MF_MT_DRM_FLAGS),
1579 X(MF_MT_AVG_BITRATE),
1580 X(MF_MT_DECODER_USE_MAX_RESOLUTION),
1581 X(MF_MT_MAX_LUMINANCE_LEVEL),
1582 X(MFT_CONNECTED_TO_HW_STREAM),
1583 X(MF_SA_D3D_AWARE),
1584 X(MF_MT_MAX_KEYFRAME_SPACING),
1585 X(MFT_TRANSFORM_CLSID_Attribute),
1586 X(MFT_TRANSFORM_CLSID_Attribute),
1587 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1588 X(MF_MT_AM_FORMAT_TYPE),
1589 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1590 X(MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE),
1591 X(MF_MT_H264_MAX_MB_PER_SEC),
1592 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1593 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1594 X(MF_PD_PMPHOST_CONTEXT),
1595 X(MF_PD_APP_CONTEXT),
1596 X(MF_PD_DURATION),
1597 X(MF_PD_TOTAL_FILE_SIZE),
1598 X(MF_PD_AUDIO_ENCODING_BITRATE),
1599 X(MF_PD_VIDEO_ENCODING_BITRATE),
1600 X(MFSampleExtension_TargetGlobalLuminance),
1601 X(MF_PD_MIME_TYPE),
1602 X(MF_MT_H264_SUPPORTED_SLICE_MODES),
1603 X(MF_PD_LAST_MODIFIED_TIME),
1604 X(MF_PD_PLAYBACK_ELEMENT_ID),
1605 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9),
1606 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1607 X(MF_PD_PREFERRED_LANGUAGE),
1608 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1609 X(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID),
1610 X(MF_ACTIVATE_MFT_LOCKED),
1611 X(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT),
1612 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1613 X(MF_MT_FRAME_SIZE),
1614 X(MF_MT_H264_SIMULCAST_SUPPORT),
1615 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1616 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1617 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1618 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1619 X(MF_MT_FRAME_RATE_RANGE_MAX),
1620 X(MF_MT_PALETTE),
1621 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1622 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1623 X(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK),
1624 X(MF_MT_GEOMETRIC_APERTURE),
1625 X(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
1626 X(MF_MT_DV_AAUX_SRC_PACK_1),
1627 X(MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL),
1628 X(MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE),
1629 X(MF_MEDIA_ENGINE_EXTENSION),
1630 X(MF_MT_DEFAULT_STRIDE),
1631 X(MF_MT_ARBITRARY_FORMAT),
1632 X(MF_TRANSFORM_CATEGORY_Attribute),
1633 X(MF_MT_MPEG2_HDCP),
1634 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1635 X(MF_MT_SPATIAL_AUDIO_MAX_DYNAMIC_OBJECTS),
1636 X(MF_MT_DECODER_MAX_DPB_COUNT),
1637 X(MFSampleExtension_ForwardedDecodeUnits),
1638 X(MF_MT_DV_AAUX_CTRL_PACK_0),
1639 X(MF_MT_YUV_MATRIX),
1640 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1641 X(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
1642 X(MF_MT_MAX_FRAME_AVERAGE_LUMINANCE_LEVEL),
1643 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1644 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1645 X(MF_MT_VIDEO_ROTATION),
1646 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1647 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11),
1648 X(MF_MT_USER_DATA),
1649 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID),
1650 X(MF_MT_MIN_MASTERING_LUMINANCE),
1651 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE),
1652 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS),
1653 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID),
1654 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1655 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE),
1656 X(MF_MT_AUDIO_CHANNEL_MASK),
1657 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1658 X(MF_READWRITE_DISABLE_CONVERTERS),
1659 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE),
1660 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS),
1661 X(MF_MT_MINIMUM_DISPLAY_APERTURE),
1662 X(MFSampleExtension_Token),
1663 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1664 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1665 X(MF_TRANSFORM_ASYNC_UNLOCK),
1666 X(MF_DISABLE_FRAME_CORRUPTION_INFO),
1667 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1668 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1669 X(MF_MEDIA_ENGINE_PLAYBACK_VISUAL),
1670 X(MF_MT_VIDEO_CHROMA_SITING),
1671 X(MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY),
1672 X(MFSampleExtension_3DVideo_SampleFormat),
1673 X(MF_MT_H264_RESOLUTION_SCALING),
1674 X(MF_MT_VIDEO_LEVEL),
1675 X(MF_MT_MPEG2_LEVEL),
1676 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1677 X(MF_MT_SAMPLE_SIZE),
1678 X(MF_MT_AAC_PAYLOAD_TYPE),
1679 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1680 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1681 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1682 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1683 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1684 X(MF_TRANSFORM_FLAGS_Attribute),
1685 X(MF_MT_H264_SUPPORTED_RATE_CONTROL_MODES),
1686 X(MF_PD_SAMI_STYLELIST),
1687 X(MF_MT_AUDIO_WMADRC_AVGREF),
1688 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1689 X(MF_SD_LANGUAGE),
1690 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1691 X(MF_SD_PROTECTED),
1692 X(MF_SESSION_TOPOLOADER),
1693 X(MF_SESSION_GLOBAL_TIME),
1694 X(MF_SESSION_QUALITY_MANAGER),
1695 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1696 X(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
1697 X(MF_MT_MPEG_START_TIME_CODE),
1698 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1699 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1700 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1701 X(MF_MT_H264_MAX_CODEC_CONFIG_DELAY),
1702 X(MF_MT_DV_AAUX_SRC_PACK_0),
1703 X(MF_BYTESTREAM_ORIGIN_NAME),
1704 X(MF_BYTESTREAM_CONTENT_TYPE),
1705 X(MF_MT_DEPTH_MEASUREMENT),
1706 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10),
1707 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1708 X(MF_BYTESTREAM_DURATION),
1709 X(MF_SD_SAMI_LANGUAGE),
1710 X(MF_EVENT_OUTPUT_NODE),
1711 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1712 X(MFT_ENUM_ADAPTER_LUID),
1713 X(MF_MT_FRAME_RATE_RANGE_MIN),
1714 X(MF_BYTESTREAM_IFO_FILE_URI),
1715 X(MF_EVENT_TOPOLOGY_STATUS),
1716 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1717 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1718 X(MF_MT_MAJOR_TYPE),
1719 X(MF_MT_IN_BAND_PARAMETER_SET),
1720 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1721 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1722 X(MF_SESSION_SERVER_CONTEXT),
1723 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1724 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1725 X(MF_PD_ADAPTIVE_STREAMING),
1726 X(MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE),
1727 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE),
1728 X(MF_MT_H264_SUPPORTED_USAGES),
1729 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1730 X(MFSampleExtension_Timestamp),
1731 X(MF_TOPONODE_PRIMARYOUTPUT),
1732 X(MF_MT_SUBTYPE),
1733 X(MF_TRANSFORM_ASYNC),
1734 X(MF_TOPONODE_STREAMID),
1735 X(MF_MEDIA_ENGINE_PLAYBACK_HWND),
1736 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1737 X(MF_MT_VIDEO_LIGHTING),
1738 X(MF_SD_MUTUALLY_EXCLUSIVE),
1739 X(MF_SD_STREAM_NAME),
1740 X(MF_MT_DV_VAUX_SRC_PACK),
1741 X(MF_TOPONODE_RATELESS),
1742 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1743 X(MF_TOPONODE_DISABLE_PREROLL),
1744 X(MF_MT_VIDEO_3D_FORMAT),
1745 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1746 X(MF_SOURCE_READER_D3D_MANAGER),
1747 X(MF_SINK_WRITER_D3D_MANAGER),
1748 X(MFSampleExtension_3DVideo),
1749 X(MF_MT_H264_USAGE),
1750 X(MF_MEDIA_ENGINE_EME_CALLBACK),
1751 X(MF_EVENT_SOURCE_FAKE_START),
1752 X(MF_EVENT_SOURCE_PROJECTSTART),
1753 X(MF_EVENT_SOURCE_ACTUAL_START),
1754 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER),
1755 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1756 X(MFT_ENUM_HARDWARE_URL_Attribute),
1757 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1758 X(MF_MT_OUTPUT_BUFFER_NUM),
1759 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1760 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1761 X(MFT_FRIENDLY_NAME_Attribute),
1762 X(MF_MT_FIXED_SIZE_SAMPLES),
1763 X(MFT_SUPPORT_3DVIDEO),
1764 X(MFT_SUPPORT_3DVIDEO),
1765 X(MFT_INPUT_TYPES_Attributes),
1766 X(MF_MT_H264_LAYOUT_PER_STREAM),
1767 X(MF_EVENT_SCRUBSAMPLE_TIME),
1768 X(MF_MT_SPATIAL_AUDIO_MAX_METADATA_ITEMS),
1769 X(MF_MT_MPEG2_ONE_FRAME_PER_PACKET),
1770 X(MF_MT_INTERLACE_MODE),
1771 X(MF_MEDIA_ENGINE_CALLBACK),
1772 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1773 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1774 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1775 X(MF_MT_H264_SVC_CAPABILITIES),
1776 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1777 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_LENGTH),
1778 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_FORMAT_ID),
1779 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1780 X(MF_MT_PAN_SCAN_ENABLED),
1781 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID),
1782 X(MF_MT_DV_VAUX_CTRL_PACK),
1783 X(MFSampleExtension_ForwardedDecodeUnitType),
1784 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1785 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1786 X(MF_MT_SPATIAL_AUDIO_MIN_METADATA_ITEM_OFFSET_SPACING),
1787 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1788 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1789 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1790 X(MF_MT_SOURCE_CONTENT_HINT),
1791 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1792 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1793 X(MF_READWRITE_MMCSS_PRIORITY),
1794 X(MF_MT_VIDEO_3D),
1795 X(MF_EVENT_START_PRESENTATION_TIME),
1796 X(MF_EVENT_SESSIONCAPS),
1797 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1798 X(MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE),
1799 X(MF_EVENT_SESSIONCAPS_DELTA),
1800 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1801 X(MFSampleExtension_DecodeTimestamp),
1802 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE),
1803 X(MF_MT_VIDEO_H264_NO_FMOASO),
1804 X(MF_MT_AVG_BIT_ERROR_RATE),
1805 X(MF_MT_VIDEO_PRIMARIES),
1806 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1807 X(MF_MT_H264_RATE_CONTROL_MODES),
1808 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1809 X(MF_READWRITE_D3D_OPTIONAL),
1810 X(MF_MEDIA_ENGINE_DXGI_MANAGER),
1811 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1812 X(MF_MEDIA_ENGINE_COREWINDOW),
1813 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1814 X(MF_MT_MPEG4_TRACK_TYPE),
1815 X(MF_ACTIVATE_VIDEO_WINDOW),
1816 X(MF_MT_PAN_SCAN_APERTURE),
1817 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1818 X(MF_MT_ORIGINAL_4CC),
1819 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1820 X(MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS),
1821 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE),
1822 X(MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID),
1823 X(MF_MT_MPEG2_CONTENT_PACKET),
1824 X(MFT_PROCESS_LOCAL_Attribute),
1825 X(MFT_PROCESS_LOCAL_Attribute),
1826 X(MF_MT_PAD_CONTROL_FLAGS),
1827 X(MF_MT_VIDEO_NOMINAL_RANGE),
1828 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1829 X(MF_MT_MPEG_SEQUENCE_HEADER),
1830 X(MF_MEDIA_ENGINE_OPM_HWND),
1831 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1832 X(MF_MT_SPATIAL_AUDIO_DATA_PRESENT),
1833 X(MF_MT_FRAME_RATE),
1834 X(MF_TOPONODE_FLUSH),
1835 X(MF_MT_MPEG2_STANDARD),
1836 X(MF_TOPONODE_DRAIN),
1837 X(MF_MT_TRANSFER_FUNCTION),
1838 X(MF_TOPONODE_MEDIASTART),
1839 X(MF_TOPONODE_MEDIASTOP),
1840 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
1841 X(MF_TOPONODE_SOURCE),
1842 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
1843 X(MF_TOPONODE_D3DAWARE),
1844 X(MF_MT_COMPRESSED),
1845 X(MF_TOPONODE_STREAM_DESCRIPTOR),
1846 X(MF_TOPONODE_ERRORCODE),
1847 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
1848 X(MF_EVENT_MFT_CONTEXT),
1849 X(MF_MT_FORWARD_CUSTOM_SEI),
1850 X(MF_TOPONODE_CONNECT_METHOD),
1851 X(MFT_OUTPUT_TYPES_Attributes),
1852 X(MF_MT_IMAGE_LOSS_TOLERANT),
1853 X(MF_SESSION_REMOTE_SOURCE_MODE),
1854 X(MF_MT_DEPTH_VALUE_UNIT),
1855 X(MF_MT_AUDIO_NUM_CHANNELS),
1856 X(MF_MT_ARBITRARY_HEADER),
1857 X(MF_TOPOLOGY_DXVA_MODE),
1858 X(MF_TOPONODE_LOCKED),
1859 X(MF_TOPONODE_WORKQUEUE_ID),
1860 X(MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR),
1861 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
1862 X(MF_TOPONODE_DECRYPTOR),
1863 X(MF_EVENT_DO_THINNING),
1864 X(MF_TOPONODE_DISCARDABLE),
1865 X(MF_TOPOLOGY_HARDWARE_MODE),
1866 X(MF_SOURCE_READER_DISABLE_DXVA),
1867 X(MF_MT_FORWARD_CUSTOM_NALU),
1868 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10),
1869 X(MF_TOPONODE_ERROR_MAJORTYPE),
1870 X(MF_MT_SECURE),
1871 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
1872 X(MF_TOPONODE_ERROR_SUBTYPE),
1873 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
1874 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE),
1875 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
1876 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
1877 #undef X
1879 struct guid_def *ret = NULL;
1881 if (guid)
1882 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
1884 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
1887 const char *debugstr_mf_guid(const GUID *guid)
1889 static const struct guid_def guid_defs[] =
1891 #define X(g) { &(g), #g }
1892 X(MFAudioFormat_ADTS),
1893 X(MFAudioFormat_PCM),
1894 X(MFAudioFormat_PCM_HDCP),
1895 X(MFAudioFormat_Float),
1896 X(MFAudioFormat_DTS),
1897 X(MFAudioFormat_DRM),
1898 X(MFAudioFormat_MSP1),
1899 X(MFAudioFormat_Vorbis),
1900 X(MFAudioFormat_AAC),
1901 X(MFVideoFormat_RGB24),
1902 X(MFVideoFormat_ARGB32),
1903 X(MFVideoFormat_RGB32),
1904 X(MFVideoFormat_RGB565),
1905 X(MFVideoFormat_RGB555),
1906 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
1907 X(MFVideoFormat_A2R10G10B10),
1908 X(MFMediaType_Script),
1909 X(MFMediaType_Image),
1910 X(MFMediaType_HTML),
1911 X(MFMediaType_Binary),
1912 X(MFVideoFormat_MPEG2),
1913 X(MFMediaType_FileTransfer),
1914 X(MFVideoFormat_RGB8),
1915 X(MFAudioFormat_Dolby_AC3),
1916 X(MFVideoFormat_L8),
1917 X(MFAudioFormat_LPCM),
1918 X(MFVideoFormat_420O),
1919 X(MFVideoFormat_AI44),
1920 X(MFVideoFormat_AV1),
1921 X(MFVideoFormat_AYUV),
1922 X(MFVideoFormat_H263),
1923 X(MFVideoFormat_H264),
1924 X(MFVideoFormat_H265),
1925 X(MFVideoFormat_HEVC),
1926 X(MFVideoFormat_HEVC_ES),
1927 X(MFVideoFormat_I420),
1928 X(MFVideoFormat_IYUV),
1929 X(MFVideoFormat_M4S2),
1930 X(MFVideoFormat_MJPG),
1931 X(MFVideoFormat_MP43),
1932 X(MFVideoFormat_MP4S),
1933 X(MFVideoFormat_MP4V),
1934 X(MFVideoFormat_MPG1),
1935 X(MFVideoFormat_MSS1),
1936 X(MFVideoFormat_MSS2),
1937 X(MFVideoFormat_NV11),
1938 X(MFVideoFormat_NV12),
1939 X(MFVideoFormat_ORAW),
1940 X(MFAudioFormat_Opus),
1941 X(MFVideoFormat_D16),
1942 X(MFAudioFormat_MPEG),
1943 X(MFVideoFormat_P010),
1944 X(MFVideoFormat_P016),
1945 X(MFVideoFormat_P210),
1946 X(MFVideoFormat_P216),
1947 X(MFVideoFormat_L16),
1948 X(MFAudioFormat_MP3),
1949 X(MFVideoFormat_UYVY),
1950 X(MFVideoFormat_VP10),
1951 X(MFVideoFormat_VP80),
1952 X(MFVideoFormat_VP90),
1953 X(MFVideoFormat_WMV1),
1954 X(MFVideoFormat_WMV2),
1955 X(MFVideoFormat_WMV3),
1956 X(MFVideoFormat_WVC1),
1957 X(MFVideoFormat_Y210),
1958 X(MFVideoFormat_Y216),
1959 X(MFVideoFormat_Y410),
1960 X(MFVideoFormat_Y416),
1961 X(MFVideoFormat_Y41P),
1962 X(MFVideoFormat_Y41T),
1963 X(MFVideoFormat_Y42T),
1964 X(MFVideoFormat_YUY2),
1965 X(MFVideoFormat_YV12),
1966 X(MFVideoFormat_YVU9),
1967 X(MFVideoFormat_YVYU),
1968 X(MFAudioFormat_WMAudioV8),
1969 X(MFAudioFormat_ALAC),
1970 X(MFAudioFormat_AMR_NB),
1971 X(MFMediaType_Audio),
1972 X(MFAudioFormat_WMAudioV9),
1973 X(MFAudioFormat_AMR_WB),
1974 X(MFAudioFormat_WMAudio_Lossless),
1975 X(MFAudioFormat_AMR_WP),
1976 X(MFAudioFormat_WMASPDIF),
1977 X(MFVideoFormat_DV25),
1978 X(MFVideoFormat_DV50),
1979 X(MFVideoFormat_DVC),
1980 X(MFVideoFormat_DVH1),
1981 X(MFVideoFormat_DVHD),
1982 X(MFVideoFormat_DVSD),
1983 X(MFVideoFormat_DVSL),
1984 X(MFVideoFormat_A16B16G16R16F),
1985 X(MFVideoFormat_v210),
1986 X(MFVideoFormat_v216),
1987 X(MFVideoFormat_v410),
1988 X(MFMediaType_Video),
1989 X(MFAudioFormat_AAC_HDCP),
1990 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
1991 X(MFAudioFormat_Dolby_AC3_HDCP),
1992 X(MFMediaType_Subtitle),
1993 X(MFMediaType_Stream),
1994 X(MFAudioFormat_Dolby_AC3_SPDIF),
1995 X(MFAudioFormat_Float_SpatialObjects),
1996 X(MFMediaType_SAMI),
1997 X(MFAudioFormat_ADTS_HDCP),
1998 X(MFAudioFormat_FLAC),
1999 X(MFAudioFormat_Dolby_DDPlus),
2000 X(MFMediaType_MultiplexedFrames),
2001 X(MFAudioFormat_Base_HDCP),
2002 X(MFVideoFormat_Base_HDCP),
2003 X(MFVideoFormat_H264_HDCP),
2004 X(MFVideoFormat_HEVC_HDCP),
2005 X(MFMediaType_Default),
2006 X(MFMediaType_Protected),
2007 X(MFVideoFormat_H264_ES),
2008 X(MFMediaType_Perception),
2009 #undef X
2011 struct guid_def *ret = NULL;
2013 if (guid)
2014 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2016 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2019 struct event_id
2021 DWORD id;
2022 const char *name;
2025 static int __cdecl debug_event_id(const void *a, const void *b)
2027 const DWORD *id = a;
2028 const struct event_id *event_id = b;
2029 return *id - event_id->id;
2032 static const char *debugstr_eventid(DWORD event)
2034 static const struct event_id
2036 DWORD id;
2037 const char *name;
2039 event_ids[] =
2041 #define X(e) { e, #e }
2042 X(MEUnknown),
2043 X(MEError),
2044 X(MEExtendedType),
2045 X(MENonFatalError),
2046 X(MESessionUnknown),
2047 X(MESessionTopologySet),
2048 X(MESessionTopologiesCleared),
2049 X(MESessionStarted),
2050 X(MESessionPaused),
2051 X(MESessionStopped),
2052 X(MESessionClosed),
2053 X(MESessionEnded),
2054 X(MESessionRateChanged),
2055 X(MESessionScrubSampleComplete),
2056 X(MESessionCapabilitiesChanged),
2057 X(MESessionTopologyStatus),
2058 X(MESessionNotifyPresentationTime),
2059 X(MENewPresentation),
2060 X(MELicenseAcquisitionStart),
2061 X(MELicenseAcquisitionCompleted),
2062 X(MEIndividualizationStart),
2063 X(MEIndividualizationCompleted),
2064 X(MEEnablerProgress),
2065 X(MEEnablerCompleted),
2066 X(MEPolicyError),
2067 X(MEPolicyReport),
2068 X(MEBufferingStarted),
2069 X(MEBufferingStopped),
2070 X(MEConnectStart),
2071 X(MEConnectEnd),
2072 X(MEReconnectStart),
2073 X(MEReconnectEnd),
2074 X(MERendererEvent),
2075 X(MESessionStreamSinkFormatChanged),
2076 X(MESourceUnknown),
2077 X(MESourceStarted),
2078 X(MEStreamStarted),
2079 X(MESourceSeeked),
2080 X(MEStreamSeeked),
2081 X(MENewStream),
2082 X(MEUpdatedStream),
2083 X(MESourceStopped),
2084 X(MEStreamStopped),
2085 X(MESourcePaused),
2086 X(MEStreamPaused),
2087 X(MEEndOfPresentation),
2088 X(MEEndOfStream),
2089 X(MEMediaSample),
2090 X(MEStreamTick),
2091 X(MEStreamThinMode),
2092 X(MEStreamFormatChanged),
2093 X(MESourceRateChanged),
2094 X(MEEndOfPresentationSegment),
2095 X(MESourceCharacteristicsChanged),
2096 X(MESourceRateChangeRequested),
2097 X(MESourceMetadataChanged),
2098 X(MESequencerSourceTopologyUpdated),
2099 X(MESinkUnknown),
2100 X(MEStreamSinkStarted),
2101 X(MEStreamSinkStopped),
2102 X(MEStreamSinkPaused),
2103 X(MEStreamSinkRateChanged),
2104 X(MEStreamSinkRequestSample),
2105 X(MEStreamSinkMarker),
2106 X(MEStreamSinkPrerolled),
2107 X(MEStreamSinkScrubSampleComplete),
2108 X(MEStreamSinkFormatChanged),
2109 X(MEStreamSinkDeviceChanged),
2110 X(MEQualityNotify),
2111 X(MESinkInvalidated),
2112 X(MEAudioSessionNameChanged),
2113 X(MEAudioSessionVolumeChanged),
2114 X(MEAudioSessionDeviceRemoved),
2115 X(MEAudioSessionServerShutdown),
2116 X(MEAudioSessionGroupingParamChanged),
2117 X(MEAudioSessionIconChanged),
2118 X(MEAudioSessionFormatChanged),
2119 X(MEAudioSessionDisconnected),
2120 X(MEAudioSessionExclusiveModeOverride),
2121 X(METrustUnknown),
2122 X(MEPolicyChanged),
2123 X(MEContentProtectionMessage),
2124 X(MEPolicySet),
2125 X(MEWMDRMLicenseBackupCompleted),
2126 X(MEWMDRMLicenseBackupProgress),
2127 X(MEWMDRMLicenseRestoreCompleted),
2128 X(MEWMDRMLicenseRestoreProgress),
2129 X(MEWMDRMLicenseAcquisitionCompleted),
2130 X(MEWMDRMIndividualizationCompleted),
2131 X(MEWMDRMIndividualizationProgress),
2132 X(MEWMDRMProximityCompleted),
2133 X(MEWMDRMLicenseStoreCleaned),
2134 X(MEWMDRMRevocationDownloadCompleted),
2135 X(METransformUnknown),
2136 X(METransformNeedInput),
2137 X(METransformHaveOutput),
2138 X(METransformDrainComplete),
2139 X(METransformMarker),
2140 X(METransformInputStreamStateChanged),
2141 X(MEByteStreamCharacteristicsChanged),
2142 X(MEVideoCaptureDeviceRemoved),
2143 X(MEVideoCaptureDevicePreempted),
2144 X(MEStreamSinkFormatInvalidated),
2145 X(MEEncodingParameters),
2146 X(MEContentProtectionMetadata),
2147 X(MEDeviceThermalStateChanged),
2148 #undef X
2151 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2152 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%u", event);
2155 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2157 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2160 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2162 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2164 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2165 IsEqualGUID(riid, &IID_IUnknown))
2167 *out = iface;
2168 IMFAttributes_AddRef(iface);
2169 return S_OK;
2172 WARN("Unsupported %s.\n", debugstr_guid(riid));
2173 *out = NULL;
2174 return E_NOINTERFACE;
2177 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2179 struct attributes *attributes = impl_from_IMFAttributes(iface);
2180 ULONG refcount = InterlockedIncrement(&attributes->ref);
2182 TRACE("%p, refcount %d.\n", iface, refcount);
2184 return refcount;
2187 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2189 struct attributes *attributes = impl_from_IMFAttributes(iface);
2190 ULONG refcount = InterlockedDecrement(&attributes->ref);
2192 TRACE("%p, refcount %d.\n", iface, refcount);
2194 if (!refcount)
2196 clear_attributes_object(attributes);
2197 heap_free(attributes);
2200 return refcount;
2203 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2205 size_t i;
2207 for (i = 0; i < attributes->count; ++i)
2209 if (IsEqualGUID(key, &attributes->attributes[i].key))
2211 if (index)
2212 *index = i;
2213 return &attributes->attributes[i];
2217 return NULL;
2220 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2222 struct attribute *attribute;
2223 HRESULT hr;
2225 EnterCriticalSection(&attributes->cs);
2227 attribute = attributes_find_item(attributes, key, NULL);
2228 if (attribute)
2230 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.u.punkVal))
2231 hr = PropVariantCopy(value, &attribute->value);
2232 else
2233 hr = MF_E_INVALIDTYPE;
2235 else
2236 hr = MF_E_ATTRIBUTENOTFOUND;
2238 LeaveCriticalSection(&attributes->cs);
2240 return hr;
2243 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2245 struct attribute *attribute;
2246 HRESULT hr;
2248 EnterCriticalSection(&attributes->cs);
2250 if ((attribute = attributes_find_item(attributes, key, NULL)))
2251 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2252 else
2253 hr = MF_E_ATTRIBUTENOTFOUND;
2255 LeaveCriticalSection(&attributes->cs);
2257 return hr;
2260 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2262 struct attribute *attribute;
2263 HRESULT hr = S_OK;
2265 EnterCriticalSection(&attributes->cs);
2267 if ((attribute = attributes_find_item(attributes, key, NULL)))
2269 *type = attribute->value.vt;
2271 else
2272 hr = MF_E_ATTRIBUTENOTFOUND;
2274 LeaveCriticalSection(&attributes->cs);
2276 return hr;
2279 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2281 struct attribute *attribute;
2283 *result = FALSE;
2285 EnterCriticalSection(&attributes->cs);
2287 if ((attribute = attributes_find_item(attributes, key, NULL)))
2289 *result = attribute->value.vt == value->vt &&
2290 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2293 LeaveCriticalSection(&attributes->cs);
2295 return S_OK;
2298 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2299 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2301 IMFAttributes *smaller, *other;
2302 MF_ATTRIBUTE_TYPE type;
2303 HRESULT hr = S_OK;
2304 UINT32 count;
2305 BOOL result;
2306 size_t i;
2308 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2309 return hr;
2311 EnterCriticalSection(&attributes->cs);
2313 result = TRUE;
2315 switch (match_type)
2317 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2318 for (i = 0; i < attributes->count; ++i)
2320 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2321 &attributes->attributes[i].value, &result)))
2322 break;
2323 if (!result)
2324 break;
2326 break;
2327 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2328 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2329 break;
2330 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2331 if (count != attributes->count)
2333 result = FALSE;
2334 break;
2336 for (i = 0; i < count; ++i)
2338 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2339 &attributes->attributes[i].value, &result)))
2340 break;
2341 if (!result)
2342 break;
2344 break;
2345 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2346 for (i = 0; i < attributes->count; ++i)
2348 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2349 continue;
2351 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2352 &attributes->attributes[i].value, &result)))
2353 break;
2355 if (!result)
2356 break;
2358 break;
2359 case MF_ATTRIBUTES_MATCH_SMALLER:
2360 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2361 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2362 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2363 break;
2364 default:
2365 WARN("Unknown match type %d.\n", match_type);
2366 hr = E_INVALIDARG;
2369 LeaveCriticalSection(&attributes->cs);
2371 if (SUCCEEDED(hr))
2372 *ret = result;
2374 return hr;
2377 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2379 PROPVARIANT attrval;
2380 HRESULT hr;
2382 PropVariantInit(&attrval);
2383 attrval.vt = VT_UI4;
2384 hr = attributes_get_item(attributes, key, &attrval);
2385 if (SUCCEEDED(hr))
2386 *value = attrval.u.ulVal;
2388 return hr;
2391 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2393 PROPVARIANT attrval;
2394 HRESULT hr;
2396 PropVariantInit(&attrval);
2397 attrval.vt = VT_UI8;
2398 hr = attributes_get_item(attributes, key, &attrval);
2399 if (SUCCEEDED(hr))
2400 *value = attrval.u.uhVal.QuadPart;
2402 return hr;
2405 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2407 PROPVARIANT attrval;
2408 HRESULT hr;
2410 PropVariantInit(&attrval);
2411 attrval.vt = VT_R8;
2412 hr = attributes_get_item(attributes, key, &attrval);
2413 if (SUCCEEDED(hr))
2414 *value = attrval.u.dblVal;
2416 return hr;
2419 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
2421 struct attribute *attribute;
2422 HRESULT hr = S_OK;
2424 EnterCriticalSection(&attributes->cs);
2426 attribute = attributes_find_item(attributes, key, NULL);
2427 if (attribute)
2429 if (attribute->value.vt == MF_ATTRIBUTE_GUID)
2430 *value = *attribute->value.u.puuid;
2431 else
2432 hr = MF_E_INVALIDTYPE;
2434 else
2435 hr = MF_E_ATTRIBUTENOTFOUND;
2437 LeaveCriticalSection(&attributes->cs);
2439 return hr;
2442 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2444 struct attribute *attribute;
2445 HRESULT hr = S_OK;
2447 EnterCriticalSection(&attributes->cs);
2449 attribute = attributes_find_item(attributes, key, NULL);
2450 if (attribute)
2452 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2453 *length = lstrlenW(attribute->value.u.pwszVal);
2454 else
2455 hr = MF_E_INVALIDTYPE;
2457 else
2458 hr = MF_E_ATTRIBUTENOTFOUND;
2460 LeaveCriticalSection(&attributes->cs);
2462 return hr;
2465 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2466 UINT32 size, UINT32 *length)
2468 struct attribute *attribute;
2469 HRESULT hr = S_OK;
2471 EnterCriticalSection(&attributes->cs);
2473 attribute = attributes_find_item(attributes, key, NULL);
2474 if (attribute)
2476 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2478 int len = lstrlenW(attribute->value.u.pwszVal);
2480 if (length)
2481 *length = len;
2483 if (size <= len)
2484 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2485 else
2486 memcpy(value, attribute->value.u.pwszVal, (len + 1) * sizeof(WCHAR));
2488 else
2489 hr = MF_E_INVALIDTYPE;
2491 else
2492 hr = MF_E_ATTRIBUTENOTFOUND;
2494 LeaveCriticalSection(&attributes->cs);
2496 return hr;
2499 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2501 PROPVARIANT attrval;
2502 HRESULT hr;
2504 PropVariantInit(&attrval);
2505 attrval.vt = VT_LPWSTR;
2506 hr = attributes_get_item(attributes, key, &attrval);
2507 if (SUCCEEDED(hr))
2509 *value = attrval.u.pwszVal;
2510 *length = lstrlenW(*value);
2513 return hr;
2516 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2518 struct attribute *attribute;
2519 HRESULT hr = S_OK;
2521 EnterCriticalSection(&attributes->cs);
2523 attribute = attributes_find_item(attributes, key, NULL);
2524 if (attribute)
2526 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2527 *size = attribute->value.u.caub.cElems;
2528 else
2529 hr = MF_E_INVALIDTYPE;
2531 else
2532 hr = MF_E_ATTRIBUTENOTFOUND;
2534 LeaveCriticalSection(&attributes->cs);
2536 return hr;
2539 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2541 struct attribute *attribute;
2542 HRESULT hr;
2544 EnterCriticalSection(&attributes->cs);
2546 attribute = attributes_find_item(attributes, key, NULL);
2547 if (attribute)
2549 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2551 UINT32 size = attribute->value.u.caub.cElems;
2553 if (bufsize >= size)
2554 hr = PropVariantToBuffer(&attribute->value, buf, size);
2555 else
2556 hr = E_NOT_SUFFICIENT_BUFFER;
2558 if (blobsize)
2559 *blobsize = size;
2561 else
2562 hr = MF_E_INVALIDTYPE;
2564 else
2565 hr = MF_E_ATTRIBUTENOTFOUND;
2567 LeaveCriticalSection(&attributes->cs);
2569 return hr;
2572 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2574 PROPVARIANT attrval;
2575 HRESULT hr;
2577 attrval.vt = VT_VECTOR | VT_UI1;
2578 hr = attributes_get_item(attributes, key, &attrval);
2579 if (SUCCEEDED(hr))
2581 *buf = attrval.u.caub.pElems;
2582 *size = attrval.u.caub.cElems;
2585 return hr;
2588 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2590 PROPVARIANT attrval;
2591 HRESULT hr;
2593 PropVariantInit(&attrval);
2594 attrval.vt = VT_UNKNOWN;
2595 hr = attributes_get_item(attributes, key, &attrval);
2596 if (SUCCEEDED(hr))
2597 hr = IUnknown_QueryInterface(attrval.u.punkVal, riid, out);
2598 PropVariantClear(&attrval);
2599 return hr;
2602 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2604 struct attribute *attribute;
2606 EnterCriticalSection(&attributes->cs);
2608 attribute = attributes_find_item(attributes, key, NULL);
2609 if (!attribute)
2611 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2612 sizeof(*attributes->attributes)))
2614 LeaveCriticalSection(&attributes->cs);
2615 return E_OUTOFMEMORY;
2617 attributes->attributes[attributes->count].key = *key;
2618 attribute = &attributes->attributes[attributes->count++];
2620 else
2621 PropVariantClear(&attribute->value);
2623 PropVariantCopy(&attribute->value, value);
2625 LeaveCriticalSection(&attributes->cs);
2627 return S_OK;
2630 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2632 PROPVARIANT empty;
2634 switch (value->vt)
2636 case MF_ATTRIBUTE_UINT32:
2637 case MF_ATTRIBUTE_UINT64:
2638 case MF_ATTRIBUTE_DOUBLE:
2639 case MF_ATTRIBUTE_GUID:
2640 case MF_ATTRIBUTE_STRING:
2641 case MF_ATTRIBUTE_BLOB:
2642 case MF_ATTRIBUTE_IUNKNOWN:
2643 return attributes_set_item(attributes, key, value);
2644 default:
2645 PropVariantInit(&empty);
2646 attributes_set_item(attributes, key, &empty);
2647 return MF_E_INVALIDTYPE;
2651 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2653 struct attribute *attribute;
2654 size_t index = 0;
2656 EnterCriticalSection(&attributes->cs);
2658 if ((attribute = attributes_find_item(attributes, key, &index)))
2660 size_t count;
2662 PropVariantClear(&attribute->value);
2664 attributes->count--;
2665 count = attributes->count - index;
2666 if (count)
2667 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2670 LeaveCriticalSection(&attributes->cs);
2672 return S_OK;
2675 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2677 EnterCriticalSection(&attributes->cs);
2679 while (attributes->count)
2681 PropVariantClear(&attributes->attributes[--attributes->count].value);
2683 heap_free(attributes->attributes);
2684 attributes->attributes = NULL;
2685 attributes->capacity = 0;
2687 LeaveCriticalSection(&attributes->cs);
2689 return S_OK;
2692 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2694 PROPVARIANT attrval;
2696 attrval.vt = VT_UI4;
2697 attrval.u.ulVal = value;
2698 return attributes_set_item(attributes, key, &attrval);
2701 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2703 PROPVARIANT attrval;
2705 attrval.vt = VT_UI8;
2706 attrval.u.uhVal.QuadPart = value;
2707 return attributes_set_item(attributes, key, &attrval);
2710 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2712 PROPVARIANT attrval;
2714 attrval.vt = VT_R8;
2715 attrval.u.dblVal = value;
2716 return attributes_set_item(attributes, key, &attrval);
2719 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2721 PROPVARIANT attrval;
2723 attrval.vt = VT_CLSID;
2724 attrval.u.puuid = (CLSID *)value;
2725 return attributes_set_item(attributes, key, &attrval);
2728 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2730 PROPVARIANT attrval;
2732 attrval.vt = VT_LPWSTR;
2733 attrval.u.pwszVal = (WCHAR *)value;
2734 return attributes_set_item(attributes, key, &attrval);
2737 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2739 PROPVARIANT attrval;
2741 attrval.vt = VT_VECTOR | VT_UI1;
2742 attrval.u.caub.cElems = size;
2743 attrval.u.caub.pElems = (UINT8 *)buf;
2744 return attributes_set_item(attributes, key, &attrval);
2747 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2749 PROPVARIANT attrval;
2751 attrval.vt = VT_UNKNOWN;
2752 attrval.u.punkVal = unknown;
2753 return attributes_set_item(attributes, key, &attrval);
2756 HRESULT attributes_LockStore(struct attributes *attributes)
2758 EnterCriticalSection(&attributes->cs);
2760 return S_OK;
2763 HRESULT attributes_UnlockStore(struct attributes *attributes)
2765 LeaveCriticalSection(&attributes->cs);
2767 return S_OK;
2770 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2772 EnterCriticalSection(&attributes->cs);
2773 *count = attributes->count;
2774 LeaveCriticalSection(&attributes->cs);
2776 return S_OK;
2779 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2781 HRESULT hr = S_OK;
2783 EnterCriticalSection(&attributes->cs);
2785 if (index < attributes->count)
2787 *key = attributes->attributes[index].key;
2788 if (value)
2789 PropVariantCopy(value, &attributes->attributes[index].value);
2791 else
2792 hr = E_INVALIDARG;
2794 LeaveCriticalSection(&attributes->cs);
2796 return hr;
2799 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2801 HRESULT hr = S_OK;
2802 size_t i;
2804 EnterCriticalSection(&attributes->cs);
2806 IMFAttributes_LockStore(dest);
2808 IMFAttributes_DeleteAllItems(dest);
2810 for (i = 0; i < attributes->count; ++i)
2812 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2813 if (FAILED(hr))
2814 break;
2817 IMFAttributes_UnlockStore(dest);
2819 LeaveCriticalSection(&attributes->cs);
2821 return hr;
2824 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2826 struct attributes *attributes = impl_from_IMFAttributes(iface);
2828 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2830 return attributes_GetItem(attributes, key, value);
2833 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2835 struct attributes *attributes = impl_from_IMFAttributes(iface);
2837 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
2839 return attributes_GetItemType(attributes, key, type);
2842 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
2844 struct attributes *attributes = impl_from_IMFAttributes(iface);
2846 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
2848 return attributes_CompareItem(attributes, key, value, result);
2851 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2852 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2854 struct attributes *attributes = impl_from_IMFAttributes(iface);
2856 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
2858 return attributes_Compare(attributes, theirs, match_type, ret);
2861 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2863 struct attributes *attributes = impl_from_IMFAttributes(iface);
2865 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2867 return attributes_GetUINT32(attributes, key, value);
2870 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2872 struct attributes *attributes = impl_from_IMFAttributes(iface);
2874 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2876 return attributes_GetUINT64(attributes, key, value);
2879 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2881 struct attributes *attributes = impl_from_IMFAttributes(iface);
2883 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2885 return attributes_GetDouble(attributes, key, value);
2888 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2890 struct attributes *attributes = impl_from_IMFAttributes(iface);
2892 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2894 return attributes_GetGUID(attributes, key, value);
2897 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
2899 struct attributes *attributes = impl_from_IMFAttributes(iface);
2901 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
2903 return attributes_GetStringLength(attributes, key, length);
2906 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2907 UINT32 size, UINT32 *length)
2909 struct attributes *attributes = impl_from_IMFAttributes(iface);
2911 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
2913 return attributes_GetString(attributes, key, value, size, length);
2916 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
2918 struct attributes *attributes = impl_from_IMFAttributes(iface);
2920 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
2922 return attributes_GetAllocatedString(attributes, key, value, length);
2925 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2927 struct attributes *attributes = impl_from_IMFAttributes(iface);
2929 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
2931 return attributes_GetBlobSize(attributes, key, size);
2934 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2935 UINT32 bufsize, UINT32 *blobsize)
2937 struct attributes *attributes = impl_from_IMFAttributes(iface);
2939 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
2941 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
2944 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
2946 struct attributes *attributes = impl_from_IMFAttributes(iface);
2948 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
2950 return attributes_GetAllocatedBlob(attributes, key, buf, size);
2953 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2955 struct attributes *attributes = impl_from_IMFAttributes(iface);
2957 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
2959 return attributes_GetUnknown(attributes, key, riid, out);
2962 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2964 struct attributes *attributes = impl_from_IMFAttributes(iface);
2966 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
2968 return attributes_SetItem(attributes, key, value);
2971 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2973 struct attributes *attributes = impl_from_IMFAttributes(iface);
2975 TRACE("%p, %s.\n", iface, debugstr_attr(key));
2977 return attributes_DeleteItem(attributes, key);
2980 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
2982 struct attributes *attributes = impl_from_IMFAttributes(iface);
2984 TRACE("%p.\n", iface);
2986 return attributes_DeleteAllItems(attributes);
2989 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2991 struct attributes *attributes = impl_from_IMFAttributes(iface);
2993 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
2995 return attributes_SetUINT32(attributes, key, value);
2998 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
3000 struct attributes *attributes = impl_from_IMFAttributes(iface);
3002 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
3004 return attributes_SetUINT64(attributes, key, value);
3007 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
3009 struct attributes *attributes = impl_from_IMFAttributes(iface);
3011 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
3013 return attributes_SetDouble(attributes, key, value);
3016 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
3018 struct attributes *attributes = impl_from_IMFAttributes(iface);
3020 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
3022 return attributes_SetGUID(attributes, key, value);
3025 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
3027 struct attributes *attributes = impl_from_IMFAttributes(iface);
3029 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
3031 return attributes_SetString(attributes, key, value);
3034 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
3036 struct attributes *attributes = impl_from_IMFAttributes(iface);
3038 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
3040 return attributes_SetBlob(attributes, key, buf, size);
3043 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
3045 struct attributes *attributes = impl_from_IMFAttributes(iface);
3047 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
3049 return attributes_SetUnknown(attributes, key, unknown);
3052 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
3054 struct attributes *attributes = impl_from_IMFAttributes(iface);
3056 TRACE("%p.\n", iface);
3058 return attributes_LockStore(attributes);
3061 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
3063 struct attributes *attributes = impl_from_IMFAttributes(iface);
3065 TRACE("%p.\n", iface);
3067 return attributes_UnlockStore(attributes);
3070 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
3072 struct attributes *attributes = impl_from_IMFAttributes(iface);
3074 TRACE("%p, %p.\n", iface, count);
3076 return attributes_GetCount(attributes, count);
3079 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
3081 struct attributes *attributes = impl_from_IMFAttributes(iface);
3083 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
3085 return attributes_GetItemByIndex(attributes, index, key, value);
3088 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
3090 struct attributes *attributes = impl_from_IMFAttributes(iface);
3092 TRACE("%p, %p.\n", iface, dest);
3094 return attributes_CopyAllItems(attributes, dest);
3097 static const IMFAttributesVtbl mfattributes_vtbl =
3099 mfattributes_QueryInterface,
3100 mfattributes_AddRef,
3101 mfattributes_Release,
3102 mfattributes_GetItem,
3103 mfattributes_GetItemType,
3104 mfattributes_CompareItem,
3105 mfattributes_Compare,
3106 mfattributes_GetUINT32,
3107 mfattributes_GetUINT64,
3108 mfattributes_GetDouble,
3109 mfattributes_GetGUID,
3110 mfattributes_GetStringLength,
3111 mfattributes_GetString,
3112 mfattributes_GetAllocatedString,
3113 mfattributes_GetBlobSize,
3114 mfattributes_GetBlob,
3115 mfattributes_GetAllocatedBlob,
3116 mfattributes_GetUnknown,
3117 mfattributes_SetItem,
3118 mfattributes_DeleteItem,
3119 mfattributes_DeleteAllItems,
3120 mfattributes_SetUINT32,
3121 mfattributes_SetUINT64,
3122 mfattributes_SetDouble,
3123 mfattributes_SetGUID,
3124 mfattributes_SetString,
3125 mfattributes_SetBlob,
3126 mfattributes_SetUnknown,
3127 mfattributes_LockStore,
3128 mfattributes_UnlockStore,
3129 mfattributes_GetCount,
3130 mfattributes_GetItemByIndex,
3131 mfattributes_CopyAllItems
3134 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3136 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3137 object->ref = 1;
3138 InitializeCriticalSection(&object->cs);
3140 object->attributes = NULL;
3141 object->count = 0;
3142 object->capacity = 0;
3143 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3144 sizeof(*object->attributes)))
3146 DeleteCriticalSection(&object->cs);
3147 return E_OUTOFMEMORY;
3150 return S_OK;
3153 void clear_attributes_object(struct attributes *object)
3155 size_t i;
3157 for (i = 0; i < object->count; i++)
3158 PropVariantClear(&object->attributes[i].value);
3159 heap_free(object->attributes);
3161 DeleteCriticalSection(&object->cs);
3164 /***********************************************************************
3165 * MFCreateAttributes (mfplat.@)
3167 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3169 struct attributes *object;
3170 HRESULT hr;
3172 TRACE("%p, %d\n", attributes, size);
3174 object = heap_alloc_zero(sizeof(*object));
3175 if (!object)
3176 return E_OUTOFMEMORY;
3178 if (FAILED(hr = init_attributes_object(object, size)))
3180 heap_free(object);
3181 return hr;
3183 *attributes = &object->IMFAttributes_iface;
3185 return S_OK;
3188 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3190 struct attributes_store_header
3192 DWORD magic;
3193 UINT32 count;
3196 struct attributes_store_item
3198 GUID key;
3199 QWORD type;
3200 union
3202 double f;
3203 UINT32 i32;
3204 UINT64 i64;
3205 struct
3207 DWORD size;
3208 DWORD offset;
3209 } subheader;
3210 } u;
3213 /***********************************************************************
3214 * MFGetAttributesAsBlobSize (mfplat.@)
3216 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3218 unsigned int i, count, length;
3219 HRESULT hr;
3220 GUID key;
3222 TRACE("%p, %p.\n", attributes, size);
3224 IMFAttributes_LockStore(attributes);
3226 hr = IMFAttributes_GetCount(attributes, &count);
3228 *size = sizeof(struct attributes_store_header);
3230 for (i = 0; i < count; ++i)
3232 MF_ATTRIBUTE_TYPE type;
3234 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3235 if (FAILED(hr))
3236 break;
3238 *size += sizeof(struct attributes_store_item);
3240 IMFAttributes_GetItemType(attributes, &key, &type);
3242 switch (type)
3244 case MF_ATTRIBUTE_GUID:
3245 *size += sizeof(GUID);
3246 break;
3247 case MF_ATTRIBUTE_STRING:
3248 IMFAttributes_GetStringLength(attributes, &key, &length);
3249 *size += (length + 1) * sizeof(WCHAR);
3250 break;
3251 case MF_ATTRIBUTE_BLOB:
3252 IMFAttributes_GetBlobSize(attributes, &key, &length);
3253 *size += length;
3254 break;
3255 case MF_ATTRIBUTE_UINT32:
3256 case MF_ATTRIBUTE_UINT64:
3257 case MF_ATTRIBUTE_DOUBLE:
3258 case MF_ATTRIBUTE_IUNKNOWN:
3259 default:
3264 IMFAttributes_UnlockStore(attributes);
3266 return hr;
3269 struct attr_serialize_context
3271 UINT8 *buffer;
3272 UINT8 *ptr;
3273 UINT32 size;
3276 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3278 memcpy(context->ptr, value, size);
3279 context->ptr += size;
3282 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3283 const void *value)
3285 switch (item->type)
3287 case MF_ATTRIBUTE_UINT32:
3288 case MF_ATTRIBUTE_UINT64:
3289 case MF_ATTRIBUTE_DOUBLE:
3290 attributes_serialize_write(context, item, sizeof(*item));
3291 break;
3292 case MF_ATTRIBUTE_GUID:
3293 case MF_ATTRIBUTE_STRING:
3294 case MF_ATTRIBUTE_BLOB:
3295 item->u.subheader.offset = context->size - item->u.subheader.size;
3296 attributes_serialize_write(context, item, sizeof(*item));
3297 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3298 context->size -= item->u.subheader.size;
3299 break;
3300 default:
3301 return FALSE;
3304 return TRUE;
3307 /***********************************************************************
3308 * MFGetAttributesAsBlob (mfplat.@)
3310 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3312 struct attributes_store_header header;
3313 struct attr_serialize_context context;
3314 unsigned int required_size, i;
3315 PROPVARIANT value;
3316 UINT32 count;
3317 HRESULT hr;
3319 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3321 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3322 return hr;
3324 if (required_size > size)
3325 return MF_E_BUFFERTOOSMALL;
3327 context.buffer = buffer;
3328 context.ptr = buffer;
3329 context.size = required_size;
3331 IMFAttributes_LockStore(attributes);
3333 header.magic = ATTRIBUTES_STORE_MAGIC;
3334 header.count = 0; /* Will be updated later */
3335 IMFAttributes_GetCount(attributes, &count);
3337 attributes_serialize_write(&context, &header, sizeof(header));
3339 for (i = 0; i < count; ++i)
3341 struct attributes_store_item item;
3342 const void *data = NULL;
3344 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3345 if (FAILED(hr))
3346 break;
3348 item.type = value.vt;
3350 switch (value.vt)
3352 case MF_ATTRIBUTE_UINT32:
3353 case MF_ATTRIBUTE_UINT64:
3354 item.u.i64 = value.u.uhVal.QuadPart;
3355 break;
3356 case MF_ATTRIBUTE_DOUBLE:
3357 item.u.f = value.u.dblVal;
3358 break;
3359 case MF_ATTRIBUTE_GUID:
3360 item.u.subheader.size = sizeof(*value.u.puuid);
3361 data = value.u.puuid;
3362 break;
3363 case MF_ATTRIBUTE_STRING:
3364 item.u.subheader.size = (lstrlenW(value.u.pwszVal) + 1) * sizeof(WCHAR);
3365 data = value.u.pwszVal;
3366 break;
3367 case MF_ATTRIBUTE_BLOB:
3368 item.u.subheader.size = value.u.caub.cElems;
3369 data = value.u.caub.pElems;
3370 break;
3371 case MF_ATTRIBUTE_IUNKNOWN:
3372 break;
3373 default:
3374 WARN("Unknown attribute type %#x.\n", value.vt);
3377 if (attributes_serialize_write_item(&context, &item, data))
3378 header.count++;
3380 PropVariantClear(&value);
3383 memcpy(context.buffer, &header, sizeof(header));
3385 IMFAttributes_UnlockStore(attributes);
3387 return S_OK;
3390 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3392 if (context->size < (context->ptr - context->buffer) + size)
3393 return E_INVALIDARG;
3395 memcpy(value, context->ptr, size);
3396 context->ptr += size;
3398 return S_OK;
3401 /***********************************************************************
3402 * MFInitAttributesFromBlob (mfplat.@)
3404 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3406 struct attr_serialize_context context;
3407 struct attributes_store_header header;
3408 struct attributes_store_item item;
3409 IMFAttributes *attributes;
3410 unsigned int i;
3411 HRESULT hr;
3413 TRACE("%p, %p, %u.\n", dest, buffer, size);
3415 context.buffer = (UINT8 *)buffer;
3416 context.ptr = (UINT8 *)buffer;
3417 context.size = size;
3419 /* Validate buffer structure. */
3420 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3421 return hr;
3423 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3424 return E_UNEXPECTED;
3426 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3427 return hr;
3429 for (i = 0; i < header.count; ++i)
3431 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3432 break;
3434 hr = E_UNEXPECTED;
3436 switch (item.type)
3438 case MF_ATTRIBUTE_UINT32:
3439 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3440 break;
3441 case MF_ATTRIBUTE_UINT64:
3442 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3443 break;
3444 case MF_ATTRIBUTE_DOUBLE:
3445 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3446 break;
3447 case MF_ATTRIBUTE_GUID:
3448 if (item.u.subheader.size == sizeof(GUID) &&
3449 item.u.subheader.offset + item.u.subheader.size <= context.size)
3451 hr = IMFAttributes_SetGUID(attributes, &item.key,
3452 (const GUID *)(context.buffer + item.u.subheader.offset));
3454 break;
3455 case MF_ATTRIBUTE_STRING:
3456 if (item.u.subheader.size >= sizeof(WCHAR) &&
3457 item.u.subheader.offset + item.u.subheader.size <= context.size)
3459 hr = IMFAttributes_SetString(attributes, &item.key,
3460 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3462 break;
3463 case MF_ATTRIBUTE_BLOB:
3464 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3466 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3467 item.u.subheader.size);
3469 break;
3470 default:
3474 if (FAILED(hr))
3475 break;
3478 if (SUCCEEDED(hr))
3480 IMFAttributes_DeleteAllItems(dest);
3481 hr = IMFAttributes_CopyAllItems(attributes, dest);
3484 IMFAttributes_Release(attributes);
3486 return hr;
3489 typedef struct bytestream
3491 struct attributes attributes;
3492 IMFByteStream IMFByteStream_iface;
3493 IMFGetService IMFGetService_iface;
3494 IRtwqAsyncCallback read_callback;
3495 IRtwqAsyncCallback write_callback;
3496 IStream *stream;
3497 HANDLE hfile;
3498 QWORD position;
3499 DWORD capabilities;
3500 struct list pending;
3501 CRITICAL_SECTION cs;
3502 } mfbytestream;
3504 static inline mfbytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3506 return CONTAINING_RECORD(iface, mfbytestream, IMFByteStream_iface);
3509 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3511 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3514 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3516 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3519 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3521 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3524 enum async_stream_op_type
3526 ASYNC_STREAM_OP_READ,
3527 ASYNC_STREAM_OP_WRITE,
3530 struct async_stream_op
3532 IUnknown IUnknown_iface;
3533 LONG refcount;
3534 union
3536 const BYTE *src;
3537 BYTE *dest;
3538 } u;
3539 QWORD position;
3540 ULONG requested_length;
3541 ULONG actual_length;
3542 IMFAsyncResult *caller;
3543 struct list entry;
3544 enum async_stream_op_type type;
3547 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3549 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3552 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3554 if (IsEqualIID(riid, &IID_IUnknown))
3556 *obj = iface;
3557 IUnknown_AddRef(iface);
3558 return S_OK;
3561 WARN("Unsupported %s.\n", debugstr_guid(riid));
3562 *obj = NULL;
3563 return E_NOINTERFACE;
3566 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3568 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3569 ULONG refcount = InterlockedIncrement(&op->refcount);
3571 TRACE("%p, refcount %d.\n", iface, refcount);
3573 return refcount;
3576 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3578 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3579 ULONG refcount = InterlockedDecrement(&op->refcount);
3581 TRACE("%p, refcount %d.\n", iface, refcount);
3583 if (!refcount)
3585 if (op->caller)
3586 IMFAsyncResult_Release(op->caller);
3587 heap_free(op);
3590 return refcount;
3593 static const IUnknownVtbl async_stream_op_vtbl =
3595 async_stream_op_QueryInterface,
3596 async_stream_op_AddRef,
3597 async_stream_op_Release,
3600 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3601 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3603 struct async_stream_op *op;
3604 IRtwqAsyncResult *request;
3605 HRESULT hr;
3607 op = heap_alloc(sizeof(*op));
3608 if (!op)
3609 return E_OUTOFMEMORY;
3611 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3612 op->refcount = 1;
3613 op->u.src = data;
3614 op->position = stream->position;
3615 op->requested_length = size;
3616 op->type = type;
3617 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3618 (IRtwqAsyncResult **)&op->caller)))
3620 goto failed;
3623 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3624 &stream->write_callback, NULL, &request)))
3625 goto failed;
3627 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, request);
3628 IRtwqAsyncResult_Release(request);
3630 failed:
3631 IUnknown_Release(&op->IUnknown_iface);
3632 return hr;
3635 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3636 IMFAsyncResult *result, ULONG *actual_length)
3638 struct async_stream_op *op = NULL, *cur;
3639 HRESULT hr;
3641 EnterCriticalSection(&stream->cs);
3642 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3644 if (cur->caller == result && cur->type == type)
3646 op = cur;
3647 list_remove(&cur->entry);
3648 break;
3651 LeaveCriticalSection(&stream->cs);
3653 if (!op)
3654 return E_INVALIDARG;
3656 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3657 *actual_length = op->actual_length;
3659 IUnknown_Release(&op->IUnknown_iface);
3661 return hr;
3664 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3666 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3667 IsEqualIID(riid, &IID_IUnknown))
3669 *obj = iface;
3670 IRtwqAsyncCallback_AddRef(iface);
3671 return S_OK;
3674 WARN("Unsupported %s.\n", debugstr_guid(riid));
3675 *obj = NULL;
3676 return E_NOINTERFACE;
3679 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3681 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3682 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3685 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3687 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3688 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3691 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3693 return E_NOTIMPL;
3696 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3698 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3699 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3702 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3704 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3705 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3708 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3710 struct bytestream *stream = impl_from_IMFByteStream(iface);
3712 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3714 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3715 IsEqualIID(riid, &IID_IUnknown))
3717 *out = &stream->IMFByteStream_iface;
3719 else if (IsEqualIID(riid, &IID_IMFAttributes))
3721 *out = &stream->attributes.IMFAttributes_iface;
3723 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3725 *out = &stream->IMFGetService_iface;
3727 else
3729 WARN("Unsupported %s.\n", debugstr_guid(riid));
3730 *out = NULL;
3731 return E_NOINTERFACE;
3734 IUnknown_AddRef((IUnknown*)*out);
3735 return S_OK;
3738 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3740 struct bytestream *stream = impl_from_IMFByteStream(iface);
3741 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3743 TRACE("%p, refcount %d.\n", iface, refcount);
3745 return refcount;
3748 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3750 struct bytestream *stream = impl_from_IMFByteStream(iface);
3751 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3752 struct async_stream_op *cur, *cur2;
3754 TRACE("%p, refcount %d.\n", iface, refcount);
3756 if (!refcount)
3758 clear_attributes_object(&stream->attributes);
3759 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3761 list_remove(&cur->entry);
3762 IUnknown_Release(&cur->IUnknown_iface);
3764 DeleteCriticalSection(&stream->cs);
3765 if (stream->stream)
3766 IStream_Release(stream->stream);
3767 if (stream->hfile)
3768 CloseHandle(stream->hfile);
3769 heap_free(stream);
3772 return refcount;
3775 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3777 struct bytestream *stream = impl_from_IMFByteStream(iface);
3778 STATSTG stat;
3779 HRESULT hr;
3781 TRACE("%p, %p.\n", iface, capabilities);
3783 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3784 return hr;
3786 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3787 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3788 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3790 return S_OK;
3793 static HRESULT WINAPI bytestream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3795 struct bytestream *stream = impl_from_IMFByteStream(iface);
3797 TRACE("%p, %p.\n", iface, capabilities);
3799 *capabilities = stream->capabilities;
3801 return S_OK;
3804 static HRESULT WINAPI mfbytestream_SetLength(IMFByteStream *iface, QWORD length)
3806 mfbytestream *This = impl_from_IMFByteStream(iface);
3808 FIXME("%p, %s\n", This, wine_dbgstr_longlong(length));
3810 return E_NOTIMPL;
3813 static HRESULT WINAPI bytestream_file_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3815 struct bytestream *stream = impl_from_IMFByteStream(iface);
3817 TRACE("%p, %p.\n", iface, position);
3819 if (!position)
3820 return E_INVALIDARG;
3822 *position = stream->position;
3824 return S_OK;
3827 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
3829 struct bytestream *stream = impl_from_IMFByteStream(iface);
3830 LARGE_INTEGER li;
3832 TRACE("%p, %p.\n", iface, length);
3834 if (!length)
3835 return E_INVALIDARG;
3837 if (GetFileSizeEx(stream->hfile, &li))
3838 *length = li.QuadPart;
3839 else
3840 return HRESULT_FROM_WIN32(GetLastError());
3842 return S_OK;
3845 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
3847 struct bytestream *stream = impl_from_IMFByteStream(iface);
3848 LARGE_INTEGER position, length;
3849 HRESULT hr = S_OK;
3851 TRACE("%p, %p.\n", iface, ret);
3853 EnterCriticalSection(&stream->cs);
3855 position.QuadPart = 0;
3856 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
3857 *ret = stream->position >= length.QuadPart;
3858 else
3859 hr = HRESULT_FROM_WIN32(GetLastError());
3861 LeaveCriticalSection(&stream->cs);
3863 return hr;
3866 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
3868 struct bytestream *stream = impl_from_IMFByteStream(iface);
3869 LARGE_INTEGER position;
3870 HRESULT hr = S_OK;
3871 BOOL ret;
3873 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
3875 EnterCriticalSection(&stream->cs);
3877 position.QuadPart = stream->position;
3878 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
3880 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
3881 stream->position += *read_len;
3884 if (!ret)
3885 hr = HRESULT_FROM_WIN32(GetLastError());
3887 LeaveCriticalSection(&stream->cs);
3889 return hr;
3892 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
3893 IUnknown *state)
3895 struct bytestream *stream = impl_from_IMFByteStream(iface);
3897 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3899 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_READ, data, size, callback, state);
3902 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
3904 struct bytestream *stream = impl_from_IMFByteStream(iface);
3906 TRACE("%p, %p, %p.\n", iface, result, byte_read);
3908 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
3911 static HRESULT WINAPI mfbytestream_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
3913 mfbytestream *This = impl_from_IMFByteStream(iface);
3915 FIXME("%p, %p, %u, %p\n", This, data, count, written);
3917 return E_NOTIMPL;
3920 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
3921 IMFAsyncCallback *callback, IUnknown *state)
3923 struct bytestream *stream = impl_from_IMFByteStream(iface);
3925 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3927 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
3930 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
3932 struct bytestream *stream = impl_from_IMFByteStream(iface);
3934 TRACE("%p, %p, %p.\n", iface, result, written);
3936 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
3939 static HRESULT WINAPI mfbytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
3940 DWORD flags, QWORD *current)
3942 mfbytestream *This = impl_from_IMFByteStream(iface);
3944 FIXME("%p, %u, %s, 0x%08x, %p\n", This, seek, wine_dbgstr_longlong(offset), flags, current);
3946 return E_NOTIMPL;
3949 static HRESULT WINAPI mfbytestream_Flush(IMFByteStream *iface)
3951 mfbytestream *This = impl_from_IMFByteStream(iface);
3953 FIXME("%p\n", This);
3955 return E_NOTIMPL;
3958 static HRESULT WINAPI mfbytestream_Close(IMFByteStream *iface)
3960 mfbytestream *This = impl_from_IMFByteStream(iface);
3962 FIXME("%p\n", This);
3964 return E_NOTIMPL;
3967 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
3969 struct bytestream *stream = impl_from_IMFByteStream(iface);
3971 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
3973 EnterCriticalSection(&stream->cs);
3974 stream->position = position;
3975 LeaveCriticalSection(&stream->cs);
3977 return S_OK;
3980 static const IMFByteStreamVtbl bytestream_file_vtbl =
3982 bytestream_QueryInterface,
3983 bytestream_AddRef,
3984 bytestream_Release,
3985 bytestream_GetCapabilities,
3986 bytestream_file_GetLength,
3987 mfbytestream_SetLength,
3988 bytestream_file_GetCurrentPosition,
3989 bytestream_SetCurrentPosition,
3990 bytestream_file_IsEndOfStream,
3991 bytestream_file_Read,
3992 bytestream_BeginRead,
3993 bytestream_EndRead,
3994 mfbytestream_Write,
3995 bytestream_BeginWrite,
3996 bytestream_EndWrite,
3997 mfbytestream_Seek,
3998 mfbytestream_Flush,
3999 mfbytestream_Close
4002 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
4004 struct bytestream *stream = impl_from_IMFByteStream(iface);
4005 STATSTG statstg;
4006 HRESULT hr;
4008 TRACE("%p, %p.\n", iface, length);
4010 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4011 return hr;
4013 *length = statstg.cbSize.QuadPart;
4015 return S_OK;
4018 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
4020 struct bytestream *stream = impl_from_IMFByteStream(iface);
4021 ULARGE_INTEGER size;
4022 HRESULT hr;
4024 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4026 EnterCriticalSection(&stream->cs);
4028 size.QuadPart = length;
4029 hr = IStream_SetSize(stream->stream, size);
4031 LeaveCriticalSection(&stream->cs);
4033 return hr;
4036 static HRESULT WINAPI bytestream_stream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4038 struct bytestream *stream = impl_from_IMFByteStream(iface);
4040 TRACE("%p, %p.\n", iface, position);
4042 *position = stream->position;
4044 return S_OK;
4047 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4049 struct bytestream *stream = impl_from_IMFByteStream(iface);
4050 STATSTG statstg;
4051 HRESULT hr;
4053 TRACE("%p, %p.\n", iface, ret);
4055 EnterCriticalSection(&stream->cs);
4057 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4058 *ret = stream->position >= statstg.cbSize.QuadPart;
4060 LeaveCriticalSection(&stream->cs);
4062 return hr;
4065 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4067 struct bytestream *stream = impl_from_IMFByteStream(iface);
4068 LARGE_INTEGER position;
4069 HRESULT hr;
4071 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
4073 EnterCriticalSection(&stream->cs);
4075 position.QuadPart = stream->position;
4076 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4078 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
4079 stream->position += *read_len;
4082 LeaveCriticalSection(&stream->cs);
4084 return hr;
4087 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
4089 struct bytestream *stream = impl_from_IMFByteStream(iface);
4090 LARGE_INTEGER position;
4091 HRESULT hr;
4093 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, written);
4095 EnterCriticalSection(&stream->cs);
4097 position.QuadPart = stream->position;
4098 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4100 if (SUCCEEDED(hr = IStream_Write(stream->stream, buffer, size, written)))
4101 stream->position += *written;
4104 LeaveCriticalSection(&stream->cs);
4106 return hr;
4109 static HRESULT WINAPI bytestream_stream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
4110 DWORD flags, QWORD *current)
4112 struct bytestream *stream = impl_from_IMFByteStream(iface);
4113 HRESULT hr = S_OK;
4115 TRACE("%p, %u, %s, %#x, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
4117 EnterCriticalSection(&stream->cs);
4119 switch (origin)
4121 case msoBegin:
4122 stream->position = offset;
4123 break;
4124 case msoCurrent:
4125 stream->position += offset;
4126 break;
4127 default:
4128 WARN("Unknown origin mode %d.\n", origin);
4129 hr = E_INVALIDARG;
4132 *current = stream->position;
4134 LeaveCriticalSection(&stream->cs);
4136 return hr;
4139 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4141 struct bytestream *stream = impl_from_IMFByteStream(iface);
4143 TRACE("%p.\n", iface);
4145 return IStream_Commit(stream->stream, STGC_DEFAULT);
4148 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4150 TRACE("%p.\n", iface);
4152 return S_OK;
4155 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4157 bytestream_QueryInterface,
4158 bytestream_AddRef,
4159 bytestream_Release,
4160 bytestream_stream_GetCapabilities,
4161 bytestream_stream_GetLength,
4162 bytestream_stream_SetLength,
4163 bytestream_stream_GetCurrentPosition,
4164 bytestream_SetCurrentPosition,
4165 bytestream_stream_IsEndOfStream,
4166 bytestream_stream_Read,
4167 bytestream_BeginRead,
4168 bytestream_EndRead,
4169 bytestream_stream_Write,
4170 bytestream_BeginWrite,
4171 bytestream_EndWrite,
4172 bytestream_stream_Seek,
4173 bytestream_stream_Flush,
4174 bytestream_stream_Close,
4177 static inline mfbytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4179 return CONTAINING_RECORD(iface, mfbytestream, attributes.IMFAttributes_iface);
4182 static HRESULT WINAPI mfbytestream_attributes_QueryInterface(
4183 IMFAttributes *iface, REFIID riid, void **out)
4185 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4186 return IMFByteStream_QueryInterface(&This->IMFByteStream_iface, riid, out);
4189 static ULONG WINAPI mfbytestream_attributes_AddRef(IMFAttributes *iface)
4191 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4192 return IMFByteStream_AddRef(&This->IMFByteStream_iface);
4195 static ULONG WINAPI mfbytestream_attributes_Release(IMFAttributes *iface)
4197 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4198 return IMFByteStream_Release(&This->IMFByteStream_iface);
4201 static const IMFAttributesVtbl mfbytestream_attributes_vtbl =
4203 mfbytestream_attributes_QueryInterface,
4204 mfbytestream_attributes_AddRef,
4205 mfbytestream_attributes_Release,
4206 mfattributes_GetItem,
4207 mfattributes_GetItemType,
4208 mfattributes_CompareItem,
4209 mfattributes_Compare,
4210 mfattributes_GetUINT32,
4211 mfattributes_GetUINT64,
4212 mfattributes_GetDouble,
4213 mfattributes_GetGUID,
4214 mfattributes_GetStringLength,
4215 mfattributes_GetString,
4216 mfattributes_GetAllocatedString,
4217 mfattributes_GetBlobSize,
4218 mfattributes_GetBlob,
4219 mfattributes_GetAllocatedBlob,
4220 mfattributes_GetUnknown,
4221 mfattributes_SetItem,
4222 mfattributes_DeleteItem,
4223 mfattributes_DeleteAllItems,
4224 mfattributes_SetUINT32,
4225 mfattributes_SetUINT64,
4226 mfattributes_SetDouble,
4227 mfattributes_SetGUID,
4228 mfattributes_SetString,
4229 mfattributes_SetBlob,
4230 mfattributes_SetUnknown,
4231 mfattributes_LockStore,
4232 mfattributes_UnlockStore,
4233 mfattributes_GetCount,
4234 mfattributes_GetItemByIndex,
4235 mfattributes_CopyAllItems
4238 static HRESULT WINAPI bytestream_stream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4240 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4241 struct async_stream_op *op;
4242 LARGE_INTEGER position;
4243 IUnknown *object;
4244 HRESULT hr;
4246 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4247 return hr;
4249 op = impl_async_stream_op_from_IUnknown(object);
4251 EnterCriticalSection(&stream->cs);
4253 position.QuadPart = op->position;
4254 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4256 if (SUCCEEDED(hr = IStream_Read(stream->stream, op->u.dest, op->requested_length, &op->actual_length)))
4257 stream->position += op->actual_length;
4260 IMFAsyncResult_SetStatus(op->caller, hr);
4261 list_add_tail(&stream->pending, &op->entry);
4263 LeaveCriticalSection(&stream->cs);
4265 MFInvokeCallback(op->caller);
4267 return S_OK;
4270 static HRESULT WINAPI bytestream_stream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4272 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4273 struct async_stream_op *op;
4274 LARGE_INTEGER position;
4275 IUnknown *object;
4276 HRESULT hr;
4278 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4279 return hr;
4281 op = impl_async_stream_op_from_IUnknown(object);
4283 EnterCriticalSection(&stream->cs);
4285 position.QuadPart = op->position;
4286 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4288 if (SUCCEEDED(hr = IStream_Write(stream->stream, op->u.src, op->requested_length, &op->actual_length)))
4289 stream->position += op->actual_length;
4292 IMFAsyncResult_SetStatus(op->caller, hr);
4293 list_add_tail(&stream->pending, &op->entry);
4295 LeaveCriticalSection(&stream->cs);
4297 MFInvokeCallback(op->caller);
4299 return S_OK;
4302 static const IRtwqAsyncCallbackVtbl bytestream_stream_read_callback_vtbl =
4304 bytestream_callback_QueryInterface,
4305 bytestream_read_callback_AddRef,
4306 bytestream_read_callback_Release,
4307 bytestream_callback_GetParameters,
4308 bytestream_stream_read_callback_Invoke,
4311 static const IRtwqAsyncCallbackVtbl bytestream_stream_write_callback_vtbl =
4313 bytestream_callback_QueryInterface,
4314 bytestream_write_callback_AddRef,
4315 bytestream_write_callback_Release,
4316 bytestream_callback_GetParameters,
4317 bytestream_stream_write_callback_Invoke,
4320 /***********************************************************************
4321 * MFCreateMFByteStreamOnStream (mfplat.@)
4323 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4325 struct bytestream *object;
4326 LARGE_INTEGER position;
4327 STATSTG stat;
4328 HRESULT hr;
4330 TRACE("%p, %p.\n", stream, bytestream);
4332 object = heap_alloc_zero(sizeof(*object));
4333 if (!object)
4334 return E_OUTOFMEMORY;
4336 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4338 heap_free(object);
4339 return hr;
4342 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4343 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4344 object->read_callback.lpVtbl = &bytestream_stream_read_callback_vtbl;
4345 object->write_callback.lpVtbl = &bytestream_stream_write_callback_vtbl;
4346 InitializeCriticalSection(&object->cs);
4347 list_init(&object->pending);
4349 object->stream = stream;
4350 IStream_AddRef(object->stream);
4351 position.QuadPart = 0;
4352 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4354 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4356 if (stat.pwcsName)
4358 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4359 stat.pwcsName);
4360 CoTaskMemFree(stat.pwcsName);
4364 *bytestream = &object->IMFByteStream_iface;
4366 return S_OK;
4369 static HRESULT WINAPI bytestream_file_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4371 FIXME("%p, %p.\n", iface, result);
4373 return E_NOTIMPL;
4376 static HRESULT WINAPI bytestream_file_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4378 FIXME("%p, %p.\n", iface, result);
4380 return E_NOTIMPL;
4383 static const IRtwqAsyncCallbackVtbl bytestream_file_read_callback_vtbl =
4385 bytestream_callback_QueryInterface,
4386 bytestream_read_callback_AddRef,
4387 bytestream_read_callback_Release,
4388 bytestream_callback_GetParameters,
4389 bytestream_file_read_callback_Invoke,
4392 static const IRtwqAsyncCallbackVtbl bytestream_file_write_callback_vtbl =
4394 bytestream_callback_QueryInterface,
4395 bytestream_write_callback_AddRef,
4396 bytestream_write_callback_Release,
4397 bytestream_callback_GetParameters,
4398 bytestream_file_write_callback_Invoke,
4401 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4403 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4404 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4407 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4409 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4410 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4413 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4415 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4416 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4419 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4420 REFIID riid, void **obj)
4422 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4424 return E_NOTIMPL;
4427 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4429 bytestream_file_getservice_QueryInterface,
4430 bytestream_file_getservice_AddRef,
4431 bytestream_file_getservice_Release,
4432 bytestream_file_getservice_GetService,
4435 /***********************************************************************
4436 * MFCreateFile (mfplat.@)
4438 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4439 LPCWSTR url, IMFByteStream **bytestream)
4441 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4442 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4443 DWORD filesharemode = FILE_SHARE_READ;
4444 struct bytestream *object;
4445 FILETIME writetime;
4446 HANDLE file;
4447 HRESULT hr;
4449 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(url), bytestream);
4451 switch (accessmode)
4453 case MF_ACCESSMODE_READ:
4454 fileaccessmode = GENERIC_READ;
4455 capabilities |= MFBYTESTREAM_IS_READABLE;
4456 break;
4457 case MF_ACCESSMODE_WRITE:
4458 fileaccessmode = GENERIC_WRITE;
4459 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4460 break;
4461 case MF_ACCESSMODE_READWRITE:
4462 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4463 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4464 break;
4467 switch (openmode)
4469 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4470 filecreation_disposition = OPEN_EXISTING;
4471 break;
4472 case MF_OPENMODE_FAIL_IF_EXIST:
4473 filecreation_disposition = CREATE_NEW;
4474 break;
4475 case MF_OPENMODE_RESET_IF_EXIST:
4476 filecreation_disposition = TRUNCATE_EXISTING;
4477 break;
4478 case MF_OPENMODE_APPEND_IF_EXIST:
4479 filecreation_disposition = OPEN_ALWAYS;
4480 fileaccessmode |= FILE_APPEND_DATA;
4481 break;
4482 case MF_OPENMODE_DELETE_IF_EXIST:
4483 filecreation_disposition = CREATE_ALWAYS;
4484 break;
4487 if (flags & MF_FILEFLAGS_NOBUFFERING)
4488 fileattributes |= FILE_FLAG_NO_BUFFERING;
4490 /* Open HANDLE to file */
4491 file = CreateFileW(url, fileaccessmode, filesharemode, NULL,
4492 filecreation_disposition, fileattributes, 0);
4494 if(file == INVALID_HANDLE_VALUE)
4495 return HRESULT_FROM_WIN32(GetLastError());
4497 object = heap_alloc_zero(sizeof(*object));
4498 if (!object)
4500 CloseHandle(file);
4501 return E_OUTOFMEMORY;
4504 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4506 CloseHandle(file);
4507 heap_free(object);
4508 return hr;
4510 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4511 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4512 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4513 object->read_callback.lpVtbl = &bytestream_file_read_callback_vtbl;
4514 object->write_callback.lpVtbl = &bytestream_file_write_callback_vtbl;
4515 InitializeCriticalSection(&object->cs);
4516 list_init(&object->pending);
4517 object->capabilities = capabilities;
4518 object->hfile = file;
4520 if (GetFileTime(file, NULL, NULL, &writetime))
4522 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4523 (const UINT8 *)&writetime, sizeof(writetime));
4526 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, url);
4528 *bytestream = &object->IMFByteStream_iface;
4530 return S_OK;
4533 struct bytestream_wrapper
4535 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4536 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4537 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4538 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4539 IMFSampleOutputStream IMFSampleOutputStream_iface;
4540 IPropertyStore IPropertyStore_iface;
4541 IMFByteStream IMFByteStream_iface;
4542 IMFAttributes IMFAttributes_iface;
4543 LONG refcount;
4545 IMFByteStreamCacheControl *cache_control;
4546 IMFByteStreamBuffering *stream_buffering;
4547 IMFMediaEventGenerator *event_generator;
4548 IMFByteStreamTimeSeek *time_seek;
4549 IMFSampleOutputStream *sample_output;
4550 IPropertyStore *propstore;
4551 IMFByteStream *stream;
4552 IMFAttributes *attributes;
4553 BOOL is_closed;
4556 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4558 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4561 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4563 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4566 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4568 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4571 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4573 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4576 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4578 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4581 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4583 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4586 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4588 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4591 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4593 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4596 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4598 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4600 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4602 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4603 IsEqualIID(riid, &IID_IUnknown))
4605 *out = &wrapper->IMFByteStream_iface;
4607 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4609 *out = &wrapper->IMFByteStreamCacheControl_iface;
4611 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4613 *out = &wrapper->IMFByteStreamBuffering_iface;
4615 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4617 *out = &wrapper->IMFMediaEventGenerator_iface;
4619 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4621 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4623 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4625 *out = &wrapper->IMFSampleOutputStream_iface;
4627 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4629 *out = &wrapper->IPropertyStore_iface;
4631 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4633 *out = &wrapper->IMFAttributes_iface;
4635 else
4637 WARN("Unsupported %s.\n", debugstr_guid(riid));
4638 *out = NULL;
4639 return E_NOINTERFACE;
4642 IUnknown_AddRef((IUnknown *)*out);
4643 return S_OK;
4646 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4648 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4649 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4651 TRACE("%p, refcount %d.\n", iface, refcount);
4653 return refcount;
4656 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4658 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4659 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4661 TRACE("%p, refcount %d.\n", iface, refcount);
4663 if (!refcount)
4665 if (wrapper->cache_control)
4666 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4667 if (wrapper->stream_buffering)
4668 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4669 if (wrapper->event_generator)
4670 IMFMediaEventGenerator_Release(wrapper->event_generator);
4671 if (wrapper->time_seek)
4672 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4673 if (wrapper->sample_output)
4674 IMFSampleOutputStream_Release(wrapper->sample_output);
4675 if (wrapper->propstore)
4676 IPropertyStore_Release(wrapper->propstore);
4677 if (wrapper->attributes)
4678 IMFAttributes_Release(wrapper->attributes);
4679 IMFByteStream_Release(wrapper->stream);
4680 heap_free(wrapper);
4683 return refcount;
4686 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4688 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4690 TRACE("%p, %p.\n", iface, capabilities);
4692 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4693 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4696 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4698 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4700 TRACE("%p, %p.\n", iface, length);
4702 if (wrapper->is_closed)
4703 return MF_E_INVALIDREQUEST;
4705 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4706 IMFByteStream_GetLength(wrapper->stream, length);
4709 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4711 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4713 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4715 if (wrapper->is_closed)
4716 return MF_E_INVALIDREQUEST;
4718 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4719 IMFByteStream_SetLength(wrapper->stream, length);
4722 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4724 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4726 TRACE("%p, %p.\n", iface, position);
4728 if (wrapper->is_closed)
4729 return MF_E_INVALIDREQUEST;
4731 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4732 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4735 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4737 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4739 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4741 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4742 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4745 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4747 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4749 TRACE("%p, %p.\n", iface, eos);
4751 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4752 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4755 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4757 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4759 TRACE("%p, %p, %u, %p.\n", iface, data, count, byte_read);
4761 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4762 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4765 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4766 IMFAsyncCallback *callback, IUnknown *state)
4768 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4770 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4772 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4773 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4776 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4778 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4780 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4782 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4783 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4786 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4788 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4790 TRACE("%p, %p, %u, %p.\n", iface, data, count, written);
4792 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4793 IMFByteStream_Write(wrapper->stream, data, count, written);
4796 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4797 IMFAsyncCallback *callback, IUnknown *state)
4799 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4801 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4803 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4804 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4807 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4809 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4811 TRACE("%p, %p, %p.\n", iface, result, written);
4813 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4814 IMFByteStream_EndWrite(wrapper->stream, result, written);
4817 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4818 DWORD flags, QWORD *current)
4820 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4822 TRACE("%p, %u, %s, %#x, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4824 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4825 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
4828 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
4830 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4832 TRACE("%p\n", iface);
4834 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
4837 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
4839 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4841 TRACE("%p\n", iface);
4843 wrapper->is_closed = TRUE;
4845 return S_OK;
4848 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
4850 bytestream_wrapper_QueryInterface,
4851 bytestream_wrapper_AddRef,
4852 bytestream_wrapper_Release,
4853 bytestream_wrapper_GetCapabilities,
4854 bytestream_wrapper_GetLength,
4855 bytestream_wrapper_SetLength,
4856 bytestream_wrapper_GetCurrentPosition,
4857 bytestream_wrapper_SetCurrentPosition,
4858 bytestream_wrapper_IsEndOfStream,
4859 bytestream_wrapper_Read,
4860 bytestream_wrapper_BeginRead,
4861 bytestream_wrapper_EndRead,
4862 bytestream_wrapper_Write,
4863 bytestream_wrapper_BeginWrite,
4864 bytestream_wrapper_EndWrite,
4865 bytestream_wrapper_Seek,
4866 bytestream_wrapper_Flush,
4867 bytestream_wrapper_Close,
4870 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
4871 REFIID riid, void **obj)
4873 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4874 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4877 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
4879 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4880 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4883 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
4885 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4886 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4889 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
4891 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4893 TRACE("%p.\n", iface);
4895 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
4898 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
4900 bytestream_wrapper_cache_control_QueryInterface,
4901 bytestream_wrapper_cache_control_AddRef,
4902 bytestream_wrapper_cache_control_Release,
4903 bytestream_wrapper_cache_control_StopBackgroundTransfer,
4906 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
4907 REFIID riid, void **obj)
4909 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4910 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4913 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
4915 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4916 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4919 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
4921 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4922 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4925 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
4926 MFBYTESTREAM_BUFFERING_PARAMS *params)
4928 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4930 TRACE("%p, %p.\n", iface, params);
4932 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
4935 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
4936 BOOL enable)
4938 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4940 TRACE("%p, %d.\n", iface, enable);
4942 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
4945 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
4947 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4949 TRACE("%p.\n", iface);
4951 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
4954 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
4956 bytestream_wrapper_buffering_QueryInterface,
4957 bytestream_wrapper_buffering_AddRef,
4958 bytestream_wrapper_buffering_Release,
4959 bytestream_wrapper_buffering_SetBufferingParams,
4960 bytestream_wrapper_buffering_EnableBuffering,
4961 bytestream_wrapper_buffering_StopBuffering,
4964 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
4965 REFIID riid, void **obj)
4967 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4968 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4971 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
4973 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4974 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4977 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
4979 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4980 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4983 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
4985 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4987 TRACE("%p, %p.\n", iface, result);
4989 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
4992 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
4994 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4996 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4998 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
5001 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
5002 QWORD *stop_time, QWORD *duration)
5004 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5006 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
5008 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
5011 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
5013 bytestream_wrapper_timeseek_QueryInterface,
5014 bytestream_wrapper_timeseek_AddRef,
5015 bytestream_wrapper_timeseek_Release,
5016 bytestream_wrapper_timeseek_IsTimeSeekSupported,
5017 bytestream_wrapper_timeseek_TimeSeek,
5018 bytestream_wrapper_timeseek_GetTimeSeekResult,
5021 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
5023 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5024 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5027 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
5029 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5030 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5033 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
5035 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5036 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5039 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
5041 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5043 TRACE("%p, %#x, %p.\n", iface, flags, event);
5045 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
5048 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
5050 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5052 TRACE("%p, %p, %p.\n", iface, callback, state);
5054 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
5057 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5059 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5061 TRACE("%p, %p, %p.\n", iface, result, event);
5063 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
5066 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
5067 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
5069 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5071 TRACE("%p, %d, %s, %#x, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
5073 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
5076 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
5078 bytestream_wrapper_events_QueryInterface,
5079 bytestream_wrapper_events_AddRef,
5080 bytestream_wrapper_events_Release,
5081 bytestream_wrapper_events_GetEvent,
5082 bytestream_wrapper_events_BeginGetEvent,
5083 bytestream_wrapper_events_EndGetEvent,
5084 bytestream_wrapper_events_QueueEvent,
5087 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
5089 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5090 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5093 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
5095 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5096 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5099 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
5101 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5102 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5105 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
5106 IMFAsyncCallback *callback, IUnknown *state)
5108 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5110 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
5112 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
5115 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
5117 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5119 TRACE("%p, %p.\n", iface, result);
5121 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
5124 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
5126 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5128 TRACE("%p.\n", iface);
5130 return IMFSampleOutputStream_Close(wrapper->sample_output);
5133 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5135 bytestream_wrapper_sample_output_QueryInterface,
5136 bytestream_wrapper_sample_output_AddRef,
5137 bytestream_wrapper_sample_output_Release,
5138 bytestream_wrapper_sample_output_BeginWriteSample,
5139 bytestream_wrapper_sample_output_EndWriteSample,
5140 bytestream_wrapper_sample_output_Close,
5143 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5145 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5146 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5149 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5151 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5152 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5155 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5157 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5158 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5161 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5163 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5165 TRACE("%p, %p.\n", iface, count);
5167 return IPropertyStore_GetCount(wrapper->propstore, count);
5170 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5172 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5174 TRACE("%p, %u, %p.\n", iface, prop, key);
5176 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5179 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5181 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5183 TRACE("%p, %p, %p.\n", iface, key, value);
5185 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5188 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5189 const PROPVARIANT *value)
5191 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5193 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5195 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5198 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5200 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5202 TRACE("%p.\n", iface);
5204 return IPropertyStore_Commit(wrapper->propstore);
5207 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5209 bytestream_wrapper_propstore_QueryInterface,
5210 bytestream_wrapper_propstore_AddRef,
5211 bytestream_wrapper_propstore_Release,
5212 bytestream_wrapper_propstore_GetCount,
5213 bytestream_wrapper_propstore_GetAt,
5214 bytestream_wrapper_propstore_GetValue,
5215 bytestream_wrapper_propstore_SetValue,
5216 bytestream_wrapper_propstore_Commit,
5219 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5221 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5222 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5225 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5227 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5228 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5231 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5233 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5234 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5237 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5239 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5241 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5243 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5246 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5248 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5250 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5252 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5255 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5256 REFPROPVARIANT value, BOOL *result)
5258 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5260 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5262 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5265 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5266 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5268 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5270 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5272 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5275 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5277 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5279 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5281 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5284 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5286 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5288 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5290 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5293 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5295 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5297 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5299 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5302 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5304 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5306 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5308 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5311 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5313 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5315 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5317 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5320 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5321 UINT32 size, UINT32 *length)
5323 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5325 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5327 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5330 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5332 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5334 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5336 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5339 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5341 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5343 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5345 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5348 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5349 UINT32 bufsize, UINT32 *blobsize)
5351 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5353 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5355 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5358 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5360 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5362 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5364 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5367 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5369 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5371 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5373 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5376 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5378 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5380 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5382 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5385 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5387 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5389 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5391 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5394 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5396 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5398 TRACE("%p.\n", iface);
5400 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5403 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5405 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5407 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5409 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5412 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5414 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5416 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5418 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5421 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5423 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5425 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5427 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5430 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5432 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5434 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5436 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5439 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5441 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5443 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5445 return IMFAttributes_SetString(wrapper->attributes, key, value);
5448 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5450 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5452 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5454 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5457 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5459 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5461 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5463 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5466 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5468 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5470 TRACE("%p.\n", iface);
5472 return IMFAttributes_LockStore(wrapper->attributes);
5475 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5477 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5479 TRACE("%p.\n", iface);
5481 return IMFAttributes_UnlockStore(wrapper->attributes);
5484 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5486 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5488 TRACE("%p, %p.\n", iface, count);
5490 return IMFAttributes_GetCount(wrapper->attributes, count);
5493 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5495 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5497 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5499 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5502 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5504 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5506 TRACE("%p, %p.\n", iface, dest);
5508 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5511 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5513 bytestream_wrapper_attributes_QueryInterface,
5514 bytestream_wrapper_attributes_AddRef,
5515 bytestream_wrapper_attributes_Release,
5516 bytestream_wrapper_attributes_GetItem,
5517 bytestream_wrapper_attributes_GetItemType,
5518 bytestream_wrapper_attributes_CompareItem,
5519 bytestream_wrapper_attributes_Compare,
5520 bytestream_wrapper_attributes_GetUINT32,
5521 bytestream_wrapper_attributes_GetUINT64,
5522 bytestream_wrapper_attributes_GetDouble,
5523 bytestream_wrapper_attributes_GetGUID,
5524 bytestream_wrapper_attributes_GetStringLength,
5525 bytestream_wrapper_attributes_GetString,
5526 bytestream_wrapper_attributes_GetAllocatedString,
5527 bytestream_wrapper_attributes_GetBlobSize,
5528 bytestream_wrapper_attributes_GetBlob,
5529 bytestream_wrapper_attributes_GetAllocatedBlob,
5530 bytestream_wrapper_attributes_GetUnknown,
5531 bytestream_wrapper_attributes_SetItem,
5532 bytestream_wrapper_attributes_DeleteItem,
5533 bytestream_wrapper_attributes_DeleteAllItems,
5534 bytestream_wrapper_attributes_SetUINT32,
5535 bytestream_wrapper_attributes_SetUINT64,
5536 bytestream_wrapper_attributes_SetDouble,
5537 bytestream_wrapper_attributes_SetGUID,
5538 bytestream_wrapper_attributes_SetString,
5539 bytestream_wrapper_attributes_SetBlob,
5540 bytestream_wrapper_attributes_SetUnknown,
5541 bytestream_wrapper_attributes_LockStore,
5542 bytestream_wrapper_attributes_UnlockStore,
5543 bytestream_wrapper_attributes_GetCount,
5544 bytestream_wrapper_attributes_GetItemByIndex,
5545 bytestream_wrapper_attributes_CopyAllItems
5548 /***********************************************************************
5549 * MFCreateMFByteStreamWrapper (mfplat.@)
5551 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5553 struct bytestream_wrapper *object;
5555 TRACE("%p, %p.\n", stream, wrapper);
5557 object = heap_alloc_zero(sizeof(*object));
5558 if (!object)
5559 return E_OUTOFMEMORY;
5561 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5562 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5563 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5564 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5565 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5566 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5567 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5568 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5570 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5571 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5572 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5573 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5574 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5575 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5576 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5578 object->stream = stream;
5579 IMFByteStream_AddRef(object->stream);
5581 object->refcount = 1;
5583 *wrapper = &object->IMFByteStream_iface;
5585 return S_OK;
5588 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5590 if(IsEqualGUID(riid, &IID_IUnknown)) {
5591 TRACE("(IID_IUnknown %p)\n", ppv);
5592 *ppv = iface;
5593 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5594 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5595 *ppv = iface;
5596 }else {
5597 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5598 *ppv = NULL;
5599 return E_NOINTERFACE;
5602 IUnknown_AddRef((IUnknown*)*ppv);
5603 return S_OK;
5606 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5608 TRACE("\n");
5609 return 2;
5612 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5614 TRACE("\n");
5615 return 1;
5618 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5619 const WCHAR *selector, CLSID *clsid)
5621 FIXME("(%d %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5622 return E_NOTIMPL;
5625 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5626 DWORD index, WCHAR **selector, CLSID *clsid)
5628 FIXME("(%d %d %p %p)\n", plugin_type, index, selector, clsid);
5629 return E_NOTIMPL;
5632 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5633 const WCHAR *selector, const CLSID *clsid)
5635 FIXME("(%d %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5636 return E_NOTIMPL;
5639 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5641 FIXME("(%d %s)\n", plugin_type, debugstr_guid(clsid));
5642 return E_NOTIMPL;
5645 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5647 FIXME("(%d %d %p)\n", plugin_type, index, clsid);
5648 return E_NOTIMPL;
5651 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5653 FIXME("(%d %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5654 return E_NOTIMPL;
5657 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5658 MFPluginControl_QueryInterface,
5659 MFPluginControl_AddRef,
5660 MFPluginControl_Release,
5661 MFPluginControl_GetPreferredClsid,
5662 MFPluginControl_GetPreferredClsidByIndex,
5663 MFPluginControl_SetPreferredClsid,
5664 MFPluginControl_IsDisabled,
5665 MFPluginControl_GetDisabledByIndex,
5666 MFPluginControl_SetDisabled
5669 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5671 /***********************************************************************
5672 * MFGetPluginControl (mfplat.@)
5674 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5676 TRACE("(%p)\n", ret);
5678 *ret = &plugin_control;
5679 return S_OK;
5682 enum resolved_object_origin
5684 OBJECT_FROM_BYTESTREAM,
5685 OBJECT_FROM_URL,
5688 struct resolver_queued_result
5690 struct list entry;
5691 IUnknown *object;
5692 MF_OBJECT_TYPE obj_type;
5693 HRESULT hr;
5694 IRtwqAsyncResult *inner_result;
5695 enum resolved_object_origin origin;
5698 struct resolver_cancel_object
5700 IUnknown IUnknown_iface;
5701 LONG refcount;
5702 union
5704 IUnknown *handler;
5705 IMFByteStreamHandler *stream_handler;
5706 IMFSchemeHandler *scheme_handler;
5707 } u;
5708 IUnknown *cancel_cookie;
5709 enum resolved_object_origin origin;
5712 struct source_resolver
5714 IMFSourceResolver IMFSourceResolver_iface;
5715 LONG refcount;
5716 IRtwqAsyncCallback stream_callback;
5717 IRtwqAsyncCallback url_callback;
5718 CRITICAL_SECTION cs;
5719 struct list pending;
5722 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5724 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5727 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5729 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5732 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5734 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5737 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5738 IRtwqAsyncResult *result)
5740 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5741 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5742 struct resolver_queued_result *queued_result;
5743 union
5745 IUnknown *handler;
5746 IMFByteStreamHandler *stream_handler;
5747 IMFSchemeHandler *scheme_handler;
5748 } handler;
5750 if (!(queued_result = heap_alloc_zero(sizeof(*queued_result))))
5751 return E_OUTOFMEMORY;
5753 queued_result->origin = origin;
5755 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5757 switch (origin)
5759 case OBJECT_FROM_BYTESTREAM:
5760 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5761 &queued_result->obj_type, &queued_result->object);
5762 break;
5763 case OBJECT_FROM_URL:
5764 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5765 &queued_result->obj_type, &queued_result->object);
5766 break;
5767 default:
5768 queued_result->hr = E_FAIL;
5771 IUnknown_Release(handler.handler);
5773 if (data->hEvent)
5775 queued_result->inner_result = inner_result;
5776 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5779 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5780 EnterCriticalSection(&resolver->cs);
5781 list_add_tail(&resolver->pending, &queued_result->entry);
5782 LeaveCriticalSection(&resolver->cs);
5784 if (data->hEvent)
5785 SetEvent(data->hEvent);
5786 else
5788 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5789 IRtwqAsyncResult *caller_result;
5791 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5793 RtwqInvokeCallback(caller_result);
5794 IRtwqAsyncResult_Release(caller_result);
5798 return S_OK;
5801 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5803 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5806 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5808 if (IsEqualIID(riid, &IID_IUnknown))
5810 *obj = iface;
5811 IUnknown_AddRef(iface);
5812 return S_OK;
5815 *obj = NULL;
5816 return E_NOINTERFACE;
5819 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
5821 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5822 return InterlockedIncrement(&object->refcount);
5825 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
5827 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5828 ULONG refcount = InterlockedDecrement(&object->refcount);
5830 if (!refcount)
5832 if (object->cancel_cookie)
5833 IUnknown_Release(object->cancel_cookie);
5834 IUnknown_Release(object->u.handler);
5835 heap_free(object);
5838 return refcount;
5841 static const IUnknownVtbl resolver_cancel_object_vtbl =
5843 resolver_cancel_object_QueryInterface,
5844 resolver_cancel_object_AddRef,
5845 resolver_cancel_object_Release,
5848 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
5850 if (!iface)
5851 return NULL;
5853 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
5854 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
5857 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
5858 IUnknown *cancel_cookie, IUnknown **cancel_object)
5860 struct resolver_cancel_object *object;
5862 object = heap_alloc_zero(sizeof(*object));
5863 if (!object)
5864 return E_OUTOFMEMORY;
5866 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
5867 object->refcount = 1;
5868 object->u.handler = handler;
5869 IUnknown_AddRef(object->u.handler);
5870 object->cancel_cookie = cancel_cookie;
5871 IUnknown_AddRef(object->cancel_cookie);
5872 object->origin = origin;
5874 *cancel_object = &object->IUnknown_iface;
5876 return S_OK;
5879 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
5881 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
5882 IsEqualIID(riid, &IID_IUnknown))
5884 *obj = iface;
5885 IRtwqAsyncCallback_AddRef(iface);
5886 return S_OK;
5889 *obj = NULL;
5890 return E_NOINTERFACE;
5893 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
5895 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5896 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5899 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
5901 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5902 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5905 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
5907 return E_NOTIMPL;
5910 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5912 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5914 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
5917 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
5919 source_resolver_callback_QueryInterface,
5920 source_resolver_callback_stream_AddRef,
5921 source_resolver_callback_stream_Release,
5922 source_resolver_callback_GetParameters,
5923 source_resolver_callback_stream_Invoke,
5926 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
5928 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5929 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5932 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
5934 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5935 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5938 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5940 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5942 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
5945 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
5947 source_resolver_callback_QueryInterface,
5948 source_resolver_callback_url_AddRef,
5949 source_resolver_callback_url_Release,
5950 source_resolver_callback_GetParameters,
5951 source_resolver_callback_url_Invoke,
5954 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
5956 unsigned int j = 0, name_length, type;
5957 HRESULT hr = E_FAIL;
5958 WCHAR clsidW[39];
5959 CLSID clsid;
5961 name_length = ARRAY_SIZE(clsidW);
5962 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
5964 if (type == REG_SZ)
5966 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
5968 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
5969 if (SUCCEEDED(hr))
5970 break;
5974 name_length = ARRAY_SIZE(clsidW);
5977 return hr;
5980 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
5981 IMFByteStreamHandler **handler)
5983 static const char streamhandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers";
5984 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
5985 IMFAttributes *attributes;
5986 const WCHAR *url_ext;
5987 WCHAR *mimeW = NULL;
5988 HRESULT hr = E_FAIL;
5989 unsigned int i, j;
5990 UINT32 length;
5992 *handler = NULL;
5994 /* MIME type */
5995 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
5997 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
5998 IMFAttributes_Release(attributes);
6001 /* Extension */
6002 url_ext = url ? wcsrchr(url, '.') : NULL;
6004 if (!url_ext && !mimeW)
6006 CoTaskMemFree(mimeW);
6007 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6010 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6012 struct local_handler *local_handler;
6014 EnterCriticalSection(&local_handlers_section);
6016 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
6018 if ((mimeW && !lstrcmpiW(mimeW, local_handler->u.bytestream.mime))
6019 || (url_ext && !lstrcmpiW(url_ext, local_handler->u.bytestream.extension)))
6021 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
6022 (void **)handler)))
6023 break;
6027 LeaveCriticalSection(&local_handlers_section);
6029 if (*handler)
6030 return hr;
6033 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
6035 const WCHAR *namesW[2] = { mimeW, url_ext };
6036 HKEY hkey, hkey_handler;
6038 if (RegOpenKeyA(hkey_roots[i], streamhandlerspath, &hkey))
6039 continue;
6041 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6043 if (!namesW[j])
6044 continue;
6046 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6048 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6049 RegCloseKey(hkey_handler);
6052 if (SUCCEEDED(hr))
6053 break;
6056 RegCloseKey(hkey);
6058 if (SUCCEEDED(hr))
6059 break;
6062 if (FAILED(hr))
6064 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6065 hr = CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6068 CoTaskMemFree(mimeW);
6069 return hr;
6072 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6074 static const char schemehandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers";
6075 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6076 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6077 unsigned int i;
6079 TRACE("%s, %#x, %p.\n", debugstr_w(scheme), flags, handler);
6081 *handler = NULL;
6083 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6085 struct local_handler *local_handler;
6087 EnterCriticalSection(&local_handlers_section);
6089 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6091 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6093 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6094 (void **)handler)))
6095 break;
6099 LeaveCriticalSection(&local_handlers_section);
6101 if (*handler)
6102 return hr;
6105 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6107 HKEY hkey, hkey_handler;
6109 hr = MF_E_UNSUPPORTED_SCHEME;
6111 if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey))
6112 continue;
6114 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6116 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6117 RegCloseKey(hkey_handler);
6120 RegCloseKey(hkey);
6122 if (SUCCEEDED(hr))
6123 break;
6126 return hr;
6129 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6131 static const WCHAR fileschemeW[] = {'f','i','l','e',':',0};
6132 const WCHAR *ptr = url;
6133 unsigned int len;
6134 WCHAR *scheme;
6135 HRESULT hr;
6137 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6138 while (*ptr)
6140 WCHAR ch = towlower(*ptr);
6142 if (*ptr == '*' && ptr == url)
6144 ptr++;
6145 break;
6147 else if (!(*ptr >= '0' && *ptr <= '9') &&
6148 !(ch >= 'a' && ch <= 'z') &&
6149 *ptr != '+' && *ptr != '-' && *ptr != '.')
6151 break;
6154 ptr++;
6157 /* Schemes must end with a ':', if not found try "file:" */
6158 if (ptr == url || *ptr != ':')
6160 url = fileschemeW;
6161 ptr = fileschemeW + ARRAY_SIZE(fileschemeW) - 1;
6164 len = ptr - url;
6165 scheme = heap_alloc((len + 1) * sizeof(WCHAR));
6166 if (!scheme)
6167 return E_OUTOFMEMORY;
6169 memcpy(scheme, url, len * sizeof(WCHAR));
6170 scheme[len] = 0;
6172 hr = resolver_create_scheme_handler(scheme, flags, handler);
6173 if (FAILED(hr) && url != fileschemeW)
6174 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6176 heap_free(scheme);
6178 return hr;
6181 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6182 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6184 struct resolver_queued_result *queued_result = NULL, *iter;
6185 IUnknown *object;
6186 HRESULT hr;
6188 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6189 return hr;
6191 EnterCriticalSection(&resolver->cs);
6193 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6195 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6197 list_remove(&iter->entry);
6198 queued_result = iter;
6199 break;
6203 LeaveCriticalSection(&resolver->cs);
6205 IUnknown_Release(object);
6207 if (queued_result)
6209 *out = queued_result->object;
6210 *obj_type = queued_result->obj_type;
6211 hr = queued_result->hr;
6212 if (queued_result->inner_result)
6213 IRtwqAsyncResult_Release(queued_result->inner_result);
6214 heap_free(queued_result);
6216 else
6217 hr = E_UNEXPECTED;
6219 return hr;
6222 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6224 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6226 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6228 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6229 IsEqualIID(riid, &IID_IUnknown))
6231 *obj = &resolver->IMFSourceResolver_iface;
6233 else
6235 *obj = NULL;
6236 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6237 return E_NOINTERFACE;
6240 IUnknown_AddRef((IUnknown *)*obj);
6241 return S_OK;
6244 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6246 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6247 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6249 TRACE("%p, refcount %d.\n", iface, refcount);
6251 return refcount;
6254 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6256 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6257 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6258 struct resolver_queued_result *result, *result2;
6260 TRACE("%p, refcount %d.\n", iface, refcount);
6262 if (!refcount)
6264 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6266 if (result->object)
6267 IUnknown_Release(result->object);
6268 list_remove(&result->entry);
6269 heap_free(result);
6271 DeleteCriticalSection(&resolver->cs);
6272 heap_free(resolver);
6275 return refcount;
6278 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6279 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6281 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6282 IMFSchemeHandler *handler;
6283 IRtwqAsyncResult *result;
6284 RTWQASYNCRESULT *data;
6285 HRESULT hr;
6287 TRACE("%p, %s, %#x, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6289 if (!url || !obj_type || !object)
6290 return E_POINTER;
6292 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6293 return hr;
6295 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6296 IMFSchemeHandler_Release(handler);
6297 if (FAILED(hr))
6298 return hr;
6300 data = (RTWQASYNCRESULT *)result;
6301 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6303 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6304 (IUnknown *)result);
6305 if (FAILED(hr))
6307 IRtwqAsyncResult_Release(result);
6308 return hr;
6311 WaitForSingleObject(data->hEvent, INFINITE);
6313 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6314 IRtwqAsyncResult_Release(result);
6316 return hr;
6319 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6320 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6322 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6323 IMFByteStreamHandler *handler;
6324 IRtwqAsyncResult *result;
6325 RTWQASYNCRESULT *data;
6326 HRESULT hr;
6328 TRACE("%p, %p, %s, %#x, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6330 if (!stream || !obj_type || !object)
6331 return E_POINTER;
6333 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6334 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6336 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6337 IMFByteStreamHandler_Release(handler);
6338 if (FAILED(hr))
6339 return hr;
6341 data = (RTWQASYNCRESULT *)result;
6342 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6344 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6345 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6346 if (FAILED(hr))
6348 IRtwqAsyncResult_Release(result);
6349 return hr;
6352 WaitForSingleObject(data->hEvent, INFINITE);
6354 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6355 IRtwqAsyncResult_Release(result);
6357 return hr;
6360 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6361 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6363 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6364 IMFSchemeHandler *handler;
6365 IUnknown *inner_cookie = NULL;
6366 IRtwqAsyncResult *result;
6367 HRESULT hr;
6369 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6371 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6372 return hr;
6374 if (cancel_cookie)
6375 *cancel_cookie = NULL;
6377 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6378 IMFSchemeHandler_Release(handler);
6379 if (FAILED(hr))
6380 return hr;
6382 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6383 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6385 if (SUCCEEDED(hr) && inner_cookie)
6386 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6388 IRtwqAsyncResult_Release(result);
6390 return hr;
6393 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6394 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6396 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6398 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6400 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6403 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6404 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6405 IUnknown *state)
6407 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6408 IMFByteStreamHandler *handler;
6409 IUnknown *inner_cookie = NULL;
6410 IRtwqAsyncResult *result;
6411 HRESULT hr;
6413 TRACE("%p, %p, %s, %#x, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6414 callback, state);
6416 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6417 return hr;
6419 if (cancel_cookie)
6420 *cancel_cookie = NULL;
6422 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6423 IMFByteStreamHandler_Release(handler);
6424 if (FAILED(hr))
6425 return hr;
6427 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6428 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6430 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6431 if (SUCCEEDED(hr) && inner_cookie)
6432 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6434 IRtwqAsyncResult_Release(result);
6436 return hr;
6439 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6440 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6442 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6444 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6446 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6449 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6451 struct resolver_cancel_object *object;
6452 HRESULT hr;
6454 TRACE("%p, %p.\n", iface, cancel_cookie);
6456 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6457 return E_UNEXPECTED;
6459 switch (object->origin)
6461 case OBJECT_FROM_BYTESTREAM:
6462 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6463 break;
6464 case OBJECT_FROM_URL:
6465 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6466 break;
6467 default:
6468 hr = E_UNEXPECTED;
6471 return hr;
6474 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6476 source_resolver_QueryInterface,
6477 source_resolver_AddRef,
6478 source_resolver_Release,
6479 source_resolver_CreateObjectFromURL,
6480 source_resolver_CreateObjectFromByteStream,
6481 source_resolver_BeginCreateObjectFromURL,
6482 source_resolver_EndCreateObjectFromURL,
6483 source_resolver_BeginCreateObjectFromByteStream,
6484 source_resolver_EndCreateObjectFromByteStream,
6485 source_resolver_CancelObjectCreation,
6488 /***********************************************************************
6489 * MFCreateSourceResolver (mfplat.@)
6491 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6493 struct source_resolver *object;
6495 TRACE("%p\n", resolver);
6497 if (!resolver)
6498 return E_POINTER;
6500 object = heap_alloc_zero(sizeof(*object));
6501 if (!object)
6502 return E_OUTOFMEMORY;
6504 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6505 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6506 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6507 object->refcount = 1;
6508 list_init(&object->pending);
6509 InitializeCriticalSection(&object->cs);
6511 *resolver = &object->IMFSourceResolver_iface;
6513 return S_OK;
6516 struct media_event
6518 struct attributes attributes;
6519 IMFMediaEvent IMFMediaEvent_iface;
6521 MediaEventType type;
6522 GUID extended_type;
6523 HRESULT status;
6524 PROPVARIANT value;
6527 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6529 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6532 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6534 struct media_event *event = impl_from_IMFMediaEvent(iface);
6536 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6538 if(IsEqualGUID(riid, &IID_IUnknown) ||
6539 IsEqualGUID(riid, &IID_IMFAttributes) ||
6540 IsEqualGUID(riid, &IID_IMFMediaEvent))
6542 *out = &event->IMFMediaEvent_iface;
6544 else
6546 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6547 *out = NULL;
6548 return E_NOINTERFACE;
6551 IUnknown_AddRef((IUnknown*)*out);
6552 return S_OK;
6555 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6557 struct media_event *event = impl_from_IMFMediaEvent(iface);
6558 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6560 TRACE("%p, refcount %u.\n", iface, refcount);
6562 return refcount;
6565 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6567 struct media_event *event = impl_from_IMFMediaEvent(iface);
6568 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6570 TRACE("%p, refcount %u.\n", iface, refcount);
6572 if (!refcount)
6574 clear_attributes_object(&event->attributes);
6575 PropVariantClear(&event->value);
6576 heap_free(event);
6579 return refcount;
6582 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6584 struct media_event *event = impl_from_IMFMediaEvent(iface);
6586 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6588 return attributes_GetItem(&event->attributes, key, value);
6591 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6593 struct media_event *event = impl_from_IMFMediaEvent(iface);
6595 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6597 return attributes_GetItemType(&event->attributes, key, type);
6600 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6602 struct media_event *event = impl_from_IMFMediaEvent(iface);
6604 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6606 return attributes_CompareItem(&event->attributes, key, value, result);
6609 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6610 BOOL *result)
6612 struct media_event *event = impl_from_IMFMediaEvent(iface);
6614 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6616 return attributes_Compare(&event->attributes, attrs, type, result);
6619 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6621 struct media_event *event = impl_from_IMFMediaEvent(iface);
6623 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6625 return attributes_GetUINT32(&event->attributes, key, value);
6628 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6630 struct media_event *event = impl_from_IMFMediaEvent(iface);
6632 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6634 return attributes_GetUINT64(&event->attributes, key, value);
6637 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6639 struct media_event *event = impl_from_IMFMediaEvent(iface);
6641 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6643 return attributes_GetDouble(&event->attributes, key, value);
6646 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6648 struct media_event *event = impl_from_IMFMediaEvent(iface);
6650 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6652 return attributes_GetGUID(&event->attributes, key, value);
6655 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6657 struct media_event *event = impl_from_IMFMediaEvent(iface);
6659 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6661 return attributes_GetStringLength(&event->attributes, key, length);
6664 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6665 UINT32 size, UINT32 *length)
6667 struct media_event *event = impl_from_IMFMediaEvent(iface);
6669 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6671 return attributes_GetString(&event->attributes, key, value, size, length);
6674 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6675 WCHAR **value, UINT32 *length)
6677 struct media_event *event = impl_from_IMFMediaEvent(iface);
6679 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6681 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6684 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6686 struct media_event *event = impl_from_IMFMediaEvent(iface);
6688 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
6690 return attributes_GetBlobSize(&event->attributes, key, size);
6693 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
6694 UINT32 bufsize, UINT32 *blobsize)
6696 struct media_event *event = impl_from_IMFMediaEvent(iface);
6698 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
6700 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
6703 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
6705 struct media_event *event = impl_from_IMFMediaEvent(iface);
6707 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
6709 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
6712 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
6714 struct media_event *event = impl_from_IMFMediaEvent(iface);
6716 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
6718 return attributes_GetUnknown(&event->attributes, key, riid, out);
6721 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
6723 struct media_event *event = impl_from_IMFMediaEvent(iface);
6725 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
6727 return attributes_SetItem(&event->attributes, key, value);
6730 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
6732 struct media_event *event = impl_from_IMFMediaEvent(iface);
6734 TRACE("%p, %s.\n", iface, debugstr_attr(key));
6736 return attributes_DeleteItem(&event->attributes, key);
6739 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
6741 struct media_event *event = impl_from_IMFMediaEvent(iface);
6743 TRACE("%p.\n", iface);
6745 return attributes_DeleteAllItems(&event->attributes);
6748 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
6750 struct media_event *event = impl_from_IMFMediaEvent(iface);
6752 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
6754 return attributes_SetUINT32(&event->attributes, key, value);
6757 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
6759 struct media_event *event = impl_from_IMFMediaEvent(iface);
6761 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
6763 return attributes_SetUINT64(&event->attributes, key, value);
6766 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
6768 struct media_event *event = impl_from_IMFMediaEvent(iface);
6770 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
6772 return attributes_SetDouble(&event->attributes, key, value);
6775 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
6777 struct media_event *event = impl_from_IMFMediaEvent(iface);
6779 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
6781 return attributes_SetGUID(&event->attributes, key, value);
6784 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
6786 struct media_event *event = impl_from_IMFMediaEvent(iface);
6788 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
6790 return attributes_SetString(&event->attributes, key, value);
6793 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
6795 struct media_event *event = impl_from_IMFMediaEvent(iface);
6797 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
6799 return attributes_SetBlob(&event->attributes, key, buf, size);
6802 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
6804 struct media_event *event = impl_from_IMFMediaEvent(iface);
6806 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
6808 return attributes_SetUnknown(&event->attributes, key, unknown);
6811 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
6813 struct media_event *event = impl_from_IMFMediaEvent(iface);
6815 TRACE("%p.\n", iface);
6817 return attributes_LockStore(&event->attributes);
6820 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
6822 struct media_event *event = impl_from_IMFMediaEvent(iface);
6824 TRACE("%p.\n", iface);
6826 return attributes_UnlockStore(&event->attributes);
6829 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
6831 struct media_event *event = impl_from_IMFMediaEvent(iface);
6833 TRACE("%p, %p.\n", iface, count);
6835 return attributes_GetCount(&event->attributes, count);
6838 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
6840 struct media_event *event = impl_from_IMFMediaEvent(iface);
6842 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
6844 return attributes_GetItemByIndex(&event->attributes, index, key, value);
6847 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
6849 struct media_event *event = impl_from_IMFMediaEvent(iface);
6851 TRACE("%p, %p.\n", iface, dest);
6853 return attributes_CopyAllItems(&event->attributes, dest);
6856 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
6858 struct media_event *event = impl_from_IMFMediaEvent(iface);
6860 TRACE("%p, %p.\n", iface, type);
6862 *type = event->type;
6864 return S_OK;
6867 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
6869 struct media_event *event = impl_from_IMFMediaEvent(iface);
6871 TRACE("%p, %p.\n", iface, extended_type);
6873 *extended_type = event->extended_type;
6875 return S_OK;
6878 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
6880 struct media_event *event = impl_from_IMFMediaEvent(iface);
6882 TRACE("%p, %p.\n", iface, status);
6884 *status = event->status;
6886 return S_OK;
6889 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
6891 struct media_event *event = impl_from_IMFMediaEvent(iface);
6893 TRACE("%p, %p.\n", iface, value);
6895 PropVariantCopy(value, &event->value);
6897 return S_OK;
6900 static const IMFMediaEventVtbl mfmediaevent_vtbl =
6902 mfmediaevent_QueryInterface,
6903 mfmediaevent_AddRef,
6904 mfmediaevent_Release,
6905 mfmediaevent_GetItem,
6906 mfmediaevent_GetItemType,
6907 mfmediaevent_CompareItem,
6908 mfmediaevent_Compare,
6909 mfmediaevent_GetUINT32,
6910 mfmediaevent_GetUINT64,
6911 mfmediaevent_GetDouble,
6912 mfmediaevent_GetGUID,
6913 mfmediaevent_GetStringLength,
6914 mfmediaevent_GetString,
6915 mfmediaevent_GetAllocatedString,
6916 mfmediaevent_GetBlobSize,
6917 mfmediaevent_GetBlob,
6918 mfmediaevent_GetAllocatedBlob,
6919 mfmediaevent_GetUnknown,
6920 mfmediaevent_SetItem,
6921 mfmediaevent_DeleteItem,
6922 mfmediaevent_DeleteAllItems,
6923 mfmediaevent_SetUINT32,
6924 mfmediaevent_SetUINT64,
6925 mfmediaevent_SetDouble,
6926 mfmediaevent_SetGUID,
6927 mfmediaevent_SetString,
6928 mfmediaevent_SetBlob,
6929 mfmediaevent_SetUnknown,
6930 mfmediaevent_LockStore,
6931 mfmediaevent_UnlockStore,
6932 mfmediaevent_GetCount,
6933 mfmediaevent_GetItemByIndex,
6934 mfmediaevent_CopyAllItems,
6935 mfmediaevent_GetType,
6936 mfmediaevent_GetExtendedType,
6937 mfmediaevent_GetStatus,
6938 mfmediaevent_GetValue,
6941 /***********************************************************************
6942 * MFCreateMediaEvent (mfplat.@)
6944 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
6945 IMFMediaEvent **event)
6947 struct media_event *object;
6948 HRESULT hr;
6950 TRACE("%s, %s, %#x, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
6951 debugstr_propvar(value), event);
6953 object = heap_alloc(sizeof(*object));
6954 if (!object)
6955 return E_OUTOFMEMORY;
6957 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
6959 heap_free(object);
6960 return hr;
6962 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
6964 object->type = type;
6965 object->extended_type = *extended_type;
6966 object->status = status;
6968 PropVariantInit(&object->value);
6969 if (value)
6970 PropVariantCopy(&object->value, value);
6972 *event = &object->IMFMediaEvent_iface;
6974 TRACE("Created event %p.\n", *event);
6976 return S_OK;
6979 struct event_queue
6981 IMFMediaEventQueue IMFMediaEventQueue_iface;
6982 LONG refcount;
6984 CRITICAL_SECTION cs;
6985 CONDITION_VARIABLE update_event;
6986 struct list events;
6987 BOOL is_shut_down;
6988 BOOL notified;
6989 IRtwqAsyncResult *subscriber;
6992 struct queued_event
6994 struct list entry;
6995 IMFMediaEvent *event;
6998 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
7000 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
7003 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
7005 struct list *head = list_head(&queue->events);
7006 struct queued_event *queued_event;
7007 IMFMediaEvent *event;
7009 if (!head)
7010 return NULL;
7012 queued_event = LIST_ENTRY(head, struct queued_event, entry);
7013 event = queued_event->event;
7014 list_remove(&queued_event->entry);
7015 heap_free(queued_event);
7016 return event;
7019 static void event_queue_cleanup(struct event_queue *queue)
7021 IMFMediaEvent *event;
7023 while ((event = queue_pop_event(queue)))
7024 IMFMediaEvent_Release(event);
7027 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7029 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7031 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7033 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7034 IsEqualIID(riid, &IID_IUnknown))
7036 *out = &queue->IMFMediaEventQueue_iface;
7037 IMFMediaEventQueue_AddRef(iface);
7038 return S_OK;
7041 WARN("Unsupported %s.\n", debugstr_guid(riid));
7042 *out = NULL;
7043 return E_NOINTERFACE;
7046 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7048 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7049 ULONG refcount = InterlockedIncrement(&queue->refcount);
7051 TRACE("%p, refcount %u.\n", iface, refcount);
7053 return refcount;
7056 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7058 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7059 ULONG refcount = InterlockedDecrement(&queue->refcount);
7061 TRACE("%p, refcount %u.\n", queue, refcount);
7063 if (!refcount)
7065 event_queue_cleanup(queue);
7066 DeleteCriticalSection(&queue->cs);
7067 heap_free(queue);
7070 return refcount;
7073 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7075 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7076 HRESULT hr = S_OK;
7078 TRACE("%p, %p.\n", iface, event);
7080 EnterCriticalSection(&queue->cs);
7082 if (queue->is_shut_down)
7083 hr = MF_E_SHUTDOWN;
7084 else if (queue->subscriber)
7085 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7086 else
7088 if (flags & MF_EVENT_FLAG_NO_WAIT)
7090 if (!(*event = queue_pop_event(queue)))
7091 hr = MF_E_NO_EVENTS_AVAILABLE;
7093 else
7095 while (list_empty(&queue->events) && !queue->is_shut_down)
7097 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7099 *event = queue_pop_event(queue);
7100 if (queue->is_shut_down)
7101 hr = MF_E_SHUTDOWN;
7105 LeaveCriticalSection(&queue->cs);
7107 return hr;
7110 static void queue_notify_subscriber(struct event_queue *queue)
7112 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7113 return;
7115 queue->notified = TRUE;
7116 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7119 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7121 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7122 MFASYNCRESULT *result_data = (MFASYNCRESULT *)queue->subscriber;
7123 HRESULT hr;
7125 TRACE("%p, %p, %p.\n", iface, callback, state);
7127 if (!callback)
7128 return E_INVALIDARG;
7130 EnterCriticalSection(&queue->cs);
7132 if (queue->is_shut_down)
7133 hr = MF_E_SHUTDOWN;
7134 else if (result_data)
7136 if (result_data->pCallback == callback)
7137 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7138 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7139 else
7140 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7142 else
7144 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7145 if (SUCCEEDED(hr))
7146 queue_notify_subscriber(queue);
7149 LeaveCriticalSection(&queue->cs);
7151 return hr;
7154 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7156 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7157 HRESULT hr = E_FAIL;
7159 TRACE("%p, %p, %p.\n", iface, result, event);
7161 EnterCriticalSection(&queue->cs);
7163 if (queue->is_shut_down)
7164 hr = MF_E_SHUTDOWN;
7165 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7167 *event = queue_pop_event(queue);
7168 if (queue->subscriber)
7169 IRtwqAsyncResult_Release(queue->subscriber);
7170 queue->subscriber = NULL;
7171 queue->notified = FALSE;
7172 hr = *event ? S_OK : E_FAIL;
7175 LeaveCriticalSection(&queue->cs);
7177 return hr;
7180 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7182 struct queued_event *queued_event;
7183 HRESULT hr = S_OK;
7185 queued_event = heap_alloc(sizeof(*queued_event));
7186 if (!queued_event)
7187 return E_OUTOFMEMORY;
7189 queued_event->event = event;
7191 EnterCriticalSection(&queue->cs);
7193 if (queue->is_shut_down)
7194 hr = MF_E_SHUTDOWN;
7195 else
7197 IMFMediaEvent_AddRef(queued_event->event);
7198 list_add_tail(&queue->events, &queued_event->entry);
7199 queue_notify_subscriber(queue);
7202 LeaveCriticalSection(&queue->cs);
7204 if (FAILED(hr))
7205 heap_free(queued_event);
7207 WakeAllConditionVariable(&queue->update_event);
7209 return hr;
7212 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7214 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7216 TRACE("%p, %p.\n", iface, event);
7218 return eventqueue_queue_event(queue, event);
7221 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7222 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7224 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7225 IMFMediaEvent *event;
7226 HRESULT hr;
7228 TRACE("%p, %s, %s, %#x, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7229 debugstr_propvar(value));
7231 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7232 return hr;
7234 hr = eventqueue_queue_event(queue, event);
7235 IMFMediaEvent_Release(event);
7236 return hr;
7239 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7240 REFGUID extended_type, HRESULT status, IUnknown *unk)
7242 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7243 IMFMediaEvent *event;
7244 PROPVARIANT value;
7245 HRESULT hr;
7247 TRACE("%p, %s, %s, %#x, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7249 value.vt = VT_UNKNOWN;
7250 value.u.punkVal = unk;
7252 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7253 return hr;
7255 hr = eventqueue_queue_event(queue, event);
7256 IMFMediaEvent_Release(event);
7257 return hr;
7260 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7262 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7264 TRACE("%p\n", queue);
7266 EnterCriticalSection(&queue->cs);
7268 if (!queue->is_shut_down)
7270 event_queue_cleanup(queue);
7271 queue->is_shut_down = TRUE;
7274 LeaveCriticalSection(&queue->cs);
7276 WakeAllConditionVariable(&queue->update_event);
7278 return S_OK;
7281 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7283 eventqueue_QueryInterface,
7284 eventqueue_AddRef,
7285 eventqueue_Release,
7286 eventqueue_GetEvent,
7287 eventqueue_BeginGetEvent,
7288 eventqueue_EndGetEvent,
7289 eventqueue_QueueEvent,
7290 eventqueue_QueueEventParamVar,
7291 eventqueue_QueueEventParamUnk,
7292 eventqueue_Shutdown
7295 /***********************************************************************
7296 * MFCreateEventQueue (mfplat.@)
7298 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7300 struct event_queue *object;
7302 TRACE("%p\n", queue);
7304 object = heap_alloc_zero(sizeof(*object));
7305 if (!object)
7306 return E_OUTOFMEMORY;
7308 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7309 object->refcount = 1;
7310 list_init(&object->events);
7311 InitializeCriticalSection(&object->cs);
7312 InitializeConditionVariable(&object->update_event);
7314 *queue = &object->IMFMediaEventQueue_iface;
7316 return S_OK;
7319 struct collection
7321 IMFCollection IMFCollection_iface;
7322 LONG refcount;
7323 IUnknown **elements;
7324 size_t capacity;
7325 size_t count;
7328 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7330 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7333 static void collection_clear(struct collection *collection)
7335 size_t i;
7337 for (i = 0; i < collection->count; ++i)
7339 if (collection->elements[i])
7340 IUnknown_Release(collection->elements[i]);
7343 heap_free(collection->elements);
7344 collection->elements = NULL;
7345 collection->count = 0;
7346 collection->capacity = 0;
7349 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7351 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7353 if (IsEqualIID(riid, &IID_IMFCollection) ||
7354 IsEqualIID(riid, &IID_IUnknown))
7356 *out = iface;
7357 IMFCollection_AddRef(iface);
7358 return S_OK;
7361 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7362 *out = NULL;
7363 return E_NOINTERFACE;
7366 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7368 struct collection *collection = impl_from_IMFCollection(iface);
7369 ULONG refcount = InterlockedIncrement(&collection->refcount);
7371 TRACE("%p, %d.\n", collection, refcount);
7373 return refcount;
7376 static ULONG WINAPI collection_Release(IMFCollection *iface)
7378 struct collection *collection = impl_from_IMFCollection(iface);
7379 ULONG refcount = InterlockedDecrement(&collection->refcount);
7381 TRACE("%p, %d.\n", collection, refcount);
7383 if (!refcount)
7385 collection_clear(collection);
7386 heap_free(collection->elements);
7387 heap_free(collection);
7390 return refcount;
7393 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7395 struct collection *collection = impl_from_IMFCollection(iface);
7397 TRACE("%p, %p.\n", iface, count);
7399 if (!count)
7400 return E_POINTER;
7402 *count = collection->count;
7404 return S_OK;
7407 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7409 struct collection *collection = impl_from_IMFCollection(iface);
7411 TRACE("%p, %u, %p.\n", iface, idx, element);
7413 if (!element)
7414 return E_POINTER;
7416 if (idx >= collection->count)
7417 return E_INVALIDARG;
7419 *element = collection->elements[idx];
7420 if (*element)
7421 IUnknown_AddRef(*element);
7423 return *element ? S_OK : E_UNEXPECTED;
7426 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7428 struct collection *collection = impl_from_IMFCollection(iface);
7430 TRACE("%p, %p.\n", iface, element);
7432 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7433 sizeof(*collection->elements)))
7434 return E_OUTOFMEMORY;
7436 collection->elements[collection->count++] = element;
7437 if (element)
7438 IUnknown_AddRef(element);
7440 return S_OK;
7443 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7445 struct collection *collection = impl_from_IMFCollection(iface);
7446 size_t count;
7448 TRACE("%p, %u, %p.\n", iface, idx, element);
7450 if (!element)
7451 return E_POINTER;
7453 if (idx >= collection->count)
7454 return E_INVALIDARG;
7456 *element = collection->elements[idx];
7458 count = collection->count - idx - 1;
7459 if (count)
7460 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7461 collection->count--;
7463 return S_OK;
7466 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7468 struct collection *collection = impl_from_IMFCollection(iface);
7469 size_t i;
7471 TRACE("%p, %u, %p.\n", iface, idx, element);
7473 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7474 sizeof(*collection->elements)))
7475 return E_OUTOFMEMORY;
7477 if (idx < collection->count)
7479 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7480 (collection->count - idx) * sizeof(*collection->elements));
7481 collection->count++;
7483 else
7485 for (i = collection->count; i < idx; ++i)
7486 collection->elements[i] = NULL;
7487 collection->count = idx + 1;
7490 collection->elements[idx] = element;
7491 if (collection->elements[idx])
7492 IUnknown_AddRef(collection->elements[idx]);
7494 return S_OK;
7497 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7499 struct collection *collection = impl_from_IMFCollection(iface);
7501 TRACE("%p.\n", iface);
7503 collection_clear(collection);
7505 return S_OK;
7508 static const IMFCollectionVtbl mfcollectionvtbl =
7510 collection_QueryInterface,
7511 collection_AddRef,
7512 collection_Release,
7513 collection_GetElementCount,
7514 collection_GetElement,
7515 collection_AddElement,
7516 collection_RemoveElement,
7517 collection_InsertElementAt,
7518 collection_RemoveAllElements,
7521 /***********************************************************************
7522 * MFCreateCollection (mfplat.@)
7524 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7526 struct collection *object;
7528 TRACE("%p\n", collection);
7530 if (!collection)
7531 return E_POINTER;
7533 object = heap_alloc_zero(sizeof(*object));
7534 if (!object)
7535 return E_OUTOFMEMORY;
7537 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7538 object->refcount = 1;
7540 *collection = &object->IMFCollection_iface;
7542 return S_OK;
7545 /***********************************************************************
7546 * MFHeapAlloc (mfplat.@)
7548 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7550 TRACE("%lu, %#x, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7551 return HeapAlloc(GetProcessHeap(), flags, size);
7554 /***********************************************************************
7555 * MFHeapFree (mfplat.@)
7557 void WINAPI MFHeapFree(void *p)
7559 TRACE("%p\n", p);
7560 HeapFree(GetProcessHeap(), 0, p);
7563 /***********************************************************************
7564 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7566 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7568 FIXME("(%p, %p): stub\n", stream, bytestream);
7570 return E_NOTIMPL;
7573 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7575 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7577 if (IsEqualIID(riid, &IID_IMFClock) ||
7578 IsEqualIID(riid, &IID_IUnknown))
7580 *obj = iface;
7581 IMFClock_AddRef(iface);
7582 return S_OK;
7585 WARN("Unsupported %s.\n", debugstr_guid(riid));
7586 *obj = NULL;
7587 return E_NOINTERFACE;
7590 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7592 struct system_clock *clock = impl_from_IMFClock(iface);
7593 ULONG refcount = InterlockedIncrement(&clock->refcount);
7595 TRACE("%p, refcount %u.\n", iface, refcount);
7597 return refcount;
7600 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7602 struct system_clock *clock = impl_from_IMFClock(iface);
7603 ULONG refcount = InterlockedDecrement(&clock->refcount);
7605 TRACE("%p, refcount %u.\n", iface, refcount);
7607 if (!refcount)
7608 heap_free(clock);
7610 return refcount;
7613 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7615 TRACE("%p, %p.\n", iface, flags);
7617 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7618 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7620 return S_OK;
7623 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7624 MFTIME *system_time)
7626 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7628 *clock_time = *system_time = MFGetSystemTime();
7630 return S_OK;
7633 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7635 TRACE("%p, %p.\n", iface, key);
7637 *key = 0;
7639 return S_OK;
7642 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7644 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7646 *state = MFCLOCK_STATE_RUNNING;
7648 return S_OK;
7651 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7653 TRACE("%p, %p.\n", iface, props);
7655 if (!props)
7656 return E_POINTER;
7658 memset(props, 0, sizeof(*props));
7659 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7660 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7661 props->dwClockJitter = 1;
7663 return S_OK;
7666 static const IMFClockVtbl system_clock_vtbl =
7668 system_clock_QueryInterface,
7669 system_clock_AddRef,
7670 system_clock_Release,
7671 system_clock_GetClockCharacteristics,
7672 system_clock_GetCorrelatedTime,
7673 system_clock_GetContinuityKey,
7674 system_clock_GetState,
7675 system_clock_GetProperties,
7678 static HRESULT create_system_clock(IMFClock **clock)
7680 struct system_clock *object;
7682 if (!(object = heap_alloc(sizeof(*object))))
7683 return E_OUTOFMEMORY;
7685 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7686 object->refcount = 1;
7688 *clock = &object->IMFClock_iface;
7690 return S_OK;
7693 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7695 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7697 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7699 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7700 IsEqualIID(riid, &IID_IUnknown))
7702 *obj = &source->IMFPresentationTimeSource_iface;
7704 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
7706 *obj = &source->IMFClockStateSink_iface;
7708 else
7710 WARN("Unsupported %s.\n", debugstr_guid(riid));
7711 *obj = NULL;
7712 return E_NOINTERFACE;
7715 IUnknown_AddRef((IUnknown *)*obj);
7716 return S_OK;
7719 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
7721 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7722 ULONG refcount = InterlockedIncrement(&source->refcount);
7724 TRACE("%p, refcount %u.\n", iface, refcount);
7726 return refcount;
7729 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
7731 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7732 ULONG refcount = InterlockedDecrement(&source->refcount);
7734 TRACE("%p, refcount %u.\n", iface, refcount);
7736 if (!refcount)
7738 if (source->clock)
7739 IMFClock_Release(source->clock);
7740 DeleteCriticalSection(&source->cs);
7741 heap_free(source);
7744 return refcount;
7747 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
7749 TRACE("%p, %p.\n", iface, flags);
7751 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7753 return S_OK;
7756 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
7757 LONGLONG *clock_time, MFTIME *system_time)
7759 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7760 HRESULT hr;
7762 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7764 EnterCriticalSection(&source->cs);
7765 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
7767 if (source->state == MFCLOCK_STATE_RUNNING)
7769 system_time_source_apply_rate(source, clock_time);
7770 *clock_time += source->start_offset;
7772 else
7773 *clock_time = source->start_offset;
7775 LeaveCriticalSection(&source->cs);
7777 return hr;
7780 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
7782 TRACE("%p, %p.\n", iface, key);
7784 *key = 0;
7786 return S_OK;
7789 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
7790 MFCLOCK_STATE *state)
7792 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7794 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7796 EnterCriticalSection(&source->cs);
7797 *state = source->state;
7798 LeaveCriticalSection(&source->cs);
7800 return S_OK;
7803 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
7805 TRACE("%p, %p.\n", iface, props);
7807 if (!props)
7808 return E_POINTER;
7810 memset(props, 0, sizeof(*props));
7811 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7812 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7813 props->dwClockJitter = 1;
7815 return S_OK;
7818 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
7820 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7822 TRACE("%p, %p.\n", iface, clock);
7824 *clock = source->clock;
7825 IMFClock_AddRef(*clock);
7827 return S_OK;
7830 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
7832 system_time_source_QueryInterface,
7833 system_time_source_AddRef,
7834 system_time_source_Release,
7835 system_time_source_GetClockCharacteristics,
7836 system_time_source_GetCorrelatedTime,
7837 system_time_source_GetContinuityKey,
7838 system_time_source_GetState,
7839 system_time_source_GetProperties,
7840 system_time_source_GetUnderlyingClock,
7843 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
7845 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7846 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
7849 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
7851 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7852 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
7855 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
7857 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7858 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
7861 enum clock_command
7863 CLOCK_CMD_START = 0,
7864 CLOCK_CMD_STOP,
7865 CLOCK_CMD_PAUSE,
7866 CLOCK_CMD_RESTART,
7867 CLOCK_CMD_MAX,
7870 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
7872 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
7873 { /* S S* P R */
7874 /* INVALID */ { 1, 0, 1, 0 },
7875 /* RUNNING */ { 1, 1, 1, 0 },
7876 /* STOPPED */ { 1, 1, 0, 0 },
7877 /* PAUSED */ { 1, 1, 0, 1 },
7879 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
7881 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
7882 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
7883 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
7884 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
7887 /* Special case that go against usual state change vs return value behavior. */
7888 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
7889 return S_OK;
7891 if (!state_change_is_allowed[source->state][command])
7892 return MF_E_INVALIDREQUEST;
7894 source->state = states[command];
7896 return S_OK;
7899 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
7900 LONGLONG start_offset)
7902 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7903 MFCLOCK_STATE state;
7904 HRESULT hr;
7906 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
7908 EnterCriticalSection(&source->cs);
7909 state = source->state;
7910 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
7912 system_time_source_apply_rate(source, &system_time);
7913 if (start_offset == PRESENTATION_CURRENT_POSITION)
7915 switch (state)
7917 case MFCLOCK_STATE_RUNNING:
7918 break;
7919 case MFCLOCK_STATE_PAUSED:
7920 source->start_offset -= system_time;
7921 break;
7922 default:
7923 source->start_offset = -system_time;
7924 break;
7928 else
7930 source->start_offset = -system_time + start_offset;
7933 LeaveCriticalSection(&source->cs);
7935 return hr;
7938 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
7940 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7941 HRESULT hr;
7943 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7945 EnterCriticalSection(&source->cs);
7946 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
7947 source->start_offset = 0;
7948 LeaveCriticalSection(&source->cs);
7950 return hr;
7953 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
7955 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7956 HRESULT hr;
7958 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7960 EnterCriticalSection(&source->cs);
7961 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
7963 system_time_source_apply_rate(source, &system_time);
7964 source->start_offset += system_time;
7966 LeaveCriticalSection(&source->cs);
7968 return hr;
7971 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
7973 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7974 HRESULT hr;
7976 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7978 EnterCriticalSection(&source->cs);
7979 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
7981 system_time_source_apply_rate(source, &system_time);
7982 source->start_offset -= system_time;
7984 LeaveCriticalSection(&source->cs);
7986 return hr;
7989 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
7991 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7992 double intpart;
7994 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
7996 if (rate == 0.0f)
7997 return MF_E_UNSUPPORTED_RATE;
7999 modf(rate, &intpart);
8001 EnterCriticalSection(&source->cs);
8002 source->rate = rate;
8003 source->i_rate = rate == intpart ? rate : 0;
8004 LeaveCriticalSection(&source->cs);
8006 return S_OK;
8009 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8011 system_time_source_sink_QueryInterface,
8012 system_time_source_sink_AddRef,
8013 system_time_source_sink_Release,
8014 system_time_source_sink_OnClockStart,
8015 system_time_source_sink_OnClockStop,
8016 system_time_source_sink_OnClockPause,
8017 system_time_source_sink_OnClockRestart,
8018 system_time_source_sink_OnClockSetRate,
8021 /***********************************************************************
8022 * MFCreateSystemTimeSource (mfplat.@)
8024 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8026 struct system_time_source *object;
8027 HRESULT hr;
8029 TRACE("%p.\n", time_source);
8031 object = heap_alloc_zero(sizeof(*object));
8032 if (!object)
8033 return E_OUTOFMEMORY;
8035 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8036 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8037 object->refcount = 1;
8038 object->rate = 1.0f;
8039 object->i_rate = 1;
8040 InitializeCriticalSection(&object->cs);
8042 if (FAILED(hr = create_system_clock(&object->clock)))
8044 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8045 return hr;
8048 *time_source = &object->IMFPresentationTimeSource_iface;
8050 return S_OK;
8053 struct async_create_file
8055 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8056 LONG refcount;
8057 MF_FILE_ACCESSMODE access_mode;
8058 MF_FILE_OPENMODE open_mode;
8059 MF_FILE_FLAGS flags;
8060 WCHAR *path;
8063 struct async_create_file_result
8065 struct list entry;
8066 IRtwqAsyncResult *result;
8067 IMFByteStream *stream;
8070 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8071 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8073 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8075 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8078 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8080 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8081 IsEqualIID(riid, &IID_IUnknown))
8083 *obj = iface;
8084 IRtwqAsyncCallback_AddRef(iface);
8085 return S_OK;
8088 *obj = NULL;
8089 return E_NOINTERFACE;
8092 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8094 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8095 ULONG refcount = InterlockedIncrement(&async->refcount);
8097 TRACE("%p, refcount %u.\n", iface, refcount);
8099 return refcount;
8102 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8104 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8105 ULONG refcount = InterlockedDecrement(&async->refcount);
8107 TRACE("%p, refcount %u.\n", iface, refcount);
8109 if (!refcount)
8111 heap_free(async->path);
8112 heap_free(async);
8115 return refcount;
8118 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8120 return E_NOTIMPL;
8123 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8125 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8126 IRtwqAsyncResult *caller;
8127 IMFByteStream *stream;
8128 HRESULT hr;
8130 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8132 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8133 if (SUCCEEDED(hr))
8135 struct async_create_file_result *result_item;
8137 result_item = heap_alloc(sizeof(*result_item));
8138 if (result_item)
8140 result_item->result = caller;
8141 IRtwqAsyncResult_AddRef(caller);
8142 result_item->stream = stream;
8143 IMFByteStream_AddRef(stream);
8145 EnterCriticalSection(&async_create_file_cs);
8146 list_add_tail(&async_create_file_results, &result_item->entry);
8147 LeaveCriticalSection(&async_create_file_cs);
8150 IMFByteStream_Release(stream);
8152 else
8153 IRtwqAsyncResult_SetStatus(caller, hr);
8155 RtwqInvokeCallback(caller);
8157 return S_OK;
8160 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8162 async_create_file_callback_QueryInterface,
8163 async_create_file_callback_AddRef,
8164 async_create_file_callback_Release,
8165 async_create_file_callback_GetParameters,
8166 async_create_file_callback_Invoke,
8169 /***********************************************************************
8170 * MFBeginCreateFile (mfplat.@)
8172 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8173 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8175 struct async_create_file *async = NULL;
8176 IRtwqAsyncResult *caller, *item = NULL;
8177 HRESULT hr;
8179 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8180 cancel_cookie);
8182 if (cancel_cookie)
8183 *cancel_cookie = NULL;
8185 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8186 return hr;
8188 async = heap_alloc(sizeof(*async));
8189 if (!async)
8191 hr = E_OUTOFMEMORY;
8192 goto failed;
8195 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8196 async->refcount = 1;
8197 async->access_mode = access_mode;
8198 async->open_mode = open_mode;
8199 async->flags = flags;
8200 if (FAILED(hr = heap_strdupW(path, &async->path)))
8201 goto failed;
8203 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8204 if (FAILED(hr))
8205 goto failed;
8207 if (cancel_cookie)
8209 *cancel_cookie = (IUnknown *)caller;
8210 IUnknown_AddRef(*cancel_cookie);
8213 hr = RtwqInvokeCallback(item);
8215 failed:
8216 if (async)
8217 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8218 if (item)
8219 IRtwqAsyncResult_Release(item);
8220 if (caller)
8221 IRtwqAsyncResult_Release(caller);
8223 return hr;
8226 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8228 struct async_create_file_result *item;
8229 HRESULT hr = MF_E_UNEXPECTED;
8230 IRtwqAsyncResult *result;
8232 *stream = NULL;
8234 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8235 return hr;
8237 EnterCriticalSection(&async_create_file_cs);
8239 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8241 if (result == item->result)
8243 *stream = item->stream;
8244 IRtwqAsyncResult_Release(item->result);
8245 list_remove(&item->entry);
8246 heap_free(item);
8247 break;
8251 LeaveCriticalSection(&async_create_file_cs);
8253 if (*stream)
8254 hr = IRtwqAsyncResult_GetStatus(result);
8256 IRtwqAsyncResult_Release(result);
8258 return hr;
8261 /***********************************************************************
8262 * MFEndCreateFile (mfplat.@)
8264 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8266 TRACE("%p, %p.\n", result, stream);
8268 return async_create_file_pull_result((IUnknown *)result, stream);
8271 /***********************************************************************
8272 * MFCancelCreateFile (mfplat.@)
8274 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8276 IMFByteStream *stream = NULL;
8277 HRESULT hr;
8279 TRACE("%p.\n", cancel_cookie);
8281 hr = async_create_file_pull_result(cancel_cookie, &stream);
8283 if (stream)
8284 IMFByteStream_Release(stream);
8286 return hr;
8289 /***********************************************************************
8290 * MFRegisterLocalSchemeHandler (mfplat.@)
8292 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8294 struct local_handler *handler;
8295 HRESULT hr;
8297 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8299 if (!scheme || !activate)
8300 return E_INVALIDARG;
8302 if (!(handler = heap_alloc(sizeof(*handler))))
8303 return E_OUTOFMEMORY;
8305 if (FAILED(hr = heap_strdupW(scheme, &handler->u.scheme)))
8307 heap_free(handler);
8308 return hr;
8310 handler->activate = activate;
8311 IMFActivate_AddRef(handler->activate);
8313 EnterCriticalSection(&local_handlers_section);
8314 list_add_head(&local_scheme_handlers, &handler->entry);
8315 LeaveCriticalSection(&local_handlers_section);
8317 return S_OK;
8320 /***********************************************************************
8321 * MFRegisterLocalByteStreamHandler (mfplat.@)
8323 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8325 struct local_handler *handler;
8326 HRESULT hr;
8328 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8330 if ((!extension && !mime) || !activate)
8331 return E_INVALIDARG;
8333 if (!(handler = heap_alloc_zero(sizeof(*handler))))
8334 return E_OUTOFMEMORY;
8336 hr = heap_strdupW(extension, &handler->u.bytestream.extension);
8337 if (SUCCEEDED(hr))
8338 hr = heap_strdupW(mime, &handler->u.bytestream.mime);
8340 if (FAILED(hr))
8341 goto failed;
8343 EnterCriticalSection(&local_handlers_section);
8344 list_add_head(&local_bytestream_handlers, &handler->entry);
8345 LeaveCriticalSection(&local_handlers_section);
8347 return hr;
8349 failed:
8350 heap_free(handler->u.bytestream.extension);
8351 heap_free(handler->u.bytestream.mime);
8352 heap_free(handler);
8354 return hr;
8357 struct property_store
8359 IPropertyStore IPropertyStore_iface;
8360 LONG refcount;
8361 CRITICAL_SECTION cs;
8362 size_t count, capacity;
8363 struct
8365 PROPERTYKEY key;
8366 PROPVARIANT value;
8367 } *values;
8370 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8372 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8375 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8377 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8379 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8381 *obj = iface;
8382 IPropertyStore_AddRef(iface);
8383 return S_OK;
8386 *obj = NULL;
8387 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8388 return E_NOINTERFACE;
8391 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8393 struct property_store *store = impl_from_IPropertyStore(iface);
8394 ULONG refcount = InterlockedIncrement(&store->refcount);
8396 TRACE("%p, refcount %d.\n", iface, refcount);
8398 return refcount;
8401 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8403 struct property_store *store = impl_from_IPropertyStore(iface);
8404 ULONG refcount = InterlockedDecrement(&store->refcount);
8406 TRACE("%p, refcount %d.\n", iface, refcount);
8408 if (!refcount)
8410 DeleteCriticalSection(&store->cs);
8411 heap_free(store->values);
8412 heap_free(store);
8415 return refcount;
8418 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8420 struct property_store *store = impl_from_IPropertyStore(iface);
8422 TRACE("%p, %p.\n", iface, count);
8424 if (!count)
8425 return E_INVALIDARG;
8427 EnterCriticalSection(&store->cs);
8428 *count = store->count;
8429 LeaveCriticalSection(&store->cs);
8430 return S_OK;
8433 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8435 struct property_store *store = impl_from_IPropertyStore(iface);
8437 TRACE("%p, %u, %p.\n", iface, index, key);
8439 EnterCriticalSection(&store->cs);
8441 if (index >= store->count)
8443 LeaveCriticalSection(&store->cs);
8444 return E_INVALIDARG;
8447 *key = store->values[index].key;
8449 LeaveCriticalSection(&store->cs);
8450 return S_OK;
8453 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8455 struct property_store *store = impl_from_IPropertyStore(iface);
8456 unsigned int i;
8458 TRACE("%p, %p, %p.\n", iface, key, value);
8460 if (!value)
8461 return E_INVALIDARG;
8463 if (!key)
8464 return S_FALSE;
8466 EnterCriticalSection(&store->cs);
8468 for (i = 0; i < store->count; ++i)
8470 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8472 PropVariantCopy(value, &store->values[i].value);
8473 LeaveCriticalSection(&store->cs);
8474 return S_OK;
8478 LeaveCriticalSection(&store->cs);
8479 return S_FALSE;
8482 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8484 struct property_store *store = impl_from_IPropertyStore(iface);
8485 unsigned int i;
8487 TRACE("%p, %p, %p.\n", iface, key, value);
8489 EnterCriticalSection(&store->cs);
8491 for (i = 0; i < store->count; ++i)
8493 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8495 PropVariantCopy(&store->values[i].value, value);
8496 LeaveCriticalSection(&store->cs);
8497 return S_OK;
8501 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8503 LeaveCriticalSection(&store->cs);
8504 return E_OUTOFMEMORY;
8507 store->values[store->count].key = *key;
8508 PropVariantCopy(&store->values[store->count].value, value);
8509 ++store->count;
8511 LeaveCriticalSection(&store->cs);
8512 return S_OK;
8515 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8517 TRACE("%p.\n", iface);
8519 return E_NOTIMPL;
8522 static const IPropertyStoreVtbl property_store_vtbl =
8524 property_store_QueryInterface,
8525 property_store_AddRef,
8526 property_store_Release,
8527 property_store_GetCount,
8528 property_store_GetAt,
8529 property_store_GetValue,
8530 property_store_SetValue,
8531 property_store_Commit,
8534 /***********************************************************************
8535 * CreatePropertyStore (mfplat.@)
8537 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8539 struct property_store *object;
8541 TRACE("%p.\n", store);
8543 if (!store)
8544 return E_INVALIDARG;
8546 if (!(object = heap_alloc_zero(sizeof(*object))))
8547 return E_OUTOFMEMORY;
8549 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8550 object->refcount = 1;
8551 InitializeCriticalSection(&object->cs);
8553 TRACE("Created store %p.\n", object);
8554 *store = &object->IPropertyStore_iface;
8556 return S_OK;
8559 enum dxgi_device_handle_flags
8561 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8562 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8563 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8566 struct dxgi_device_manager
8568 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8569 LONG refcount;
8570 UINT token;
8571 IDXGIDevice *device;
8573 unsigned int *handles;
8574 size_t count;
8575 size_t capacity;
8577 unsigned int locks;
8578 unsigned int locking_tid;
8580 CRITICAL_SECTION cs;
8581 CONDITION_VARIABLE lock;
8584 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8586 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8589 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8591 if (!hdevice || hdevice > ULongToHandle(manager->count))
8592 return E_HANDLE;
8593 *idx = (ULONG_PTR)hdevice - 1;
8594 return S_OK;
8597 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8599 TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj);
8601 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8602 IsEqualGUID(riid, &IID_IUnknown))
8604 *obj = iface;
8605 IMFDXGIDeviceManager_AddRef(iface);
8606 return S_OK;
8609 WARN("Unsupported %s.\n", debugstr_guid(riid));
8610 *obj = NULL;
8611 return E_NOINTERFACE;
8614 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8616 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8617 ULONG refcount = InterlockedIncrement(&manager->refcount);
8619 TRACE("(%p) ref=%u.\n", iface, refcount);
8621 return refcount;
8624 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8626 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8627 ULONG refcount = InterlockedDecrement(&manager->refcount);
8629 TRACE("(%p) ref=%u.\n", iface, refcount);
8631 if (!refcount)
8633 if (manager->device)
8634 IDXGIDevice_Release(manager->device);
8635 DeleteCriticalSection(&manager->cs);
8636 heap_free(manager->handles);
8637 heap_free(manager);
8640 return refcount;
8643 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8645 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8646 return;
8648 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8649 manager->locks++;
8652 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8654 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8655 return;
8657 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8658 if (!--manager->locks)
8659 manager->locking_tid = 0;
8662 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8664 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8665 HRESULT hr;
8666 size_t idx;
8668 TRACE("%p, %p.\n", iface, hdevice);
8670 EnterCriticalSection(&manager->cs);
8672 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8674 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8676 dxgi_device_manager_unlock_handle(manager, idx);
8677 manager->handles[idx] = 0;
8678 if (idx == manager->count - 1)
8679 manager->count--;
8681 else
8682 hr = E_HANDLE;
8685 LeaveCriticalSection(&manager->cs);
8687 WakeAllConditionVariable(&manager->lock);
8689 return hr;
8692 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE device,
8693 REFIID riid, void **service)
8695 FIXME("(%p, %p, %s, %p): stub.\n", iface, device, debugstr_guid(riid), service);
8697 return E_NOTIMPL;
8700 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8701 REFIID riid, void **obj, BOOL block)
8703 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8704 HRESULT hr;
8705 size_t idx;
8707 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
8709 EnterCriticalSection(&manager->cs);
8711 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8713 if (!manager->device)
8715 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8717 else if (manager->locking_tid == GetCurrentThreadId())
8719 if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8720 dxgi_device_manager_lock_handle(manager, idx);
8722 else if (manager->locking_tid && !block)
8724 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
8726 else
8728 while (manager->locking_tid)
8730 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
8733 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8735 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8736 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8737 else if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8739 manager->locking_tid = GetCurrentThreadId();
8740 dxgi_device_manager_lock_handle(manager, idx);
8746 LeaveCriticalSection(&manager->cs);
8748 return hr;
8751 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
8753 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8754 HRESULT hr = S_OK;
8755 size_t i;
8757 TRACE("%p, %p.\n", iface, hdevice);
8759 *hdevice = NULL;
8761 EnterCriticalSection(&manager->cs);
8763 if (!manager->device)
8764 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8765 else
8767 for (i = 0; i < manager->count; ++i)
8769 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8771 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
8772 *hdevice = ULongToHandle(i + 1);
8773 break;
8777 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
8778 sizeof(*manager->handles)))
8780 *hdevice = ULongToHandle(manager->count + 1);
8781 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
8783 else
8784 hr = E_OUTOFMEMORY;
8787 LeaveCriticalSection(&manager->cs);
8789 return hr;
8792 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
8794 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8795 IDXGIDevice *dxgi_device;
8796 size_t i;
8798 TRACE("%p, %p, %u.\n", iface, device, token);
8800 if (!device || token != manager->token)
8801 return E_INVALIDARG;
8803 if (FAILED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device)))
8804 return E_INVALIDARG;
8806 EnterCriticalSection(&manager->cs);
8808 if (manager->device)
8810 for (i = 0; i < manager->count; ++i)
8812 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
8813 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8815 manager->locking_tid = 0;
8816 manager->locks = 0;
8817 IDXGIDevice_Release(manager->device);
8819 manager->device = dxgi_device;
8821 LeaveCriticalSection(&manager->cs);
8823 WakeAllConditionVariable(&manager->lock);
8825 return S_OK;
8828 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8830 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8831 HRESULT hr;
8832 size_t idx;
8834 TRACE("%p, %p.\n", iface, hdevice);
8836 EnterCriticalSection(&manager->cs);
8838 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8840 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8841 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8842 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8843 hr = E_HANDLE;
8846 LeaveCriticalSection(&manager->cs);
8848 return hr;
8851 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8852 BOOL savestate)
8854 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8855 HRESULT hr = E_FAIL;
8856 size_t idx;
8858 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
8860 EnterCriticalSection(&manager->cs);
8862 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8864 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
8865 if (SUCCEEDED(hr))
8866 dxgi_device_manager_unlock_handle(manager, idx);
8869 LeaveCriticalSection(&manager->cs);
8871 WakeAllConditionVariable(&manager->lock);
8873 return hr;
8876 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
8878 dxgi_device_manager_QueryInterface,
8879 dxgi_device_manager_AddRef,
8880 dxgi_device_manager_Release,
8881 dxgi_device_manager_CloseDeviceHandle,
8882 dxgi_device_manager_GetVideoService,
8883 dxgi_device_manager_LockDevice,
8884 dxgi_device_manager_OpenDeviceHandle,
8885 dxgi_device_manager_ResetDevice,
8886 dxgi_device_manager_TestDevice,
8887 dxgi_device_manager_UnlockDevice,
8890 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8892 struct dxgi_device_manager *object;
8894 TRACE("%p, %p.\n", token, manager);
8896 if (!token || !manager)
8897 return E_POINTER;
8899 object = heap_alloc(sizeof(*object));
8900 if (!object)
8901 return E_OUTOFMEMORY;
8903 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
8904 object->refcount = 1;
8905 object->token = GetTickCount();
8906 object->device = NULL;
8907 InitializeCriticalSection(&object->cs);
8908 InitializeConditionVariable(&object->lock);
8910 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
8912 *token = object->token;
8913 *manager = &object->IMFDXGIDeviceManager_iface;
8915 return S_OK;