ucrtbase/tests: Use public onexit table declarations.
[wine.git] / dlls / mfplat / main.c
bloba5c954161dc72d56d39fb27f5ce2758f00e6a354
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 "propvarutil.h"
43 #include "strsafe.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
47 static HRESULT heap_strdupW(const WCHAR *str, WCHAR **dest)
49 HRESULT hr = S_OK;
51 if (str)
53 unsigned int size;
55 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
56 *dest = heap_alloc(size);
57 if (*dest)
58 memcpy(*dest, str, size);
59 else
60 hr = E_OUTOFMEMORY;
62 else
63 *dest = NULL;
65 return hr;
68 struct local_handler
70 struct list entry;
71 union
73 WCHAR *scheme;
74 struct
76 WCHAR *extension;
77 WCHAR *mime;
78 } bytestream;
79 } u;
80 IMFActivate *activate;
83 static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
85 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
86 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
88 struct mft_registration
90 struct list entry;
91 IClassFactory *factory;
92 CLSID clsid;
93 GUID category;
94 WCHAR *name;
95 DWORD flags;
96 MFT_REGISTER_TYPE_INFO *input_types;
97 UINT32 input_types_count;
98 MFT_REGISTER_TYPE_INFO *output_types;
99 UINT32 output_types_count;
100 BOOL local;
103 static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
105 static struct list local_mfts = LIST_INIT(local_mfts);
107 struct transform_activate
109 struct attributes attributes;
110 IMFActivate IMFActivate_iface;
111 IClassFactory *factory;
112 IMFTransform *transform;
115 struct system_clock
117 IMFClock IMFClock_iface;
118 LONG refcount;
121 struct system_time_source
123 IMFPresentationTimeSource IMFPresentationTimeSource_iface;
124 IMFClockStateSink IMFClockStateSink_iface;
125 LONG refcount;
126 MFCLOCK_STATE state;
127 IMFClock *clock;
128 LONGLONG start_offset;
129 float rate;
130 int i_rate;
131 CRITICAL_SECTION cs;
134 static void system_time_source_apply_rate(const struct system_time_source *source, LONGLONG *value)
136 if (source->i_rate)
137 *value *= source->i_rate;
138 else
139 *value *= source->rate;
142 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
144 return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
147 static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
149 return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
152 static struct system_clock *impl_from_IMFClock(IMFClock *iface)
154 return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
157 static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface)
159 return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface);
162 static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out)
164 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
166 if (IsEqualIID(riid, &IID_IMFActivate) ||
167 IsEqualIID(riid, &IID_IMFAttributes) ||
168 IsEqualIID(riid, &IID_IUnknown))
170 *out = iface;
171 IMFActivate_AddRef(iface);
172 return S_OK;
175 WARN("Unsupported %s.\n", debugstr_guid(riid));
176 *out = NULL;
177 return E_NOINTERFACE;
180 static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface)
182 struct transform_activate *activate = impl_from_IMFActivate(iface);
183 ULONG refcount = InterlockedIncrement(&activate->attributes.ref);
185 TRACE("%p, refcount %u.\n", iface, refcount);
187 return refcount;
190 static ULONG WINAPI transform_activate_Release(IMFActivate *iface)
192 struct transform_activate *activate = impl_from_IMFActivate(iface);
193 ULONG refcount = InterlockedDecrement(&activate->attributes.ref);
195 TRACE("%p, refcount %u.\n", iface, refcount);
197 if (!refcount)
199 clear_attributes_object(&activate->attributes);
200 if (activate->factory)
201 IClassFactory_Release(activate->factory);
202 if (activate->transform)
203 IMFTransform_Release(activate->transform);
204 heap_free(activate);
207 return refcount;
210 static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
212 struct transform_activate *activate = impl_from_IMFActivate(iface);
214 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
216 return attributes_GetItem(&activate->attributes, key, value);
219 static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
221 struct transform_activate *activate = impl_from_IMFActivate(iface);
223 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
225 return attributes_GetItemType(&activate->attributes, key, type);
228 static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value,
229 BOOL *result)
231 struct transform_activate *activate = impl_from_IMFActivate(iface);
233 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
235 return attributes_CompareItem(&activate->attributes, key, value, result);
238 static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs,
239 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
241 struct transform_activate *activate = impl_from_IMFActivate(iface);
243 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
245 return attributes_Compare(&activate->attributes, theirs, match_type, ret);
248 static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
250 struct transform_activate *activate = impl_from_IMFActivate(iface);
252 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
254 return attributes_GetUINT32(&activate->attributes, key, value);
257 static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
259 struct transform_activate *activate = impl_from_IMFActivate(iface);
261 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
263 return attributes_GetUINT64(&activate->attributes, key, value);
266 static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value)
268 struct transform_activate *activate = impl_from_IMFActivate(iface);
270 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
272 return attributes_GetDouble(&activate->attributes, key, value);
275 static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
277 struct transform_activate *activate = impl_from_IMFActivate(iface);
279 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
281 return attributes_GetGUID(&activate->attributes, key, value);
284 static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
286 struct transform_activate *activate = impl_from_IMFActivate(iface);
288 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
290 return attributes_GetStringLength(&activate->attributes, key, length);
293 static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
294 UINT32 size, UINT32 *length)
296 struct transform_activate *activate = impl_from_IMFActivate(iface);
298 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
300 return attributes_GetString(&activate->attributes, key, value, size, length);
303 static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value,
304 UINT32 *length)
306 struct transform_activate *activate = impl_from_IMFActivate(iface);
308 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
310 return attributes_GetAllocatedString(&activate->attributes, key, value, length);
313 static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
315 struct transform_activate *activate = impl_from_IMFActivate(iface);
317 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
319 return attributes_GetBlobSize(&activate->attributes, key, size);
322 static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize,
323 UINT32 *blobsize)
325 struct transform_activate *activate = impl_from_IMFActivate(iface);
327 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
329 return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize);
332 static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
334 struct transform_activate *activate = impl_from_IMFActivate(iface);
336 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
338 return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size);
341 static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out)
343 struct transform_activate *activate = impl_from_IMFActivate(iface);
345 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
347 return attributes_GetUnknown(&activate->attributes, key, riid, out);
350 static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
352 struct transform_activate *activate = impl_from_IMFActivate(iface);
354 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
356 return attributes_SetItem(&activate->attributes, key, value);
359 static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key)
361 struct transform_activate *activate = impl_from_IMFActivate(iface);
363 TRACE("%p, %s.\n", iface, debugstr_attr(key));
365 return attributes_DeleteItem(&activate->attributes, key);
368 static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface)
370 struct transform_activate *activate = impl_from_IMFActivate(iface);
372 TRACE("%p.\n", iface);
374 return attributes_DeleteAllItems(&activate->attributes);
377 static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
379 struct transform_activate *activate = impl_from_IMFActivate(iface);
381 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
383 return attributes_SetUINT32(&activate->attributes, key, value);
386 static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
388 struct transform_activate *activate = impl_from_IMFActivate(iface);
390 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
392 return attributes_SetUINT64(&activate->attributes, key, value);
395 static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value)
397 struct transform_activate *activate = impl_from_IMFActivate(iface);
399 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
401 return attributes_SetDouble(&activate->attributes, key, value);
404 static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
406 struct transform_activate *activate = impl_from_IMFActivate(iface);
408 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
410 return attributes_SetGUID(&activate->attributes, key, value);
413 static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
415 struct transform_activate *activate = impl_from_IMFActivate(iface);
417 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
419 return attributes_SetString(&activate->attributes, key, value);
422 static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
424 struct transform_activate *activate = impl_from_IMFActivate(iface);
426 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
428 return attributes_SetBlob(&activate->attributes, key, buf, size);
431 static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
433 struct transform_activate *activate = impl_from_IMFActivate(iface);
435 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
437 return attributes_SetUnknown(&activate->attributes, key, unknown);
440 static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface)
442 struct transform_activate *activate = impl_from_IMFActivate(iface);
444 TRACE("%p.\n", iface);
446 return attributes_LockStore(&activate->attributes);
449 static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface)
451 struct transform_activate *activate = impl_from_IMFActivate(iface);
453 TRACE("%p.\n", iface);
455 return attributes_UnlockStore(&activate->attributes);
458 static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count)
460 struct transform_activate *activate = impl_from_IMFActivate(iface);
462 TRACE("%p, %p.\n", iface, count);
464 return attributes_GetCount(&activate->attributes, count);
467 static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key,
468 PROPVARIANT *value)
470 struct transform_activate *activate = impl_from_IMFActivate(iface);
472 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
474 return attributes_GetItemByIndex(&activate->attributes, index, key, value);
477 static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
479 struct transform_activate *activate = impl_from_IMFActivate(iface);
481 TRACE("%p, %p.\n", iface, dest);
483 return attributes_CopyAllItems(&activate->attributes, dest);
486 static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
488 struct transform_activate *activate = impl_from_IMFActivate(iface);
489 CLSID clsid;
490 HRESULT hr;
492 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
494 EnterCriticalSection(&activate->attributes.cs);
496 if (!activate->transform)
498 if (activate->factory)
500 if (FAILED(hr = IClassFactory_CreateInstance(activate->factory, NULL, &IID_IMFTransform,
501 (void **)&activate->transform)))
503 hr = MF_E_INVALIDREQUEST;
506 else
508 if (SUCCEEDED(hr = attributes_GetGUID(&activate->attributes, &MFT_TRANSFORM_CLSID_Attribute, &clsid)))
510 if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
511 (void **)&activate->transform)))
513 hr = MF_E_INVALIDREQUEST;
519 if (activate->transform)
520 hr = IMFTransform_QueryInterface(activate->transform, riid, obj);
522 LeaveCriticalSection(&activate->attributes.cs);
524 return hr;
527 static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface)
529 struct transform_activate *activate = impl_from_IMFActivate(iface);
531 TRACE("%p.\n", iface);
533 EnterCriticalSection(&activate->attributes.cs);
535 if (activate->transform)
537 IMFTransform_Release(activate->transform);
538 activate->transform = NULL;
541 LeaveCriticalSection(&activate->attributes.cs);
543 return S_OK;
546 static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface)
548 TRACE("%p.\n", iface);
550 return E_NOTIMPL;
553 static const IMFActivateVtbl transform_activate_vtbl =
555 transform_activate_QueryInterface,
556 transform_activate_AddRef,
557 transform_activate_Release,
558 transform_activate_GetItem,
559 transform_activate_GetItemType,
560 transform_activate_CompareItem,
561 transform_activate_Compare,
562 transform_activate_GetUINT32,
563 transform_activate_GetUINT64,
564 transform_activate_GetDouble,
565 transform_activate_GetGUID,
566 transform_activate_GetStringLength,
567 transform_activate_GetString,
568 transform_activate_GetAllocatedString,
569 transform_activate_GetBlobSize,
570 transform_activate_GetBlob,
571 transform_activate_GetAllocatedBlob,
572 transform_activate_GetUnknown,
573 transform_activate_SetItem,
574 transform_activate_DeleteItem,
575 transform_activate_DeleteAllItems,
576 transform_activate_SetUINT32,
577 transform_activate_SetUINT64,
578 transform_activate_SetDouble,
579 transform_activate_SetGUID,
580 transform_activate_SetString,
581 transform_activate_SetBlob,
582 transform_activate_SetUnknown,
583 transform_activate_LockStore,
584 transform_activate_UnlockStore,
585 transform_activate_GetCount,
586 transform_activate_GetItemByIndex,
587 transform_activate_CopyAllItems,
588 transform_activate_ActivateObject,
589 transform_activate_ShutdownObject,
590 transform_activate_DetachObject,
593 static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate)
595 struct transform_activate *object;
596 HRESULT hr;
598 object = heap_alloc_zero(sizeof(*object));
599 if (!object)
600 return E_OUTOFMEMORY;
602 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
604 heap_free(object);
605 return hr;
608 object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl;
609 object->factory = factory;
610 if (object->factory)
611 IClassFactory_AddRef(object->factory);
613 *activate = &object->IMFActivate_iface;
615 return S_OK;
618 HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate)
620 TRACE("%p.\n", activate);
622 return create_transform_activate(NULL, activate);
625 static const WCHAR transform_keyW[] = {'M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\\',
626 'T','r','a','n','s','f','o','r','m','s',0};
627 static const WCHAR categories_keyW[] = {'M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\\',
628 'T','r','a','n','s','f','o','r','m','s','\\',
629 'C','a','t','e','g','o','r','i','e','s',0};
630 static const WCHAR inputtypesW[] = {'I','n','p','u','t','T','y','p','e','s',0};
631 static const WCHAR outputtypesW[] = {'O','u','t','p','u','t','T','y','p','e','s',0};
632 static const WCHAR attributesW[] = {'A','t','t','r','i','b','u','t','e','s',0};
633 static const WCHAR mftflagsW[] = {'M','F','T','F','l','a','g','s',0};
634 static const WCHAR szGUIDFmt[] =
636 '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0',
637 '2','x','%','0','2','x','-','%','0','2','x','%','0','2','x','%','0','2',
638 'x','%','0','2','x','%','0','2','x','%','0','2','x',0
641 static const BYTE guid_conv_table[256] =
643 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
645 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
646 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
647 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
648 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
649 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
652 static WCHAR* GUIDToString(WCHAR *str, REFGUID guid)
654 swprintf(str, 39, szGUIDFmt, guid->Data1, guid->Data2,
655 guid->Data3, guid->Data4[0], guid->Data4[1],
656 guid->Data4[2], guid->Data4[3], guid->Data4[4],
657 guid->Data4[5], guid->Data4[6], guid->Data4[7]);
659 return str;
662 static inline BOOL is_valid_hex(WCHAR c)
664 if (!(((c >= '0') && (c <= '9')) ||
665 ((c >= 'a') && (c <= 'f')) ||
666 ((c >= 'A') && (c <= 'F'))))
667 return FALSE;
668 return TRUE;
671 static BOOL GUIDFromString(LPCWSTR s, GUID *id)
673 int i;
675 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
677 id->Data1 = 0;
678 for (i = 0; i < 8; i++)
680 if (!is_valid_hex(s[i])) return FALSE;
681 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
683 if (s[8]!='-') return FALSE;
685 id->Data2 = 0;
686 for (i = 9; i < 13; i++)
688 if (!is_valid_hex(s[i])) return FALSE;
689 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
691 if (s[13]!='-') return FALSE;
693 id->Data3 = 0;
694 for (i = 14; i < 18; i++)
696 if (!is_valid_hex(s[i])) return FALSE;
697 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
699 if (s[18]!='-') return FALSE;
701 for (i = 19; i < 36; i+=2)
703 if (i == 23)
705 if (s[i]!='-') return FALSE;
706 i++;
708 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
709 id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
712 if (!s[36]) return TRUE;
713 return FALSE;
716 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
718 switch (reason)
720 case DLL_WINE_PREATTACH:
721 return FALSE; /* prefer native version */
722 case DLL_PROCESS_ATTACH:
723 DisableThreadLibraryCalls(instance);
724 break;
727 return TRUE;
730 static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags,
731 UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
732 const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
734 static const WCHAR reg_format[] = {'%','s','\\','%','s',0};
735 HRESULT hr = S_OK;
736 HKEY hclsid = 0;
737 WCHAR buffer[64];
738 DWORD size, ret;
739 WCHAR str[250];
740 UINT8 *blob;
742 GUIDToString(buffer, clsid);
743 swprintf(str, ARRAY_SIZE(str), reg_format, transform_keyW, buffer);
745 if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)))
746 hr = HRESULT_FROM_WIN32(ret);
748 if (SUCCEEDED(hr))
750 size = (lstrlenW(name) + 1) * sizeof(WCHAR);
751 if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)))
752 hr = HRESULT_FROM_WIN32(ret);
755 if (SUCCEEDED(hr) && cinput && input_types)
757 size = cinput * sizeof(MFT_REGISTER_TYPE_INFO);
758 if ((ret = RegSetValueExW(hclsid, inputtypesW, 0, REG_BINARY, (BYTE *)input_types, size)))
759 hr = HRESULT_FROM_WIN32(ret);
762 if (SUCCEEDED(hr) && coutput && output_types)
764 size = coutput * sizeof(MFT_REGISTER_TYPE_INFO);
765 if ((ret = RegSetValueExW(hclsid, outputtypesW, 0, REG_BINARY, (BYTE *)output_types, size)))
766 hr = HRESULT_FROM_WIN32(ret);
769 if (SUCCEEDED(hr) && attributes)
771 if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size)))
773 if ((blob = heap_alloc(size)))
775 if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size)))
777 if ((ret = RegSetValueExW(hclsid, attributesW, 0, REG_BINARY, blob, size)))
778 hr = HRESULT_FROM_WIN32(ret);
780 heap_free(blob);
782 else
783 hr = E_OUTOFMEMORY;
787 if (SUCCEEDED(hr) && flags)
789 if ((ret = RegSetValueExW(hclsid, mftflagsW, 0, REG_DWORD, (BYTE *)&flags, sizeof(flags))))
790 hr = HRESULT_FROM_WIN32(ret);
793 RegCloseKey(hclsid);
794 return hr;
797 static HRESULT register_category(CLSID *clsid, GUID *category)
799 static const WCHAR reg_format[] = {'%','s','\\','%','s','\\','%','s',0};
800 HKEY htmp1;
801 WCHAR guid1[64], guid2[64];
802 WCHAR str[350];
804 GUIDToString(guid1, category);
805 GUIDToString(guid2, clsid);
807 swprintf(str, ARRAY_SIZE(str), reg_format, categories_keyW, guid1, guid2);
809 if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &htmp1))
810 return E_FAIL;
812 RegCloseKey(htmp1);
813 return S_OK;
816 /***********************************************************************
817 * MFTRegister (mfplat.@)
819 HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
820 MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
821 MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
823 HRESULT hr;
825 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category),
826 debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
828 hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes);
829 if(FAILED(hr))
830 ERR("Failed to write register transform\n");
832 if (SUCCEEDED(hr))
833 hr = register_category(&clsid, &category);
835 return hr;
838 static void release_mft_registration(struct mft_registration *mft)
840 if (mft->factory)
841 IClassFactory_Release(mft->factory);
842 heap_free(mft->name);
843 heap_free(mft->input_types);
844 heap_free(mft->output_types);
845 heap_free(mft);
848 static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
849 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
850 const MFT_REGISTER_TYPE_INFO *output_types)
852 struct mft_registration *mft, *cur, *unreg_mft = NULL;
853 HRESULT hr;
855 if (!factory && !clsid)
857 WARN("Can't register without factory or CLSID.\n");
858 return E_FAIL;
861 mft = heap_alloc_zero(sizeof(*mft));
862 if (!mft)
863 return E_OUTOFMEMORY;
865 mft->factory = factory;
866 if (mft->factory)
867 IClassFactory_AddRef(mft->factory);
868 if (clsid)
869 mft->clsid = *clsid;
870 mft->category = *category;
871 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
872 flags |= MFT_ENUM_FLAG_SYNCMFT;
873 mft->flags = flags;
874 mft->local = TRUE;
875 if (FAILED(hr = heap_strdupW(name, &mft->name)))
876 goto failed;
878 if (input_count && input_types)
880 mft->input_types_count = input_count;
881 if (!(mft->input_types = heap_calloc(mft->input_types_count, sizeof(*input_types))))
883 hr = E_OUTOFMEMORY;
884 goto failed;
886 memcpy(mft->input_types, input_types, mft->input_types_count * sizeof(*input_types));
889 if (output_count && output_types)
891 mft->output_types_count = output_count;
892 if (!(mft->output_types = heap_calloc(mft->output_types_count, sizeof(*output_types))))
894 hr = E_OUTOFMEMORY;
895 goto failed;
897 memcpy(mft->output_types, output_types, mft->output_types_count * sizeof(*output_types));
900 EnterCriticalSection(&local_mfts_section);
902 LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct mft_registration, entry)
904 if (cur->factory == factory)
906 unreg_mft = cur;
907 list_remove(&cur->entry);
908 break;
911 list_add_tail(&local_mfts, &mft->entry);
913 LeaveCriticalSection(&local_mfts_section);
915 if (unreg_mft)
916 release_mft_registration(unreg_mft);
918 failed:
919 if (FAILED(hr))
920 release_mft_registration(mft);
922 return hr;
925 HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name, UINT32 flags,
926 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
927 const MFT_REGISTER_TYPE_INFO *output_types)
929 TRACE("%p, %s, %s, %#x, %u, %p, %u, %p.\n", factory, debugstr_guid(category), debugstr_w(name), flags, input_count,
930 input_types, output_count, output_types);
932 return mft_register_local(factory, NULL, category, name, flags, input_count, input_types, output_count, output_types);
935 HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
936 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
937 const MFT_REGISTER_TYPE_INFO *output_types)
939 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
940 input_count, input_types, output_count, output_types);
942 return mft_register_local(NULL, clsid, category, name, flags, input_count, input_types, output_count, output_types);
945 static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
947 struct mft_registration *cur, *cur2;
948 BOOL unregister_all = !factory && !clsid;
949 struct list unreg;
951 list_init(&unreg);
953 EnterCriticalSection(&local_mfts_section);
955 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct mft_registration, entry)
957 if (!unregister_all)
959 if ((factory && cur->factory == factory) || IsEqualCLSID(&cur->clsid, clsid))
961 list_remove(&cur->entry);
962 list_add_tail(&unreg, &cur->entry);
963 break;
966 else
968 list_remove(&cur->entry);
969 list_add_tail(&unreg, &cur->entry);
973 LeaveCriticalSection(&local_mfts_section);
975 if (!unregister_all && list_empty(&unreg))
976 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
978 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct mft_registration, entry)
980 list_remove(&cur->entry);
981 release_mft_registration(cur);
984 return S_OK;
987 HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid)
989 TRACE("%s.\n", debugstr_guid(&clsid));
991 return mft_unregister_local(NULL, &clsid);
994 HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
996 TRACE("%p.\n", factory);
998 return mft_unregister_local(factory, NULL);
1001 MFTIME WINAPI MFGetSystemTime(void)
1003 MFTIME mf;
1005 TRACE("()\n");
1007 GetSystemTimeAsFileTime( (FILETIME*)&mf );
1009 return mf;
1012 static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *category, UINT32 flags,
1013 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1014 const MFT_REGISTER_TYPE_INFO *output_type)
1016 BOOL matching = TRUE;
1017 DWORD model;
1018 int i;
1020 if (!IsEqualGUID(category, &mft->category))
1021 return FALSE;
1023 /* Default model is synchronous. */
1024 model = mft->flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE);
1025 if (!model)
1026 model = MFT_ENUM_FLAG_SYNCMFT;
1027 if (!(model & flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1028 return FALSE;
1030 /* These flags should be explicitly enabled. */
1031 if (mft->flags & ~flags & (MFT_ENUM_FLAG_FIELDOFUSE | MFT_ENUM_FLAG_TRANSCODE_ONLY))
1032 return FALSE;
1034 if (flags & MFT_ENUM_FLAG_SORTANDFILTER && !mft->factory && plugin_control
1035 && IMFPluginControl_IsDisabled(plugin_control, MF_Plugin_Type_MFT, &mft->clsid) == S_OK)
1037 return FALSE;
1040 if (input_type)
1042 for (i = 0, matching = FALSE; input_type && i < mft->input_types_count; ++i)
1044 if (!memcmp(&mft->input_types[i], input_type, sizeof(*input_type)))
1046 matching = TRUE;
1047 break;
1052 if (output_type && matching)
1054 for (i = 0, matching = FALSE; i < mft->output_types_count; ++i)
1056 if (!memcmp(&mft->output_types[i], output_type, sizeof(*output_type)))
1058 matching = TRUE;
1059 break;
1064 return matching;
1067 static void mft_get_reg_type_info(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type,
1068 UINT32 *count)
1070 HKEY htransform, hfilter;
1071 DWORD reg_type, size;
1073 *type = NULL;
1074 *count = 0;
1076 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1077 return;
1079 if (RegOpenKeyW(htransform, clsidW, &hfilter))
1081 RegCloseKey(htransform);
1082 return;
1085 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, NULL, &size))
1086 goto out;
1088 if (reg_type != REG_BINARY)
1089 goto out;
1091 if (!size || size % sizeof(**type))
1092 goto out;
1094 if (!(*type = heap_alloc(size)))
1095 goto out;
1097 *count = size / sizeof(**type);
1099 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, (BYTE *)*type, &size))
1101 heap_free(*type);
1102 *type = NULL;
1103 *count = 0;
1106 out:
1107 RegCloseKey(hfilter);
1108 RegCloseKey(htransform);
1111 static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags)
1113 DWORD ret, reg_type, size;
1114 HKEY hroot, hmft;
1116 *flags = 0;
1118 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot))
1119 return;
1121 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1122 RegCloseKey(hroot);
1123 if (ret)
1124 return;
1126 reg_type = 0;
1127 if (!RegQueryValueExW(hmft, nameW, NULL, &reg_type, NULL, &size) && reg_type == REG_DWORD)
1128 RegQueryValueExW(hmft, nameW, NULL, &reg_type, (BYTE *)flags, &size);
1130 RegCloseKey(hmft);
1133 static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, UINT32 flags,
1134 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1135 const MFT_REGISTER_TYPE_INFO *output_type)
1137 struct mft_registration mft, *cur;
1138 HKEY hcategory, hlist;
1139 WCHAR clsidW[64];
1140 DWORD ret, size;
1141 int index = 0;
1143 if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1144 return E_FAIL;
1146 GUIDToString(clsidW, category);
1147 ret = RegOpenKeyW(hcategory, clsidW, &hlist);
1148 RegCloseKey(hcategory);
1149 if (ret)
1150 return E_FAIL;
1152 size = ARRAY_SIZE(clsidW);
1153 while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL))
1155 memset(&mft, 0, sizeof(mft));
1156 mft.category = *category;
1157 if (!GUIDFromString(clsidW, &mft.clsid))
1158 goto next;
1160 mft_get_reg_flags(clsidW, mftflagsW, &mft.flags);
1162 if (output_type)
1163 mft_get_reg_type_info(clsidW, outputtypesW, &mft.output_types, &mft.output_types_count);
1165 if (input_type)
1166 mft_get_reg_type_info(clsidW, inputtypesW, &mft.input_types, &mft.input_types_count);
1168 if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type))
1170 heap_free(mft.input_types);
1171 heap_free(mft.output_types);
1172 goto next;
1175 cur = heap_alloc(sizeof(*cur));
1176 /* Reuse allocated type arrays. */
1177 *cur = mft;
1178 list_add_tail(mfts, &cur->entry);
1180 next:
1181 size = ARRAY_SIZE(clsidW);
1182 index++;
1185 return S_OK;
1188 static BOOL mft_is_preferred(IMFPluginControl *plugin_control, const CLSID *clsid)
1190 CLSID preferred;
1191 WCHAR *selector;
1192 int index = 0;
1194 while (SUCCEEDED(IMFPluginControl_GetPreferredClsidByIndex(plugin_control, MF_Plugin_Type_MFT, index++, &selector,
1195 &preferred)))
1197 CoTaskMemFree(selector);
1199 if (IsEqualGUID(&preferred, clsid))
1200 return TRUE;
1203 return FALSE;
1206 static HRESULT mft_enum(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1207 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1209 IMFPluginControl *plugin_control = NULL;
1210 struct list mfts, mfts_sorted, *result = &mfts;
1211 struct mft_registration *mft, *mft2;
1212 unsigned int obj_count;
1213 HRESULT hr;
1215 *count = 0;
1216 *activate = NULL;
1218 if (!flags)
1219 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER;
1221 /* Synchronous processing is default. */
1222 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1223 flags |= MFT_ENUM_FLAG_SYNCMFT;
1225 if (FAILED(hr = MFGetPluginControl(&plugin_control)))
1227 WARN("Failed to get plugin control instance, hr %#x.\n", hr);
1228 return hr;
1231 list_init(&mfts);
1233 /* Collect from registry */
1234 mft_collect_machine_reg(&mfts, &category, flags, plugin_control, input_type, output_type);
1236 /* Collect locally registered ones. */
1237 if (flags & MFT_ENUM_FLAG_LOCALMFT)
1239 struct mft_registration *local;
1241 EnterCriticalSection(&local_mfts_section);
1243 LIST_FOR_EACH_ENTRY(local, &local_mfts, struct mft_registration, entry)
1245 if (mft_is_type_info_match(local, &category, flags, plugin_control, input_type, output_type))
1247 mft = heap_alloc_zero(sizeof(*mft));
1249 mft->clsid = local->clsid;
1250 mft->factory = local->factory;
1251 if (mft->factory)
1252 IClassFactory_AddRef(mft->factory);
1253 mft->flags = local->flags;
1254 mft->local = local->local;
1256 list_add_tail(&mfts, &mft->entry);
1260 LeaveCriticalSection(&local_mfts_section);
1263 list_init(&mfts_sorted);
1265 if (flags & MFT_ENUM_FLAG_SORTANDFILTER)
1267 /* Local registrations. */
1268 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1270 if (mft->local)
1272 list_remove(&mft->entry);
1273 list_add_tail(&mfts_sorted, &mft->entry);
1277 /* FIXME: Sort by merit value, for the ones that got it. Currently not handled. */
1279 /* Preferred transforms. */
1280 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1282 if (!mft->factory && mft_is_preferred(plugin_control, &mft->clsid))
1284 list_remove(&mft->entry);
1285 list_add_tail(&mfts_sorted, &mft->entry);
1289 /* Append the rest. */
1290 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1292 list_remove(&mft->entry);
1293 list_add_tail(&mfts_sorted, &mft->entry);
1296 result = &mfts_sorted;
1299 IMFPluginControl_Release(plugin_control);
1301 /* Create activation objects from CLSID/IClassFactory. */
1303 obj_count = list_count(result);
1305 if (obj_count)
1307 if (!(*activate = CoTaskMemAlloc(obj_count * sizeof(**activate))))
1308 hr = E_OUTOFMEMORY;
1310 obj_count = 0;
1312 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, result, struct mft_registration, entry)
1314 IMFActivate *mft_activate;
1316 if (*activate)
1318 if (SUCCEEDED(create_transform_activate(mft->factory, &mft_activate)))
1320 (*activate)[obj_count] = mft_activate;
1322 if (mft->local)
1324 IMFActivate_SetUINT32(mft_activate, &MFT_PROCESS_LOCAL_Attribute, 1);
1326 else
1328 if (mft->name)
1329 IMFActivate_SetString(mft_activate, &MFT_FRIENDLY_NAME_Attribute, mft->name);
1330 if (mft->input_types)
1331 IMFActivate_SetBlob(mft_activate, &MFT_INPUT_TYPES_Attributes, (const UINT8 *)mft->input_types,
1332 sizeof(*mft->input_types) * mft->input_types_count);
1333 if (mft->output_types)
1334 IMFActivate_SetBlob(mft_activate, &MFT_OUTPUT_TYPES_Attributes, (const UINT8 *)mft->output_types,
1335 sizeof(*mft->output_types) * mft->output_types_count);
1338 if (!mft->factory)
1339 IMFActivate_SetGUID(mft_activate, &MFT_TRANSFORM_CLSID_Attribute, &mft->clsid);
1341 IMFActivate_SetUINT32(mft_activate, &MF_TRANSFORM_FLAGS_Attribute, mft->flags);
1342 IMFActivate_SetGUID(mft_activate, &MF_TRANSFORM_CATEGORY_Attribute, &mft->category);
1344 obj_count++;
1348 list_remove(&mft->entry);
1349 release_mft_registration(mft);
1353 if (!obj_count)
1355 CoTaskMemFree(*activate);
1356 *activate = NULL;
1358 *count = obj_count;
1360 return hr;
1363 /***********************************************************************
1364 * MFTEnum (mfplat.@)
1366 HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
1367 MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count)
1369 struct mft_registration *mft, *mft2;
1370 unsigned int mft_count;
1371 struct list mfts;
1372 HRESULT hr;
1374 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1375 clsids, count);
1377 if (!clsids || !count)
1378 return E_INVALIDARG;
1380 *count = 0;
1382 list_init(&mfts);
1384 if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
1385 return hr;
1387 mft_count = list_count(&mfts);
1389 if (mft_count)
1391 if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
1392 hr = E_OUTOFMEMORY;
1394 mft_count = 0;
1395 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1397 if (*clsids)
1398 (*clsids)[mft_count++] = mft->clsid;
1399 list_remove(&mft->entry);
1400 release_mft_registration(mft);
1404 if (!mft_count)
1406 CoTaskMemFree(*clsids);
1407 *clsids = NULL;
1409 *count = mft_count;
1411 return hr;
1414 /***********************************************************************
1415 * MFTEnumEx (mfplat.@)
1417 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1418 const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count)
1420 TRACE("%s, %#x, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, activate, count);
1422 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1425 /***********************************************************************
1426 * MFTEnum2 (mfplat.@)
1428 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1429 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1431 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1432 activate, count);
1434 if (attributes)
1435 FIXME("Ignoring attributes.\n");
1437 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1440 /***********************************************************************
1441 * MFTUnregister (mfplat.@)
1443 HRESULT WINAPI MFTUnregister(CLSID clsid)
1445 WCHAR buffer[64], category[MAX_PATH];
1446 HKEY htransform, hcategory, htmp;
1447 DWORD size = MAX_PATH;
1448 DWORD index = 0;
1450 TRACE("(%s)\n", debugstr_guid(&clsid));
1452 GUIDToString(buffer, &clsid);
1454 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1456 RegDeleteKeyW(htransform, buffer);
1457 RegCloseKey(htransform);
1460 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1462 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1464 if (!RegOpenKeyW(hcategory, category, &htmp))
1466 RegDeleteKeyW(htmp, buffer);
1467 RegCloseKey(htmp);
1469 size = MAX_PATH;
1470 index++;
1472 RegCloseKey(hcategory);
1475 return S_OK;
1478 /***********************************************************************
1479 * MFStartup (mfplat.@)
1481 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1483 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1484 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1486 TRACE("%#x, %#x.\n", version, flags);
1488 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1489 return MF_E_BAD_STARTUP_VERSION;
1491 RtwqStartup();
1493 return S_OK;
1496 /***********************************************************************
1497 * MFShutdown (mfplat.@)
1499 HRESULT WINAPI MFShutdown(void)
1501 TRACE("\n");
1503 RtwqShutdown();
1505 return S_OK;
1508 /***********************************************************************
1509 * MFCopyImage (mfplat.@)
1511 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1513 TRACE("(%p, %d, %p, %d, %u, %u)\n", dest, deststride, src, srcstride, width, lines);
1515 while (lines--)
1517 memcpy(dest, src, width);
1518 dest += deststride;
1519 src += srcstride;
1522 return S_OK;
1525 struct guid_def
1527 const GUID *guid;
1528 const char *name;
1531 static int __cdecl debug_compare_guid(const void *a, const void *b)
1533 const GUID *guid = a;
1534 const struct guid_def *guid_def = b;
1535 return memcmp(guid, guid_def->guid, sizeof(*guid));
1538 const char *debugstr_attr(const GUID *guid)
1540 static const struct guid_def guid_defs[] =
1542 #define X(g) { &(g), #g }
1543 X(MF_READWRITE_MMCSS_CLASS),
1544 X(MF_TOPONODE_MARKIN_HERE),
1545 X(MF_TOPONODE_MARKOUT_HERE),
1546 X(MF_TOPONODE_DECODER),
1547 X(MF_TOPOLOGY_PROJECTSTART),
1548 X(MF_TOPOLOGY_PROJECTSTOP),
1549 X(MF_SINK_WRITER_ENCODER_CONFIG),
1550 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1551 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1552 X(MFT_PREFERRED_ENCODER_PROFILE),
1553 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1554 X(MF_MT_ALPHA_MODE),
1555 X(MF_PMP_SERVER_CONTEXT),
1556 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1557 X(MFT_CODEC_MERIT_Attribute),
1558 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1559 X(MF_LOW_LATENCY),
1560 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1561 X(MF_MT_PIXEL_ASPECT_RATIO),
1562 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1563 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1564 X(MF_MT_WRAPPED_TYPE),
1565 X(MF_MT_AVG_BITRATE),
1566 X(MFT_CONNECTED_TO_HW_STREAM),
1567 X(MF_SA_D3D_AWARE),
1568 X(MFT_TRANSFORM_CLSID_Attribute),
1569 X(MFT_TRANSFORM_CLSID_Attribute),
1570 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1571 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1572 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1573 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1574 X(MF_PD_PMPHOST_CONTEXT),
1575 X(MF_PD_APP_CONTEXT),
1576 X(MF_PD_DURATION),
1577 X(MF_PD_TOTAL_FILE_SIZE),
1578 X(MF_PD_AUDIO_ENCODING_BITRATE),
1579 X(MF_PD_VIDEO_ENCODING_BITRATE),
1580 X(MFSampleExtension_TargetGlobalLuminance),
1581 X(MF_PD_MIME_TYPE),
1582 X(MF_PD_LAST_MODIFIED_TIME),
1583 X(MF_PD_PLAYBACK_ELEMENT_ID),
1584 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1585 X(MF_PD_PREFERRED_LANGUAGE),
1586 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1587 X(MF_ACTIVATE_MFT_LOCKED),
1588 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1589 X(MF_MT_FRAME_SIZE),
1590 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1591 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1592 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1593 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1594 X(MF_MT_FRAME_RATE_RANGE_MAX),
1595 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1596 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1597 X(MF_TRANSFORM_CATEGORY_Attribute),
1598 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1599 X(MFSampleExtension_ForwardedDecodeUnits),
1600 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1601 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1602 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1603 X(MF_MT_VIDEO_ROTATION),
1604 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1605 X(MF_MT_USER_DATA),
1606 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1607 X(MF_MT_AUDIO_CHANNEL_MASK),
1608 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1609 X(MF_READWRITE_DISABLE_CONVERTERS),
1610 X(MFSampleExtension_Token),
1611 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1612 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1613 X(MF_TRANSFORM_ASYNC_UNLOCK),
1614 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1615 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1616 X(MFSampleExtension_3DVideo_SampleFormat),
1617 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1618 X(MF_MT_SAMPLE_SIZE),
1619 X(MF_MT_AAC_PAYLOAD_TYPE),
1620 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1621 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1622 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1623 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1624 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1625 X(MF_TRANSFORM_FLAGS_Attribute),
1626 X(MF_PD_SAMI_STYLELIST),
1627 X(MF_MT_AUDIO_WMADRC_AVGREF),
1628 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1629 X(MF_SD_LANGUAGE),
1630 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1631 X(MF_SD_PROTECTED),
1632 X(MF_SESSION_TOPOLOADER),
1633 X(MF_SESSION_GLOBAL_TIME),
1634 X(MF_SESSION_QUALITY_MANAGER),
1635 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1636 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1637 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1638 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1639 X(MF_BYTESTREAM_ORIGIN_NAME),
1640 X(MF_BYTESTREAM_CONTENT_TYPE),
1641 X(MF_MT_DEPTH_MEASUREMENT),
1642 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1643 X(MF_BYTESTREAM_DURATION),
1644 X(MF_SD_SAMI_LANGUAGE),
1645 X(MF_EVENT_OUTPUT_NODE),
1646 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1647 X(MFT_ENUM_ADAPTER_LUID),
1648 X(MF_MT_FRAME_RATE_RANGE_MIN),
1649 X(MF_BYTESTREAM_IFO_FILE_URI),
1650 X(MF_EVENT_TOPOLOGY_STATUS),
1651 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1652 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1653 X(MF_MT_MAJOR_TYPE),
1654 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1655 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1656 X(MF_SESSION_SERVER_CONTEXT),
1657 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1658 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1659 X(MF_PD_ADAPTIVE_STREAMING),
1660 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1661 X(MFSampleExtension_Timestamp),
1662 X(MF_TOPONODE_PRIMARYOUTPUT),
1663 X(MF_MT_SUBTYPE),
1664 X(MF_TRANSFORM_ASYNC),
1665 X(MF_TOPONODE_STREAMID),
1666 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1667 X(MF_SD_MUTUALLY_EXCLUSIVE),
1668 X(MF_SD_STREAM_NAME),
1669 X(MF_TOPONODE_RATELESS),
1670 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1671 X(MF_TOPONODE_DISABLE_PREROLL),
1672 X(MF_MT_VIDEO_3D_FORMAT),
1673 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1674 X(MF_SOURCE_READER_D3D_MANAGER),
1675 X(MF_SINK_WRITER_D3D_MANAGER),
1676 X(MFSampleExtension_3DVideo),
1677 X(MF_EVENT_SOURCE_FAKE_START),
1678 X(MF_EVENT_SOURCE_PROJECTSTART),
1679 X(MF_EVENT_SOURCE_ACTUAL_START),
1680 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1681 X(MFT_ENUM_HARDWARE_URL_Attribute),
1682 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1683 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1684 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1685 X(MFT_FRIENDLY_NAME_Attribute),
1686 X(MF_MT_FIXED_SIZE_SAMPLES),
1687 X(MFT_SUPPORT_3DVIDEO),
1688 X(MFT_SUPPORT_3DVIDEO),
1689 X(MFT_INPUT_TYPES_Attributes),
1690 X(MF_EVENT_SCRUBSAMPLE_TIME),
1691 X(MF_MT_INTERLACE_MODE),
1692 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1693 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1694 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1695 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1696 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1697 X(MFSampleExtension_ForwardedDecodeUnitType),
1698 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1699 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1700 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1701 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1702 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1703 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1704 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1705 X(MF_READWRITE_MMCSS_PRIORITY),
1706 X(MF_MT_VIDEO_3D),
1707 X(MF_EVENT_START_PRESENTATION_TIME),
1708 X(MF_EVENT_SESSIONCAPS),
1709 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1710 X(MF_EVENT_SESSIONCAPS_DELTA),
1711 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1712 X(MFSampleExtension_DecodeTimestamp),
1713 X(MF_MT_VIDEO_H264_NO_FMOASO),
1714 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1715 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1716 X(MF_READWRITE_D3D_OPTIONAL),
1717 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1718 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1719 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1720 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1721 X(MFT_PROCESS_LOCAL_Attribute),
1722 X(MFT_PROCESS_LOCAL_Attribute),
1723 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1724 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1725 X(MF_MT_FRAME_RATE),
1726 X(MF_TOPONODE_FLUSH),
1727 X(MF_TOPONODE_DRAIN),
1728 X(MF_TOPONODE_MEDIASTART),
1729 X(MF_TOPONODE_MEDIASTOP),
1730 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
1731 X(MF_TOPONODE_SOURCE),
1732 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
1733 X(MF_TOPONODE_D3DAWARE),
1734 X(MF_MT_COMPRESSED),
1735 X(MF_TOPONODE_STREAM_DESCRIPTOR),
1736 X(MF_TOPONODE_ERRORCODE),
1737 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
1738 X(MF_EVENT_MFT_CONTEXT),
1739 X(MF_MT_FORWARD_CUSTOM_SEI),
1740 X(MF_TOPONODE_CONNECT_METHOD),
1741 X(MFT_OUTPUT_TYPES_Attributes),
1742 X(MF_SESSION_REMOTE_SOURCE_MODE),
1743 X(MF_MT_DEPTH_VALUE_UNIT),
1744 X(MF_MT_AUDIO_NUM_CHANNELS),
1745 X(MF_TOPOLOGY_DXVA_MODE),
1746 X(MF_TOPONODE_LOCKED),
1747 X(MF_TOPONODE_WORKQUEUE_ID),
1748 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
1749 X(MF_TOPONODE_DECRYPTOR),
1750 X(MF_EVENT_DO_THINNING),
1751 X(MF_TOPONODE_DISCARDABLE),
1752 X(MF_TOPOLOGY_HARDWARE_MODE),
1753 X(MF_SOURCE_READER_DISABLE_DXVA),
1754 X(MF_MT_FORWARD_CUSTOM_NALU),
1755 X(MF_TOPONODE_ERROR_MAJORTYPE),
1756 X(MF_MT_SECURE),
1757 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
1758 X(MF_TOPONODE_ERROR_SUBTYPE),
1759 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
1760 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
1761 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
1762 #undef X
1764 struct guid_def *ret = NULL;
1766 if (guid)
1767 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
1769 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
1772 const char *debugstr_mf_guid(const GUID *guid)
1774 static const struct guid_def guid_defs[] =
1776 #define X(g) { &(g), #g }
1777 X(MFAudioFormat_ADTS),
1778 X(MFAudioFormat_PCM),
1779 X(MFAudioFormat_PCM_HDCP),
1780 X(MFAudioFormat_Float),
1781 X(MFAudioFormat_DTS),
1782 X(MFAudioFormat_DRM),
1783 X(MFAudioFormat_MSP1),
1784 X(MFAudioFormat_Vorbis),
1785 X(MFAudioFormat_AAC),
1786 X(MFVideoFormat_RGB24),
1787 X(MFVideoFormat_ARGB32),
1788 X(MFVideoFormat_RGB32),
1789 X(MFVideoFormat_RGB565),
1790 X(MFVideoFormat_RGB555),
1791 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
1792 X(MFVideoFormat_A2R10G10B10),
1793 X(MFMediaType_Script),
1794 X(MFMediaType_Image),
1795 X(MFMediaType_HTML),
1796 X(MFMediaType_Binary),
1797 X(MFVideoFormat_MPEG2),
1798 X(MFMediaType_FileTransfer),
1799 X(MFVideoFormat_RGB8),
1800 X(MFAudioFormat_Dolby_AC3),
1801 X(MFVideoFormat_L8),
1802 X(MFAudioFormat_LPCM),
1803 X(MFVideoFormat_420O),
1804 X(MFVideoFormat_AI44),
1805 X(MFVideoFormat_AV1),
1806 X(MFVideoFormat_AYUV),
1807 X(MFVideoFormat_H263),
1808 X(MFVideoFormat_H264),
1809 X(MFVideoFormat_H265),
1810 X(MFVideoFormat_HEVC),
1811 X(MFVideoFormat_HEVC_ES),
1812 X(MFVideoFormat_I420),
1813 X(MFVideoFormat_IYUV),
1814 X(MFVideoFormat_M4S2),
1815 X(MFVideoFormat_MJPG),
1816 X(MFVideoFormat_MP43),
1817 X(MFVideoFormat_MP4S),
1818 X(MFVideoFormat_MP4V),
1819 X(MFVideoFormat_MPG1),
1820 X(MFVideoFormat_MSS1),
1821 X(MFVideoFormat_MSS2),
1822 X(MFVideoFormat_NV11),
1823 X(MFVideoFormat_NV12),
1824 X(MFVideoFormat_ORAW),
1825 X(MFAudioFormat_Opus),
1826 X(MFVideoFormat_D16),
1827 X(MFAudioFormat_MPEG),
1828 X(MFVideoFormat_P010),
1829 X(MFVideoFormat_P016),
1830 X(MFVideoFormat_P210),
1831 X(MFVideoFormat_P216),
1832 X(MFVideoFormat_L16),
1833 X(MFAudioFormat_MP3),
1834 X(MFVideoFormat_UYVY),
1835 X(MFVideoFormat_VP10),
1836 X(MFVideoFormat_VP80),
1837 X(MFVideoFormat_VP90),
1838 X(MFVideoFormat_WMV1),
1839 X(MFVideoFormat_WMV2),
1840 X(MFVideoFormat_WMV3),
1841 X(MFVideoFormat_WVC1),
1842 X(MFVideoFormat_Y210),
1843 X(MFVideoFormat_Y216),
1844 X(MFVideoFormat_Y410),
1845 X(MFVideoFormat_Y416),
1846 X(MFVideoFormat_Y41P),
1847 X(MFVideoFormat_Y41T),
1848 X(MFVideoFormat_Y42T),
1849 X(MFVideoFormat_YUY2),
1850 X(MFVideoFormat_YV12),
1851 X(MFVideoFormat_YVU9),
1852 X(MFVideoFormat_YVYU),
1853 X(MFAudioFormat_WMAudioV8),
1854 X(MFAudioFormat_ALAC),
1855 X(MFAudioFormat_AMR_NB),
1856 X(MFMediaType_Audio),
1857 X(MFAudioFormat_WMAudioV9),
1858 X(MFAudioFormat_AMR_WB),
1859 X(MFAudioFormat_WMAudio_Lossless),
1860 X(MFAudioFormat_AMR_WP),
1861 X(MFAudioFormat_WMASPDIF),
1862 X(MFVideoFormat_DV25),
1863 X(MFVideoFormat_DV50),
1864 X(MFVideoFormat_DVC),
1865 X(MFVideoFormat_DVH1),
1866 X(MFVideoFormat_DVHD),
1867 X(MFVideoFormat_DVSD),
1868 X(MFVideoFormat_DVSL),
1869 X(MFVideoFormat_A16B16G16R16F),
1870 X(MFVideoFormat_v210),
1871 X(MFVideoFormat_v216),
1872 X(MFVideoFormat_v410),
1873 X(MFMediaType_Video),
1874 X(MFAudioFormat_AAC_HDCP),
1875 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
1876 X(MFAudioFormat_Dolby_AC3_HDCP),
1877 X(MFMediaType_Subtitle),
1878 X(MFMediaType_Stream),
1879 X(MFAudioFormat_Dolby_AC3_SPDIF),
1880 X(MFAudioFormat_Float_SpatialObjects),
1881 X(MFMediaType_SAMI),
1882 X(MFAudioFormat_ADTS_HDCP),
1883 X(MFAudioFormat_FLAC),
1884 X(MFAudioFormat_Dolby_DDPlus),
1885 X(MFMediaType_MultiplexedFrames),
1886 X(MFAudioFormat_Base_HDCP),
1887 X(MFVideoFormat_Base_HDCP),
1888 X(MFVideoFormat_H264_HDCP),
1889 X(MFVideoFormat_HEVC_HDCP),
1890 X(MFMediaType_Default),
1891 X(MFMediaType_Protected),
1892 X(MFVideoFormat_H264_ES),
1893 X(MFMediaType_Perception),
1894 #undef X
1896 struct guid_def *ret = NULL;
1898 if (guid)
1899 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
1901 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
1904 struct event_id
1906 DWORD id;
1907 const char *name;
1910 static int __cdecl debug_event_id(const void *a, const void *b)
1912 const DWORD *id = a;
1913 const struct event_id *event_id = b;
1914 return *id - event_id->id;
1917 static const char *debugstr_eventid(DWORD event)
1919 static const struct event_id
1921 DWORD id;
1922 const char *name;
1924 event_ids[] =
1926 #define X(e) { e, #e }
1927 X(MEUnknown),
1928 X(MEError),
1929 X(MEExtendedType),
1930 X(MENonFatalError),
1931 X(MESessionUnknown),
1932 X(MESessionTopologySet),
1933 X(MESessionTopologiesCleared),
1934 X(MESessionStarted),
1935 X(MESessionPaused),
1936 X(MESessionStopped),
1937 X(MESessionClosed),
1938 X(MESessionEnded),
1939 X(MESessionRateChanged),
1940 X(MESessionScrubSampleComplete),
1941 X(MESessionCapabilitiesChanged),
1942 X(MESessionTopologyStatus),
1943 X(MESessionNotifyPresentationTime),
1944 X(MENewPresentation),
1945 X(MELicenseAcquisitionStart),
1946 X(MELicenseAcquisitionCompleted),
1947 X(MEIndividualizationStart),
1948 X(MEIndividualizationCompleted),
1949 X(MEEnablerProgress),
1950 X(MEEnablerCompleted),
1951 X(MEPolicyError),
1952 X(MEPolicyReport),
1953 X(MEBufferingStarted),
1954 X(MEBufferingStopped),
1955 X(MEConnectStart),
1956 X(MEConnectEnd),
1957 X(MEReconnectStart),
1958 X(MEReconnectEnd),
1959 X(MERendererEvent),
1960 X(MESessionStreamSinkFormatChanged),
1961 X(MESourceUnknown),
1962 X(MESourceStarted),
1963 X(MEStreamStarted),
1964 X(MESourceSeeked),
1965 X(MEStreamSeeked),
1966 X(MENewStream),
1967 X(MEUpdatedStream),
1968 X(MESourceStopped),
1969 X(MEStreamStopped),
1970 X(MESourcePaused),
1971 X(MEStreamPaused),
1972 X(MEEndOfPresentation),
1973 X(MEEndOfStream),
1974 X(MEMediaSample),
1975 X(MEStreamTick),
1976 X(MEStreamThinMode),
1977 X(MEStreamFormatChanged),
1978 X(MESourceRateChanged),
1979 X(MEEndOfPresentationSegment),
1980 X(MESourceCharacteristicsChanged),
1981 X(MESourceRateChangeRequested),
1982 X(MESourceMetadataChanged),
1983 X(MESequencerSourceTopologyUpdated),
1984 X(MESinkUnknown),
1985 X(MEStreamSinkStarted),
1986 X(MEStreamSinkStopped),
1987 X(MEStreamSinkPaused),
1988 X(MEStreamSinkRateChanged),
1989 X(MEStreamSinkRequestSample),
1990 X(MEStreamSinkMarker),
1991 X(MEStreamSinkPrerolled),
1992 X(MEStreamSinkScrubSampleComplete),
1993 X(MEStreamSinkFormatChanged),
1994 X(MEStreamSinkDeviceChanged),
1995 X(MEQualityNotify),
1996 X(MESinkInvalidated),
1997 X(MEAudioSessionNameChanged),
1998 X(MEAudioSessionVolumeChanged),
1999 X(MEAudioSessionDeviceRemoved),
2000 X(MEAudioSessionServerShutdown),
2001 X(MEAudioSessionGroupingParamChanged),
2002 X(MEAudioSessionIconChanged),
2003 X(MEAudioSessionFormatChanged),
2004 X(MEAudioSessionDisconnected),
2005 X(MEAudioSessionExclusiveModeOverride),
2006 X(METrustUnknown),
2007 X(MEPolicyChanged),
2008 X(MEContentProtectionMessage),
2009 X(MEPolicySet),
2010 X(MEWMDRMLicenseBackupCompleted),
2011 X(MEWMDRMLicenseBackupProgress),
2012 X(MEWMDRMLicenseRestoreCompleted),
2013 X(MEWMDRMLicenseRestoreProgress),
2014 X(MEWMDRMLicenseAcquisitionCompleted),
2015 X(MEWMDRMIndividualizationCompleted),
2016 X(MEWMDRMIndividualizationProgress),
2017 X(MEWMDRMProximityCompleted),
2018 X(MEWMDRMLicenseStoreCleaned),
2019 X(MEWMDRMRevocationDownloadCompleted),
2020 #undef X
2023 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2024 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%u", event);
2027 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2029 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2032 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2034 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2036 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2037 IsEqualGUID(riid, &IID_IUnknown))
2039 *out = iface;
2040 IMFAttributes_AddRef(iface);
2041 return S_OK;
2044 WARN("Unsupported %s.\n", debugstr_guid(riid));
2045 *out = NULL;
2046 return E_NOINTERFACE;
2049 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2051 struct attributes *attributes = impl_from_IMFAttributes(iface);
2052 ULONG refcount = InterlockedIncrement(&attributes->ref);
2054 TRACE("%p, refcount %d.\n", iface, refcount);
2056 return refcount;
2059 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2061 struct attributes *attributes = impl_from_IMFAttributes(iface);
2062 ULONG refcount = InterlockedDecrement(&attributes->ref);
2064 TRACE("%p, refcount %d.\n", iface, refcount);
2066 if (!refcount)
2068 clear_attributes_object(attributes);
2069 heap_free(attributes);
2072 return refcount;
2075 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2077 size_t i;
2079 for (i = 0; i < attributes->count; ++i)
2081 if (IsEqualGUID(key, &attributes->attributes[i].key))
2083 if (index)
2084 *index = i;
2085 return &attributes->attributes[i];
2089 return NULL;
2092 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2094 struct attribute *attribute;
2095 HRESULT hr;
2097 EnterCriticalSection(&attributes->cs);
2099 attribute = attributes_find_item(attributes, key, NULL);
2100 if (attribute)
2102 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.u.punkVal))
2103 hr = PropVariantCopy(value, &attribute->value);
2104 else
2105 hr = MF_E_INVALIDTYPE;
2107 else
2108 hr = MF_E_ATTRIBUTENOTFOUND;
2110 LeaveCriticalSection(&attributes->cs);
2112 return hr;
2115 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2117 struct attribute *attribute;
2118 HRESULT hr;
2120 EnterCriticalSection(&attributes->cs);
2122 if ((attribute = attributes_find_item(attributes, key, NULL)))
2123 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2124 else
2125 hr = MF_E_ATTRIBUTENOTFOUND;
2127 LeaveCriticalSection(&attributes->cs);
2129 return hr;
2132 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2134 struct attribute *attribute;
2135 HRESULT hr = S_OK;
2137 EnterCriticalSection(&attributes->cs);
2139 if ((attribute = attributes_find_item(attributes, key, NULL)))
2141 *type = attribute->value.vt;
2143 else
2144 hr = MF_E_ATTRIBUTENOTFOUND;
2146 LeaveCriticalSection(&attributes->cs);
2148 return hr;
2151 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2153 struct attribute *attribute;
2155 *result = FALSE;
2157 EnterCriticalSection(&attributes->cs);
2159 if ((attribute = attributes_find_item(attributes, key, NULL)))
2161 *result = attribute->value.vt == value->vt &&
2162 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2165 LeaveCriticalSection(&attributes->cs);
2167 return S_OK;
2170 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2171 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2173 IMFAttributes *smaller, *other;
2174 MF_ATTRIBUTE_TYPE type;
2175 HRESULT hr = S_OK;
2176 UINT32 count;
2177 BOOL result;
2178 size_t i;
2180 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2181 return hr;
2183 EnterCriticalSection(&attributes->cs);
2185 result = TRUE;
2187 switch (match_type)
2189 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2190 for (i = 0; i < attributes->count; ++i)
2192 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2193 &attributes->attributes[i].value, &result)))
2194 break;
2195 if (!result)
2196 break;
2198 break;
2199 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2200 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2201 break;
2202 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2203 if (count != attributes->count)
2205 result = FALSE;
2206 break;
2208 for (i = 0; i < count; ++i)
2210 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2211 &attributes->attributes[i].value, &result)))
2212 break;
2213 if (!result)
2214 break;
2216 break;
2217 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2218 for (i = 0; i < attributes->count; ++i)
2220 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2221 continue;
2223 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2224 &attributes->attributes[i].value, &result)))
2225 break;
2227 if (!result)
2228 break;
2230 break;
2231 case MF_ATTRIBUTES_MATCH_SMALLER:
2232 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2233 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2234 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2235 break;
2236 default:
2237 WARN("Unknown match type %d.\n", match_type);
2238 hr = E_INVALIDARG;
2241 LeaveCriticalSection(&attributes->cs);
2243 if (SUCCEEDED(hr))
2244 *ret = result;
2246 return hr;
2249 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2251 PROPVARIANT attrval;
2252 HRESULT hr;
2254 PropVariantInit(&attrval);
2255 attrval.vt = VT_UI4;
2256 hr = attributes_get_item(attributes, key, &attrval);
2257 if (SUCCEEDED(hr))
2258 *value = attrval.u.ulVal;
2260 return hr;
2263 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2265 PROPVARIANT attrval;
2266 HRESULT hr;
2268 PropVariantInit(&attrval);
2269 attrval.vt = VT_UI8;
2270 hr = attributes_get_item(attributes, key, &attrval);
2271 if (SUCCEEDED(hr))
2272 *value = attrval.u.uhVal.QuadPart;
2274 return hr;
2277 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2279 PROPVARIANT attrval;
2280 HRESULT hr;
2282 PropVariantInit(&attrval);
2283 attrval.vt = VT_R8;
2284 hr = attributes_get_item(attributes, key, &attrval);
2285 if (SUCCEEDED(hr))
2286 *value = attrval.u.dblVal;
2288 return hr;
2291 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
2293 struct attribute *attribute;
2294 HRESULT hr = S_OK;
2296 EnterCriticalSection(&attributes->cs);
2298 attribute = attributes_find_item(attributes, key, NULL);
2299 if (attribute)
2301 if (attribute->value.vt == MF_ATTRIBUTE_GUID)
2302 *value = *attribute->value.u.puuid;
2303 else
2304 hr = MF_E_INVALIDTYPE;
2306 else
2307 hr = MF_E_ATTRIBUTENOTFOUND;
2309 LeaveCriticalSection(&attributes->cs);
2311 return hr;
2314 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2316 struct attribute *attribute;
2317 HRESULT hr = S_OK;
2319 EnterCriticalSection(&attributes->cs);
2321 attribute = attributes_find_item(attributes, key, NULL);
2322 if (attribute)
2324 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2325 *length = lstrlenW(attribute->value.u.pwszVal);
2326 else
2327 hr = MF_E_INVALIDTYPE;
2329 else
2330 hr = MF_E_ATTRIBUTENOTFOUND;
2332 LeaveCriticalSection(&attributes->cs);
2334 return hr;
2337 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2338 UINT32 size, UINT32 *length)
2340 struct attribute *attribute;
2341 HRESULT hr = S_OK;
2343 EnterCriticalSection(&attributes->cs);
2345 attribute = attributes_find_item(attributes, key, NULL);
2346 if (attribute)
2348 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2350 int len = lstrlenW(attribute->value.u.pwszVal);
2352 if (length)
2353 *length = len;
2355 if (size <= len)
2356 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2357 else
2358 memcpy(value, attribute->value.u.pwszVal, (len + 1) * sizeof(WCHAR));
2360 else
2361 hr = MF_E_INVALIDTYPE;
2363 else
2364 hr = MF_E_ATTRIBUTENOTFOUND;
2366 LeaveCriticalSection(&attributes->cs);
2368 return hr;
2371 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2373 PROPVARIANT attrval;
2374 HRESULT hr;
2376 PropVariantInit(&attrval);
2377 attrval.vt = VT_LPWSTR;
2378 hr = attributes_get_item(attributes, key, &attrval);
2379 if (SUCCEEDED(hr))
2381 *value = attrval.u.pwszVal;
2382 *length = lstrlenW(*value);
2385 return hr;
2388 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2390 struct attribute *attribute;
2391 HRESULT hr = S_OK;
2393 EnterCriticalSection(&attributes->cs);
2395 attribute = attributes_find_item(attributes, key, NULL);
2396 if (attribute)
2398 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2399 *size = attribute->value.u.caub.cElems;
2400 else
2401 hr = MF_E_INVALIDTYPE;
2403 else
2404 hr = MF_E_ATTRIBUTENOTFOUND;
2406 LeaveCriticalSection(&attributes->cs);
2408 return hr;
2411 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2413 struct attribute *attribute;
2414 HRESULT hr;
2416 EnterCriticalSection(&attributes->cs);
2418 attribute = attributes_find_item(attributes, key, NULL);
2419 if (attribute)
2421 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2423 UINT32 size = attribute->value.u.caub.cElems;
2425 if (bufsize >= size)
2426 hr = PropVariantToBuffer(&attribute->value, buf, size);
2427 else
2428 hr = E_NOT_SUFFICIENT_BUFFER;
2430 if (blobsize)
2431 *blobsize = size;
2433 else
2434 hr = MF_E_INVALIDTYPE;
2436 else
2437 hr = MF_E_ATTRIBUTENOTFOUND;
2439 LeaveCriticalSection(&attributes->cs);
2441 return hr;
2444 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2446 PROPVARIANT attrval;
2447 HRESULT hr;
2449 attrval.vt = VT_VECTOR | VT_UI1;
2450 hr = attributes_get_item(attributes, key, &attrval);
2451 if (SUCCEEDED(hr))
2453 *buf = attrval.u.caub.pElems;
2454 *size = attrval.u.caub.cElems;
2457 return hr;
2460 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2462 PROPVARIANT attrval;
2463 HRESULT hr;
2465 PropVariantInit(&attrval);
2466 attrval.vt = VT_UNKNOWN;
2467 hr = attributes_get_item(attributes, key, &attrval);
2468 if (SUCCEEDED(hr))
2469 hr = IUnknown_QueryInterface(attrval.u.punkVal, riid, out);
2470 PropVariantClear(&attrval);
2471 return hr;
2474 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2476 struct attribute *attribute;
2478 EnterCriticalSection(&attributes->cs);
2480 attribute = attributes_find_item(attributes, key, NULL);
2481 if (!attribute)
2483 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2484 sizeof(*attributes->attributes)))
2486 LeaveCriticalSection(&attributes->cs);
2487 return E_OUTOFMEMORY;
2489 attributes->attributes[attributes->count].key = *key;
2490 attribute = &attributes->attributes[attributes->count++];
2492 else
2493 PropVariantClear(&attribute->value);
2495 PropVariantCopy(&attribute->value, value);
2497 LeaveCriticalSection(&attributes->cs);
2499 return S_OK;
2502 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2504 PROPVARIANT empty;
2506 switch (value->vt)
2508 case MF_ATTRIBUTE_UINT32:
2509 case MF_ATTRIBUTE_UINT64:
2510 case MF_ATTRIBUTE_DOUBLE:
2511 case MF_ATTRIBUTE_GUID:
2512 case MF_ATTRIBUTE_STRING:
2513 case MF_ATTRIBUTE_BLOB:
2514 case MF_ATTRIBUTE_IUNKNOWN:
2515 return attributes_set_item(attributes, key, value);
2516 default:
2517 PropVariantInit(&empty);
2518 attributes_set_item(attributes, key, &empty);
2519 return MF_E_INVALIDTYPE;
2523 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2525 struct attribute *attribute;
2526 size_t index = 0;
2528 EnterCriticalSection(&attributes->cs);
2530 if ((attribute = attributes_find_item(attributes, key, &index)))
2532 size_t count;
2534 PropVariantClear(&attribute->value);
2536 attributes->count--;
2537 count = attributes->count - index;
2538 if (count)
2539 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2542 LeaveCriticalSection(&attributes->cs);
2544 return S_OK;
2547 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2549 EnterCriticalSection(&attributes->cs);
2551 while (attributes->count)
2553 PropVariantClear(&attributes->attributes[--attributes->count].value);
2555 heap_free(attributes->attributes);
2556 attributes->attributes = NULL;
2557 attributes->capacity = 0;
2559 LeaveCriticalSection(&attributes->cs);
2561 return S_OK;
2564 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2566 PROPVARIANT attrval;
2568 attrval.vt = VT_UI4;
2569 attrval.u.ulVal = value;
2570 return attributes_set_item(attributes, key, &attrval);
2573 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2575 PROPVARIANT attrval;
2577 attrval.vt = VT_UI8;
2578 attrval.u.uhVal.QuadPart = value;
2579 return attributes_set_item(attributes, key, &attrval);
2582 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2584 PROPVARIANT attrval;
2586 attrval.vt = VT_R8;
2587 attrval.u.dblVal = value;
2588 return attributes_set_item(attributes, key, &attrval);
2591 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2593 PROPVARIANT attrval;
2595 attrval.vt = VT_CLSID;
2596 attrval.u.puuid = (CLSID *)value;
2597 return attributes_set_item(attributes, key, &attrval);
2600 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2602 PROPVARIANT attrval;
2604 attrval.vt = VT_LPWSTR;
2605 attrval.u.pwszVal = (WCHAR *)value;
2606 return attributes_set_item(attributes, key, &attrval);
2609 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2611 PROPVARIANT attrval;
2613 attrval.vt = VT_VECTOR | VT_UI1;
2614 attrval.u.caub.cElems = size;
2615 attrval.u.caub.pElems = (UINT8 *)buf;
2616 return attributes_set_item(attributes, key, &attrval);
2619 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2621 PROPVARIANT attrval;
2623 attrval.vt = VT_UNKNOWN;
2624 attrval.u.punkVal = unknown;
2625 return attributes_set_item(attributes, key, &attrval);
2628 HRESULT attributes_LockStore(struct attributes *attributes)
2630 EnterCriticalSection(&attributes->cs);
2632 return S_OK;
2635 HRESULT attributes_UnlockStore(struct attributes *attributes)
2637 LeaveCriticalSection(&attributes->cs);
2639 return S_OK;
2642 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2644 EnterCriticalSection(&attributes->cs);
2645 *count = attributes->count;
2646 LeaveCriticalSection(&attributes->cs);
2648 return S_OK;
2651 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2653 HRESULT hr = S_OK;
2655 EnterCriticalSection(&attributes->cs);
2657 if (index < attributes->count)
2659 *key = attributes->attributes[index].key;
2660 if (value)
2661 PropVariantCopy(value, &attributes->attributes[index].value);
2663 else
2664 hr = E_INVALIDARG;
2666 LeaveCriticalSection(&attributes->cs);
2668 return hr;
2671 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2673 HRESULT hr = S_OK;
2674 size_t i;
2676 EnterCriticalSection(&attributes->cs);
2678 IMFAttributes_LockStore(dest);
2680 IMFAttributes_DeleteAllItems(dest);
2682 for (i = 0; i < attributes->count; ++i)
2684 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2685 if (FAILED(hr))
2686 break;
2689 IMFAttributes_UnlockStore(dest);
2691 LeaveCriticalSection(&attributes->cs);
2693 return hr;
2696 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2698 struct attributes *attributes = impl_from_IMFAttributes(iface);
2700 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2702 return attributes_GetItem(attributes, key, value);
2705 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2707 struct attributes *attributes = impl_from_IMFAttributes(iface);
2709 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
2711 return attributes_GetItemType(attributes, key, type);
2714 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
2716 struct attributes *attributes = impl_from_IMFAttributes(iface);
2718 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
2720 return attributes_CompareItem(attributes, key, value, result);
2723 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2724 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2726 struct attributes *attributes = impl_from_IMFAttributes(iface);
2728 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
2730 return attributes_Compare(attributes, theirs, match_type, ret);
2733 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2735 struct attributes *attributes = impl_from_IMFAttributes(iface);
2737 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2739 return attributes_GetUINT32(attributes, key, value);
2742 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2744 struct attributes *attributes = impl_from_IMFAttributes(iface);
2746 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2748 return attributes_GetUINT64(attributes, key, value);
2751 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2753 struct attributes *attributes = impl_from_IMFAttributes(iface);
2755 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2757 return attributes_GetDouble(attributes, key, value);
2760 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2762 struct attributes *attributes = impl_from_IMFAttributes(iface);
2764 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2766 return attributes_GetGUID(attributes, key, value);
2769 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
2771 struct attributes *attributes = impl_from_IMFAttributes(iface);
2773 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
2775 return attributes_GetStringLength(attributes, key, length);
2778 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2779 UINT32 size, UINT32 *length)
2781 struct attributes *attributes = impl_from_IMFAttributes(iface);
2783 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
2785 return attributes_GetString(attributes, key, value, size, length);
2788 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
2790 struct attributes *attributes = impl_from_IMFAttributes(iface);
2792 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
2794 return attributes_GetAllocatedString(attributes, key, value, length);
2797 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2799 struct attributes *attributes = impl_from_IMFAttributes(iface);
2801 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
2803 return attributes_GetBlobSize(attributes, key, size);
2806 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2807 UINT32 bufsize, UINT32 *blobsize)
2809 struct attributes *attributes = impl_from_IMFAttributes(iface);
2811 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
2813 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
2816 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
2818 struct attributes *attributes = impl_from_IMFAttributes(iface);
2820 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
2822 return attributes_GetAllocatedBlob(attributes, key, buf, size);
2825 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2827 struct attributes *attributes = impl_from_IMFAttributes(iface);
2829 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
2831 return attributes_GetUnknown(attributes, key, riid, out);
2834 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2836 struct attributes *attributes = impl_from_IMFAttributes(iface);
2838 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
2840 return attributes_SetItem(attributes, key, value);
2843 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2845 struct attributes *attributes = impl_from_IMFAttributes(iface);
2847 TRACE("%p, %s.\n", iface, debugstr_attr(key));
2849 return attributes_DeleteItem(attributes, key);
2852 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
2854 struct attributes *attributes = impl_from_IMFAttributes(iface);
2856 TRACE("%p.\n", iface);
2858 return attributes_DeleteAllItems(attributes);
2861 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2863 struct attributes *attributes = impl_from_IMFAttributes(iface);
2865 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
2867 return attributes_SetUINT32(attributes, key, value);
2870 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
2872 struct attributes *attributes = impl_from_IMFAttributes(iface);
2874 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
2876 return attributes_SetUINT64(attributes, key, value);
2879 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
2881 struct attributes *attributes = impl_from_IMFAttributes(iface);
2883 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
2885 return attributes_SetDouble(attributes, key, value);
2888 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
2890 struct attributes *attributes = impl_from_IMFAttributes(iface);
2892 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
2894 return attributes_SetGUID(attributes, key, value);
2897 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
2899 struct attributes *attributes = impl_from_IMFAttributes(iface);
2901 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
2903 return attributes_SetString(attributes, key, value);
2906 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
2908 struct attributes *attributes = impl_from_IMFAttributes(iface);
2910 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
2912 return attributes_SetBlob(attributes, key, buf, size);
2915 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
2917 struct attributes *attributes = impl_from_IMFAttributes(iface);
2919 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
2921 return attributes_SetUnknown(attributes, key, unknown);
2924 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
2926 struct attributes *attributes = impl_from_IMFAttributes(iface);
2928 TRACE("%p.\n", iface);
2930 return attributes_LockStore(attributes);
2933 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
2935 struct attributes *attributes = impl_from_IMFAttributes(iface);
2937 TRACE("%p.\n", iface);
2939 return attributes_UnlockStore(attributes);
2942 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
2944 struct attributes *attributes = impl_from_IMFAttributes(iface);
2946 TRACE("%p, %p.\n", iface, count);
2948 return attributes_GetCount(attributes, count);
2951 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
2953 struct attributes *attributes = impl_from_IMFAttributes(iface);
2955 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
2957 return attributes_GetItemByIndex(attributes, index, key, value);
2960 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
2962 struct attributes *attributes = impl_from_IMFAttributes(iface);
2964 TRACE("%p, %p.\n", iface, dest);
2966 return attributes_CopyAllItems(attributes, dest);
2969 static const IMFAttributesVtbl mfattributes_vtbl =
2971 mfattributes_QueryInterface,
2972 mfattributes_AddRef,
2973 mfattributes_Release,
2974 mfattributes_GetItem,
2975 mfattributes_GetItemType,
2976 mfattributes_CompareItem,
2977 mfattributes_Compare,
2978 mfattributes_GetUINT32,
2979 mfattributes_GetUINT64,
2980 mfattributes_GetDouble,
2981 mfattributes_GetGUID,
2982 mfattributes_GetStringLength,
2983 mfattributes_GetString,
2984 mfattributes_GetAllocatedString,
2985 mfattributes_GetBlobSize,
2986 mfattributes_GetBlob,
2987 mfattributes_GetAllocatedBlob,
2988 mfattributes_GetUnknown,
2989 mfattributes_SetItem,
2990 mfattributes_DeleteItem,
2991 mfattributes_DeleteAllItems,
2992 mfattributes_SetUINT32,
2993 mfattributes_SetUINT64,
2994 mfattributes_SetDouble,
2995 mfattributes_SetGUID,
2996 mfattributes_SetString,
2997 mfattributes_SetBlob,
2998 mfattributes_SetUnknown,
2999 mfattributes_LockStore,
3000 mfattributes_UnlockStore,
3001 mfattributes_GetCount,
3002 mfattributes_GetItemByIndex,
3003 mfattributes_CopyAllItems
3006 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3008 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3009 object->ref = 1;
3010 InitializeCriticalSection(&object->cs);
3012 object->attributes = NULL;
3013 object->count = 0;
3014 object->capacity = 0;
3015 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3016 sizeof(*object->attributes)))
3018 DeleteCriticalSection(&object->cs);
3019 return E_OUTOFMEMORY;
3022 return S_OK;
3025 void clear_attributes_object(struct attributes *object)
3027 size_t i;
3029 for (i = 0; i < object->count; i++)
3030 PropVariantClear(&object->attributes[i].value);
3031 heap_free(object->attributes);
3033 DeleteCriticalSection(&object->cs);
3036 /***********************************************************************
3037 * MFCreateAttributes (mfplat.@)
3039 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3041 struct attributes *object;
3042 HRESULT hr;
3044 TRACE("%p, %d\n", attributes, size);
3046 object = heap_alloc_zero(sizeof(*object));
3047 if (!object)
3048 return E_OUTOFMEMORY;
3050 if (FAILED(hr = init_attributes_object(object, size)))
3052 heap_free(object);
3053 return hr;
3055 *attributes = &object->IMFAttributes_iface;
3057 return S_OK;
3060 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3062 struct attributes_store_header
3064 DWORD magic;
3065 UINT32 count;
3068 struct attributes_store_item
3070 GUID key;
3071 QWORD type;
3072 union
3074 double f;
3075 UINT32 i32;
3076 UINT64 i64;
3077 struct
3079 DWORD size;
3080 DWORD offset;
3081 } subheader;
3082 } u;
3085 /***********************************************************************
3086 * MFGetAttributesAsBlobSize (mfplat.@)
3088 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3090 unsigned int i, count, length;
3091 HRESULT hr;
3092 GUID key;
3094 TRACE("%p, %p.\n", attributes, size);
3096 IMFAttributes_LockStore(attributes);
3098 hr = IMFAttributes_GetCount(attributes, &count);
3100 *size = sizeof(struct attributes_store_header);
3102 for (i = 0; i < count; ++i)
3104 MF_ATTRIBUTE_TYPE type;
3106 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3107 if (FAILED(hr))
3108 break;
3110 *size += sizeof(struct attributes_store_item);
3112 IMFAttributes_GetItemType(attributes, &key, &type);
3114 switch (type)
3116 case MF_ATTRIBUTE_GUID:
3117 *size += sizeof(GUID);
3118 break;
3119 case MF_ATTRIBUTE_STRING:
3120 IMFAttributes_GetStringLength(attributes, &key, &length);
3121 *size += (length + 1) * sizeof(WCHAR);
3122 break;
3123 case MF_ATTRIBUTE_BLOB:
3124 IMFAttributes_GetBlobSize(attributes, &key, &length);
3125 *size += length;
3126 break;
3127 case MF_ATTRIBUTE_UINT32:
3128 case MF_ATTRIBUTE_UINT64:
3129 case MF_ATTRIBUTE_DOUBLE:
3130 case MF_ATTRIBUTE_IUNKNOWN:
3131 default:
3136 IMFAttributes_UnlockStore(attributes);
3138 return hr;
3141 struct attr_serialize_context
3143 UINT8 *buffer;
3144 UINT8 *ptr;
3145 UINT32 size;
3148 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3150 memcpy(context->ptr, value, size);
3151 context->ptr += size;
3154 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3155 const void *value)
3157 switch (item->type)
3159 case MF_ATTRIBUTE_UINT32:
3160 case MF_ATTRIBUTE_UINT64:
3161 case MF_ATTRIBUTE_DOUBLE:
3162 attributes_serialize_write(context, item, sizeof(*item));
3163 break;
3164 case MF_ATTRIBUTE_GUID:
3165 case MF_ATTRIBUTE_STRING:
3166 case MF_ATTRIBUTE_BLOB:
3167 item->u.subheader.offset = context->size - item->u.subheader.size;
3168 attributes_serialize_write(context, item, sizeof(*item));
3169 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3170 context->size -= item->u.subheader.size;
3171 break;
3172 default:
3173 return FALSE;
3176 return TRUE;
3179 /***********************************************************************
3180 * MFGetAttributesAsBlob (mfplat.@)
3182 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3184 struct attributes_store_header header;
3185 struct attr_serialize_context context;
3186 unsigned int required_size, i;
3187 PROPVARIANT value;
3188 UINT32 count;
3189 HRESULT hr;
3191 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3193 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3194 return hr;
3196 if (required_size > size)
3197 return MF_E_BUFFERTOOSMALL;
3199 context.buffer = buffer;
3200 context.ptr = buffer;
3201 context.size = required_size;
3203 IMFAttributes_LockStore(attributes);
3205 header.magic = ATTRIBUTES_STORE_MAGIC;
3206 header.count = 0; /* Will be updated later */
3207 IMFAttributes_GetCount(attributes, &count);
3209 attributes_serialize_write(&context, &header, sizeof(header));
3211 for (i = 0; i < count; ++i)
3213 struct attributes_store_item item;
3214 const void *data = NULL;
3216 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3217 if (FAILED(hr))
3218 break;
3220 item.type = value.vt;
3222 switch (value.vt)
3224 case MF_ATTRIBUTE_UINT32:
3225 case MF_ATTRIBUTE_UINT64:
3226 item.u.i64 = value.u.uhVal.QuadPart;
3227 break;
3228 case MF_ATTRIBUTE_DOUBLE:
3229 item.u.f = value.u.dblVal;
3230 break;
3231 case MF_ATTRIBUTE_GUID:
3232 item.u.subheader.size = sizeof(*value.u.puuid);
3233 data = value.u.puuid;
3234 break;
3235 case MF_ATTRIBUTE_STRING:
3236 item.u.subheader.size = (lstrlenW(value.u.pwszVal) + 1) * sizeof(WCHAR);
3237 data = value.u.pwszVal;
3238 break;
3239 case MF_ATTRIBUTE_BLOB:
3240 item.u.subheader.size = value.u.caub.cElems;
3241 data = value.u.caub.pElems;
3242 break;
3243 case MF_ATTRIBUTE_IUNKNOWN:
3244 break;
3245 default:
3246 WARN("Unknown attribute type %#x.\n", value.vt);
3249 if (attributes_serialize_write_item(&context, &item, data))
3250 header.count++;
3252 PropVariantClear(&value);
3255 memcpy(context.buffer, &header, sizeof(header));
3257 IMFAttributes_UnlockStore(attributes);
3259 return S_OK;
3262 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3264 if (context->size < (context->ptr - context->buffer) + size)
3265 return E_INVALIDARG;
3267 memcpy(value, context->ptr, size);
3268 context->ptr += size;
3270 return S_OK;
3273 /***********************************************************************
3274 * MFInitAttributesFromBlob (mfplat.@)
3276 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3278 struct attr_serialize_context context;
3279 struct attributes_store_header header;
3280 struct attributes_store_item item;
3281 IMFAttributes *attributes;
3282 unsigned int i;
3283 HRESULT hr;
3285 TRACE("%p, %p, %u.\n", dest, buffer, size);
3287 context.buffer = (UINT8 *)buffer;
3288 context.ptr = (UINT8 *)buffer;
3289 context.size = size;
3291 /* Validate buffer structure. */
3292 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3293 return hr;
3295 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3296 return E_UNEXPECTED;
3298 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3299 return hr;
3301 for (i = 0; i < header.count; ++i)
3303 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3304 break;
3306 hr = E_UNEXPECTED;
3308 switch (item.type)
3310 case MF_ATTRIBUTE_UINT32:
3311 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3312 break;
3313 case MF_ATTRIBUTE_UINT64:
3314 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3315 break;
3316 case MF_ATTRIBUTE_DOUBLE:
3317 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3318 break;
3319 case MF_ATTRIBUTE_GUID:
3320 if (item.u.subheader.size == sizeof(GUID) &&
3321 item.u.subheader.offset + item.u.subheader.size <= context.size)
3323 hr = IMFAttributes_SetGUID(attributes, &item.key,
3324 (const GUID *)(context.buffer + item.u.subheader.offset));
3326 break;
3327 case MF_ATTRIBUTE_STRING:
3328 if (item.u.subheader.size >= sizeof(WCHAR) &&
3329 item.u.subheader.offset + item.u.subheader.size <= context.size)
3331 hr = IMFAttributes_SetString(attributes, &item.key,
3332 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3334 break;
3335 case MF_ATTRIBUTE_BLOB:
3336 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3338 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3339 item.u.subheader.size);
3341 break;
3342 default:
3346 if (FAILED(hr))
3347 break;
3350 if (SUCCEEDED(hr))
3352 IMFAttributes_DeleteAllItems(dest);
3353 hr = IMFAttributes_CopyAllItems(attributes, dest);
3356 IMFAttributes_Release(attributes);
3358 return hr;
3361 typedef struct bytestream
3363 struct attributes attributes;
3364 IMFByteStream IMFByteStream_iface;
3365 IMFGetService IMFGetService_iface;
3366 IRtwqAsyncCallback read_callback;
3367 IRtwqAsyncCallback write_callback;
3368 IStream *stream;
3369 HANDLE hfile;
3370 QWORD position;
3371 DWORD capabilities;
3372 struct list pending;
3373 CRITICAL_SECTION cs;
3374 } mfbytestream;
3376 static inline mfbytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3378 return CONTAINING_RECORD(iface, mfbytestream, IMFByteStream_iface);
3381 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3383 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3386 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3388 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3391 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3393 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3396 enum async_stream_op_type
3398 ASYNC_STREAM_OP_READ,
3399 ASYNC_STREAM_OP_WRITE,
3402 struct async_stream_op
3404 IUnknown IUnknown_iface;
3405 LONG refcount;
3406 union
3408 const BYTE *src;
3409 BYTE *dest;
3410 } u;
3411 QWORD position;
3412 ULONG requested_length;
3413 ULONG actual_length;
3414 IMFAsyncResult *caller;
3415 struct list entry;
3416 enum async_stream_op_type type;
3419 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3421 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3424 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3426 if (IsEqualIID(riid, &IID_IUnknown))
3428 *obj = iface;
3429 IUnknown_AddRef(iface);
3430 return S_OK;
3433 WARN("Unsupported %s.\n", debugstr_guid(riid));
3434 *obj = NULL;
3435 return E_NOINTERFACE;
3438 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3440 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3441 ULONG refcount = InterlockedIncrement(&op->refcount);
3443 TRACE("%p, refcount %d.\n", iface, refcount);
3445 return refcount;
3448 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3450 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3451 ULONG refcount = InterlockedDecrement(&op->refcount);
3453 TRACE("%p, refcount %d.\n", iface, refcount);
3455 if (!refcount)
3457 if (op->caller)
3458 IMFAsyncResult_Release(op->caller);
3459 heap_free(op);
3462 return refcount;
3465 static const IUnknownVtbl async_stream_op_vtbl =
3467 async_stream_op_QueryInterface,
3468 async_stream_op_AddRef,
3469 async_stream_op_Release,
3472 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3473 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3475 struct async_stream_op *op;
3476 IRtwqAsyncResult *request;
3477 HRESULT hr;
3479 op = heap_alloc(sizeof(*op));
3480 if (!op)
3481 return E_OUTOFMEMORY;
3483 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3484 op->refcount = 1;
3485 op->u.src = data;
3486 op->position = stream->position;
3487 op->requested_length = size;
3488 op->type = type;
3489 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3490 (IRtwqAsyncResult **)&op->caller)))
3492 goto failed;
3495 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3496 &stream->write_callback, NULL, &request)))
3497 goto failed;
3499 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, request);
3500 IRtwqAsyncResult_Release(request);
3502 failed:
3503 IUnknown_Release(&op->IUnknown_iface);
3504 return hr;
3507 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3508 IMFAsyncResult *result, ULONG *actual_length)
3510 struct async_stream_op *op = NULL, *cur;
3511 HRESULT hr;
3513 EnterCriticalSection(&stream->cs);
3514 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3516 if (cur->caller == result && cur->type == type)
3518 op = cur;
3519 list_remove(&cur->entry);
3520 break;
3523 LeaveCriticalSection(&stream->cs);
3525 if (!op)
3526 return E_INVALIDARG;
3528 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3529 *actual_length = op->actual_length;
3531 IUnknown_Release(&op->IUnknown_iface);
3533 return hr;
3536 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3538 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3539 IsEqualIID(riid, &IID_IUnknown))
3541 *obj = iface;
3542 IRtwqAsyncCallback_AddRef(iface);
3543 return S_OK;
3546 WARN("Unsupported %s.\n", debugstr_guid(riid));
3547 *obj = NULL;
3548 return E_NOINTERFACE;
3551 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3553 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3554 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3557 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3559 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3560 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3563 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3565 return E_NOTIMPL;
3568 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3570 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3571 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3574 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3576 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3577 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3580 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3582 struct bytestream *stream = impl_from_IMFByteStream(iface);
3584 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3586 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3587 IsEqualIID(riid, &IID_IUnknown))
3589 *out = &stream->IMFByteStream_iface;
3591 else if (IsEqualIID(riid, &IID_IMFAttributes))
3593 *out = &stream->attributes.IMFAttributes_iface;
3595 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3597 *out = &stream->IMFGetService_iface;
3599 else
3601 WARN("Unsupported %s.\n", debugstr_guid(riid));
3602 *out = NULL;
3603 return E_NOINTERFACE;
3606 IUnknown_AddRef((IUnknown*)*out);
3607 return S_OK;
3610 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3612 struct bytestream *stream = impl_from_IMFByteStream(iface);
3613 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3615 TRACE("%p, refcount %d.\n", iface, refcount);
3617 return refcount;
3620 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3622 struct bytestream *stream = impl_from_IMFByteStream(iface);
3623 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3624 struct async_stream_op *cur, *cur2;
3626 TRACE("%p, refcount %d.\n", iface, refcount);
3628 if (!refcount)
3630 clear_attributes_object(&stream->attributes);
3631 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3633 list_remove(&cur->entry);
3634 IUnknown_Release(&cur->IUnknown_iface);
3636 DeleteCriticalSection(&stream->cs);
3637 if (stream->stream)
3638 IStream_Release(stream->stream);
3639 if (stream->hfile)
3640 CloseHandle(stream->hfile);
3641 heap_free(stream);
3644 return refcount;
3647 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3649 struct bytestream *stream = impl_from_IMFByteStream(iface);
3650 STATSTG stat;
3651 HRESULT hr;
3653 TRACE("%p, %p.\n", iface, capabilities);
3655 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3656 return hr;
3658 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3659 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3660 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3662 return S_OK;
3665 static HRESULT WINAPI bytestream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3667 struct bytestream *stream = impl_from_IMFByteStream(iface);
3669 TRACE("%p, %p.\n", iface, capabilities);
3671 *capabilities = stream->capabilities;
3673 return S_OK;
3676 static HRESULT WINAPI mfbytestream_SetLength(IMFByteStream *iface, QWORD length)
3678 mfbytestream *This = impl_from_IMFByteStream(iface);
3680 FIXME("%p, %s\n", This, wine_dbgstr_longlong(length));
3682 return E_NOTIMPL;
3685 static HRESULT WINAPI bytestream_file_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3687 struct bytestream *stream = impl_from_IMFByteStream(iface);
3689 TRACE("%p, %p.\n", iface, position);
3691 if (!position)
3692 return E_INVALIDARG;
3694 *position = stream->position;
3696 return S_OK;
3699 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
3701 struct bytestream *stream = impl_from_IMFByteStream(iface);
3702 LARGE_INTEGER li;
3704 TRACE("%p, %p.\n", iface, length);
3706 if (!length)
3707 return E_INVALIDARG;
3709 if (GetFileSizeEx(stream->hfile, &li))
3710 *length = li.QuadPart;
3711 else
3712 return HRESULT_FROM_WIN32(GetLastError());
3714 return S_OK;
3717 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
3719 struct bytestream *stream = impl_from_IMFByteStream(iface);
3720 LARGE_INTEGER position, length;
3721 HRESULT hr = S_OK;
3723 TRACE("%p, %p.\n", iface, ret);
3725 EnterCriticalSection(&stream->cs);
3727 position.QuadPart = 0;
3728 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
3729 *ret = stream->position >= length.QuadPart;
3730 else
3731 hr = HRESULT_FROM_WIN32(GetLastError());
3733 LeaveCriticalSection(&stream->cs);
3735 return hr;
3738 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
3740 struct bytestream *stream = impl_from_IMFByteStream(iface);
3741 LARGE_INTEGER position;
3742 HRESULT hr = S_OK;
3743 BOOL ret;
3745 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
3747 EnterCriticalSection(&stream->cs);
3749 position.QuadPart = stream->position;
3750 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
3752 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
3753 stream->position += *read_len;
3756 if (!ret)
3757 hr = HRESULT_FROM_WIN32(GetLastError());
3759 LeaveCriticalSection(&stream->cs);
3761 return hr;
3764 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
3765 IUnknown *state)
3767 struct bytestream *stream = impl_from_IMFByteStream(iface);
3769 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3771 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_READ, data, size, callback, state);
3774 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
3776 struct bytestream *stream = impl_from_IMFByteStream(iface);
3778 TRACE("%p, %p, %p.\n", iface, result, byte_read);
3780 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
3783 static HRESULT WINAPI mfbytestream_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
3785 mfbytestream *This = impl_from_IMFByteStream(iface);
3787 FIXME("%p, %p, %u, %p\n", This, data, count, written);
3789 return E_NOTIMPL;
3792 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
3793 IMFAsyncCallback *callback, IUnknown *state)
3795 struct bytestream *stream = impl_from_IMFByteStream(iface);
3797 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3799 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
3802 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
3804 struct bytestream *stream = impl_from_IMFByteStream(iface);
3806 TRACE("%p, %p, %p.\n", iface, result, written);
3808 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
3811 static HRESULT WINAPI mfbytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
3812 DWORD flags, QWORD *current)
3814 mfbytestream *This = impl_from_IMFByteStream(iface);
3816 FIXME("%p, %u, %s, 0x%08x, %p\n", This, seek, wine_dbgstr_longlong(offset), flags, current);
3818 return E_NOTIMPL;
3821 static HRESULT WINAPI mfbytestream_Flush(IMFByteStream *iface)
3823 mfbytestream *This = impl_from_IMFByteStream(iface);
3825 FIXME("%p\n", This);
3827 return E_NOTIMPL;
3830 static HRESULT WINAPI mfbytestream_Close(IMFByteStream *iface)
3832 mfbytestream *This = impl_from_IMFByteStream(iface);
3834 FIXME("%p\n", This);
3836 return E_NOTIMPL;
3839 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
3841 struct bytestream *stream = impl_from_IMFByteStream(iface);
3843 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
3845 EnterCriticalSection(&stream->cs);
3846 stream->position = position;
3847 LeaveCriticalSection(&stream->cs);
3849 return S_OK;
3852 static const IMFByteStreamVtbl bytestream_file_vtbl =
3854 bytestream_QueryInterface,
3855 bytestream_AddRef,
3856 bytestream_Release,
3857 bytestream_GetCapabilities,
3858 bytestream_file_GetLength,
3859 mfbytestream_SetLength,
3860 bytestream_file_GetCurrentPosition,
3861 bytestream_SetCurrentPosition,
3862 bytestream_file_IsEndOfStream,
3863 bytestream_file_Read,
3864 bytestream_BeginRead,
3865 bytestream_EndRead,
3866 mfbytestream_Write,
3867 bytestream_BeginWrite,
3868 bytestream_EndWrite,
3869 mfbytestream_Seek,
3870 mfbytestream_Flush,
3871 mfbytestream_Close
3874 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
3876 struct bytestream *stream = impl_from_IMFByteStream(iface);
3877 STATSTG statstg;
3878 HRESULT hr;
3880 TRACE("%p, %p.\n", iface, length);
3882 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
3883 return hr;
3885 *length = statstg.cbSize.QuadPart;
3887 return S_OK;
3890 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
3892 struct bytestream *stream = impl_from_IMFByteStream(iface);
3893 ULARGE_INTEGER size;
3894 HRESULT hr;
3896 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
3898 EnterCriticalSection(&stream->cs);
3900 size.QuadPart = length;
3901 hr = IStream_SetSize(stream->stream, size);
3903 LeaveCriticalSection(&stream->cs);
3905 return hr;
3908 static HRESULT WINAPI bytestream_stream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3910 struct bytestream *stream = impl_from_IMFByteStream(iface);
3912 TRACE("%p, %p.\n", iface, position);
3914 *position = stream->position;
3916 return S_OK;
3919 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
3921 struct bytestream *stream = impl_from_IMFByteStream(iface);
3922 STATSTG statstg;
3923 HRESULT hr;
3925 TRACE("%p, %p.\n", iface, ret);
3927 EnterCriticalSection(&stream->cs);
3929 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
3930 *ret = stream->position >= statstg.cbSize.QuadPart;
3932 LeaveCriticalSection(&stream->cs);
3934 return hr;
3937 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
3939 struct bytestream *stream = impl_from_IMFByteStream(iface);
3940 LARGE_INTEGER position;
3941 HRESULT hr;
3943 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
3945 EnterCriticalSection(&stream->cs);
3947 position.QuadPart = stream->position;
3948 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
3950 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
3951 stream->position += *read_len;
3954 LeaveCriticalSection(&stream->cs);
3956 return hr;
3959 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
3961 struct bytestream *stream = impl_from_IMFByteStream(iface);
3962 LARGE_INTEGER position;
3963 HRESULT hr;
3965 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, written);
3967 EnterCriticalSection(&stream->cs);
3969 position.QuadPart = stream->position;
3970 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
3972 if (SUCCEEDED(hr = IStream_Write(stream->stream, buffer, size, written)))
3973 stream->position += *written;
3976 LeaveCriticalSection(&stream->cs);
3978 return hr;
3981 static HRESULT WINAPI bytestream_stream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
3982 DWORD flags, QWORD *current)
3984 struct bytestream *stream = impl_from_IMFByteStream(iface);
3985 HRESULT hr = S_OK;
3987 TRACE("%p, %u, %s, %#x, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
3989 EnterCriticalSection(&stream->cs);
3991 switch (origin)
3993 case msoBegin:
3994 stream->position = offset;
3995 break;
3996 case msoCurrent:
3997 stream->position += offset;
3998 break;
3999 default:
4000 WARN("Unknown origin mode %d.\n", origin);
4001 hr = E_INVALIDARG;
4004 *current = stream->position;
4006 LeaveCriticalSection(&stream->cs);
4008 return hr;
4011 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4013 struct bytestream *stream = impl_from_IMFByteStream(iface);
4015 TRACE("%p.\n", iface);
4017 return IStream_Commit(stream->stream, STGC_DEFAULT);
4020 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4022 TRACE("%p.\n", iface);
4024 return S_OK;
4027 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4029 bytestream_QueryInterface,
4030 bytestream_AddRef,
4031 bytestream_Release,
4032 bytestream_stream_GetCapabilities,
4033 bytestream_stream_GetLength,
4034 bytestream_stream_SetLength,
4035 bytestream_stream_GetCurrentPosition,
4036 bytestream_SetCurrentPosition,
4037 bytestream_stream_IsEndOfStream,
4038 bytestream_stream_Read,
4039 bytestream_BeginRead,
4040 bytestream_EndRead,
4041 bytestream_stream_Write,
4042 bytestream_BeginWrite,
4043 bytestream_EndWrite,
4044 bytestream_stream_Seek,
4045 bytestream_stream_Flush,
4046 bytestream_stream_Close,
4049 static inline mfbytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4051 return CONTAINING_RECORD(iface, mfbytestream, attributes.IMFAttributes_iface);
4054 static HRESULT WINAPI mfbytestream_attributes_QueryInterface(
4055 IMFAttributes *iface, REFIID riid, void **out)
4057 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4058 return IMFByteStream_QueryInterface(&This->IMFByteStream_iface, riid, out);
4061 static ULONG WINAPI mfbytestream_attributes_AddRef(IMFAttributes *iface)
4063 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4064 return IMFByteStream_AddRef(&This->IMFByteStream_iface);
4067 static ULONG WINAPI mfbytestream_attributes_Release(IMFAttributes *iface)
4069 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4070 return IMFByteStream_Release(&This->IMFByteStream_iface);
4073 static const IMFAttributesVtbl mfbytestream_attributes_vtbl =
4075 mfbytestream_attributes_QueryInterface,
4076 mfbytestream_attributes_AddRef,
4077 mfbytestream_attributes_Release,
4078 mfattributes_GetItem,
4079 mfattributes_GetItemType,
4080 mfattributes_CompareItem,
4081 mfattributes_Compare,
4082 mfattributes_GetUINT32,
4083 mfattributes_GetUINT64,
4084 mfattributes_GetDouble,
4085 mfattributes_GetGUID,
4086 mfattributes_GetStringLength,
4087 mfattributes_GetString,
4088 mfattributes_GetAllocatedString,
4089 mfattributes_GetBlobSize,
4090 mfattributes_GetBlob,
4091 mfattributes_GetAllocatedBlob,
4092 mfattributes_GetUnknown,
4093 mfattributes_SetItem,
4094 mfattributes_DeleteItem,
4095 mfattributes_DeleteAllItems,
4096 mfattributes_SetUINT32,
4097 mfattributes_SetUINT64,
4098 mfattributes_SetDouble,
4099 mfattributes_SetGUID,
4100 mfattributes_SetString,
4101 mfattributes_SetBlob,
4102 mfattributes_SetUnknown,
4103 mfattributes_LockStore,
4104 mfattributes_UnlockStore,
4105 mfattributes_GetCount,
4106 mfattributes_GetItemByIndex,
4107 mfattributes_CopyAllItems
4110 static HRESULT WINAPI bytestream_stream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4112 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4113 struct async_stream_op *op;
4114 LARGE_INTEGER position;
4115 IUnknown *object;
4116 HRESULT hr;
4118 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4119 return hr;
4121 op = impl_async_stream_op_from_IUnknown(object);
4123 EnterCriticalSection(&stream->cs);
4125 position.QuadPart = op->position;
4126 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4128 if (SUCCEEDED(hr = IStream_Read(stream->stream, op->u.dest, op->requested_length, &op->actual_length)))
4129 stream->position += op->actual_length;
4132 IMFAsyncResult_SetStatus(op->caller, hr);
4133 list_add_tail(&stream->pending, &op->entry);
4135 LeaveCriticalSection(&stream->cs);
4137 MFInvokeCallback(op->caller);
4139 return S_OK;
4142 static HRESULT WINAPI bytestream_stream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4144 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4145 struct async_stream_op *op;
4146 LARGE_INTEGER position;
4147 IUnknown *object;
4148 HRESULT hr;
4150 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4151 return hr;
4153 op = impl_async_stream_op_from_IUnknown(object);
4155 EnterCriticalSection(&stream->cs);
4157 position.QuadPart = op->position;
4158 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4160 if (SUCCEEDED(hr = IStream_Write(stream->stream, op->u.src, op->requested_length, &op->actual_length)))
4161 stream->position += op->actual_length;
4164 IMFAsyncResult_SetStatus(op->caller, hr);
4165 list_add_tail(&stream->pending, &op->entry);
4167 LeaveCriticalSection(&stream->cs);
4169 MFInvokeCallback(op->caller);
4171 return S_OK;
4174 static const IRtwqAsyncCallbackVtbl bytestream_stream_read_callback_vtbl =
4176 bytestream_callback_QueryInterface,
4177 bytestream_read_callback_AddRef,
4178 bytestream_read_callback_Release,
4179 bytestream_callback_GetParameters,
4180 bytestream_stream_read_callback_Invoke,
4183 static const IRtwqAsyncCallbackVtbl bytestream_stream_write_callback_vtbl =
4185 bytestream_callback_QueryInterface,
4186 bytestream_write_callback_AddRef,
4187 bytestream_write_callback_Release,
4188 bytestream_callback_GetParameters,
4189 bytestream_stream_write_callback_Invoke,
4192 /***********************************************************************
4193 * MFCreateMFByteStreamOnStream (mfplat.@)
4195 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4197 struct bytestream *object;
4198 LARGE_INTEGER position;
4199 STATSTG stat;
4200 HRESULT hr;
4202 TRACE("%p, %p.\n", stream, bytestream);
4204 object = heap_alloc_zero(sizeof(*object));
4205 if (!object)
4206 return E_OUTOFMEMORY;
4208 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4210 heap_free(object);
4211 return hr;
4214 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4215 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4216 object->read_callback.lpVtbl = &bytestream_stream_read_callback_vtbl;
4217 object->write_callback.lpVtbl = &bytestream_stream_write_callback_vtbl;
4218 InitializeCriticalSection(&object->cs);
4219 list_init(&object->pending);
4221 object->stream = stream;
4222 IStream_AddRef(object->stream);
4223 position.QuadPart = 0;
4224 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4226 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4228 if (stat.pwcsName)
4230 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4231 stat.pwcsName);
4232 CoTaskMemFree(stat.pwcsName);
4236 *bytestream = &object->IMFByteStream_iface;
4238 return S_OK;
4241 static HRESULT WINAPI bytestream_file_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4243 FIXME("%p, %p.\n", iface, result);
4245 return E_NOTIMPL;
4248 static HRESULT WINAPI bytestream_file_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4250 FIXME("%p, %p.\n", iface, result);
4252 return E_NOTIMPL;
4255 static const IRtwqAsyncCallbackVtbl bytestream_file_read_callback_vtbl =
4257 bytestream_callback_QueryInterface,
4258 bytestream_read_callback_AddRef,
4259 bytestream_read_callback_Release,
4260 bytestream_callback_GetParameters,
4261 bytestream_file_read_callback_Invoke,
4264 static const IRtwqAsyncCallbackVtbl bytestream_file_write_callback_vtbl =
4266 bytestream_callback_QueryInterface,
4267 bytestream_write_callback_AddRef,
4268 bytestream_write_callback_Release,
4269 bytestream_callback_GetParameters,
4270 bytestream_file_write_callback_Invoke,
4273 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4275 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4276 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4279 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4281 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4282 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4285 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4287 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4288 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4291 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4292 REFIID riid, void **obj)
4294 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4296 return E_NOTIMPL;
4299 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4301 bytestream_file_getservice_QueryInterface,
4302 bytestream_file_getservice_AddRef,
4303 bytestream_file_getservice_Release,
4304 bytestream_file_getservice_GetService,
4307 /***********************************************************************
4308 * MFCreateFile (mfplat.@)
4310 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4311 LPCWSTR url, IMFByteStream **bytestream)
4313 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4314 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4315 DWORD filesharemode = FILE_SHARE_READ;
4316 struct bytestream *object;
4317 FILETIME writetime;
4318 HANDLE file;
4319 HRESULT hr;
4321 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(url), bytestream);
4323 switch (accessmode)
4325 case MF_ACCESSMODE_READ:
4326 fileaccessmode = GENERIC_READ;
4327 capabilities |= MFBYTESTREAM_IS_READABLE;
4328 break;
4329 case MF_ACCESSMODE_WRITE:
4330 fileaccessmode = GENERIC_WRITE;
4331 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4332 break;
4333 case MF_ACCESSMODE_READWRITE:
4334 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4335 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4336 break;
4339 switch (openmode)
4341 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4342 filecreation_disposition = OPEN_EXISTING;
4343 break;
4344 case MF_OPENMODE_FAIL_IF_EXIST:
4345 filecreation_disposition = CREATE_NEW;
4346 break;
4347 case MF_OPENMODE_RESET_IF_EXIST:
4348 filecreation_disposition = TRUNCATE_EXISTING;
4349 break;
4350 case MF_OPENMODE_APPEND_IF_EXIST:
4351 filecreation_disposition = OPEN_ALWAYS;
4352 fileaccessmode |= FILE_APPEND_DATA;
4353 break;
4354 case MF_OPENMODE_DELETE_IF_EXIST:
4355 filecreation_disposition = CREATE_ALWAYS;
4356 break;
4359 if (flags & MF_FILEFLAGS_NOBUFFERING)
4360 fileattributes |= FILE_FLAG_NO_BUFFERING;
4362 /* Open HANDLE to file */
4363 file = CreateFileW(url, fileaccessmode, filesharemode, NULL,
4364 filecreation_disposition, fileattributes, 0);
4366 if(file == INVALID_HANDLE_VALUE)
4367 return HRESULT_FROM_WIN32(GetLastError());
4369 object = heap_alloc_zero(sizeof(*object));
4370 if (!object)
4372 CloseHandle(file);
4373 return E_OUTOFMEMORY;
4376 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4378 CloseHandle(file);
4379 heap_free(object);
4380 return hr;
4382 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4383 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4384 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4385 object->read_callback.lpVtbl = &bytestream_file_read_callback_vtbl;
4386 object->write_callback.lpVtbl = &bytestream_file_write_callback_vtbl;
4387 InitializeCriticalSection(&object->cs);
4388 list_init(&object->pending);
4389 object->capabilities = capabilities;
4390 object->hfile = file;
4392 if (GetFileTime(file, NULL, NULL, &writetime))
4394 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4395 (const UINT8 *)&writetime, sizeof(writetime));
4398 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, url);
4400 *bytestream = &object->IMFByteStream_iface;
4402 return S_OK;
4405 struct bytestream_wrapper
4407 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4408 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4409 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4410 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4411 IMFSampleOutputStream IMFSampleOutputStream_iface;
4412 IPropertyStore IPropertyStore_iface;
4413 IMFByteStream IMFByteStream_iface;
4414 IMFAttributes IMFAttributes_iface;
4415 LONG refcount;
4417 IMFByteStreamCacheControl *cache_control;
4418 IMFByteStreamBuffering *stream_buffering;
4419 IMFMediaEventGenerator *event_generator;
4420 IMFByteStreamTimeSeek *time_seek;
4421 IMFSampleOutputStream *sample_output;
4422 IPropertyStore *propstore;
4423 IMFByteStream *stream;
4424 IMFAttributes *attributes;
4425 BOOL is_closed;
4428 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4430 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4433 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4435 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4438 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4440 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4443 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4445 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4448 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4450 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4453 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4455 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4458 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4460 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4463 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4465 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4468 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4470 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4472 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4474 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4475 IsEqualIID(riid, &IID_IUnknown))
4477 *out = &wrapper->IMFByteStream_iface;
4479 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4481 *out = &wrapper->IMFByteStreamCacheControl_iface;
4483 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4485 *out = &wrapper->IMFByteStreamBuffering_iface;
4487 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4489 *out = &wrapper->IMFMediaEventGenerator_iface;
4491 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4493 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4495 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4497 *out = &wrapper->IMFSampleOutputStream_iface;
4499 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4501 *out = &wrapper->IPropertyStore_iface;
4503 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4505 *out = &wrapper->IMFAttributes_iface;
4507 else
4509 WARN("Unsupported %s.\n", debugstr_guid(riid));
4510 *out = NULL;
4511 return E_NOINTERFACE;
4514 IUnknown_AddRef((IUnknown *)*out);
4515 return S_OK;
4518 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4520 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4521 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4523 TRACE("%p, refcount %d.\n", iface, refcount);
4525 return refcount;
4528 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4530 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4531 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4533 TRACE("%p, refcount %d.\n", iface, refcount);
4535 if (!refcount)
4537 if (wrapper->cache_control)
4538 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4539 if (wrapper->stream_buffering)
4540 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4541 if (wrapper->event_generator)
4542 IMFMediaEventGenerator_Release(wrapper->event_generator);
4543 if (wrapper->time_seek)
4544 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4545 if (wrapper->sample_output)
4546 IMFSampleOutputStream_Release(wrapper->sample_output);
4547 if (wrapper->propstore)
4548 IPropertyStore_Release(wrapper->propstore);
4549 if (wrapper->attributes)
4550 IMFAttributes_Release(wrapper->attributes);
4551 IMFByteStream_Release(wrapper->stream);
4552 heap_free(wrapper);
4555 return refcount;
4558 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4560 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4562 TRACE("%p, %p.\n", iface, capabilities);
4564 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4565 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4568 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4570 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4572 TRACE("%p, %p.\n", iface, length);
4574 if (wrapper->is_closed)
4575 return MF_E_INVALIDREQUEST;
4577 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4578 IMFByteStream_GetLength(wrapper->stream, length);
4581 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4583 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4585 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4587 if (wrapper->is_closed)
4588 return MF_E_INVALIDREQUEST;
4590 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4591 IMFByteStream_SetLength(wrapper->stream, length);
4594 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4596 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4598 TRACE("%p, %p.\n", iface, position);
4600 if (wrapper->is_closed)
4601 return MF_E_INVALIDREQUEST;
4603 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4604 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4607 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4609 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4611 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4613 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4614 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4617 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4619 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4621 TRACE("%p, %p.\n", iface, eos);
4623 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4624 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4627 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4629 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4631 TRACE("%p, %p, %u, %p.\n", iface, data, count, byte_read);
4633 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4634 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4637 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4638 IMFAsyncCallback *callback, IUnknown *state)
4640 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4642 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4644 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4645 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4648 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4650 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4652 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4654 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4655 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4658 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4660 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4662 TRACE("%p, %p, %u, %p.\n", iface, data, count, written);
4664 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4665 IMFByteStream_Write(wrapper->stream, data, count, written);
4668 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4669 IMFAsyncCallback *callback, IUnknown *state)
4671 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4673 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4675 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4676 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4679 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4681 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4683 TRACE("%p, %p, %p.\n", iface, result, written);
4685 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4686 IMFByteStream_EndWrite(wrapper->stream, result, written);
4689 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4690 DWORD flags, QWORD *current)
4692 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4694 TRACE("%p, %u, %s, %#x, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4696 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4697 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
4700 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
4702 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4704 TRACE("%p\n", iface);
4706 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
4709 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
4711 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4713 TRACE("%p\n", iface);
4715 wrapper->is_closed = TRUE;
4717 return S_OK;
4720 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
4722 bytestream_wrapper_QueryInterface,
4723 bytestream_wrapper_AddRef,
4724 bytestream_wrapper_Release,
4725 bytestream_wrapper_GetCapabilities,
4726 bytestream_wrapper_GetLength,
4727 bytestream_wrapper_SetLength,
4728 bytestream_wrapper_GetCurrentPosition,
4729 bytestream_wrapper_SetCurrentPosition,
4730 bytestream_wrapper_IsEndOfStream,
4731 bytestream_wrapper_Read,
4732 bytestream_wrapper_BeginRead,
4733 bytestream_wrapper_EndRead,
4734 bytestream_wrapper_Write,
4735 bytestream_wrapper_BeginWrite,
4736 bytestream_wrapper_EndWrite,
4737 bytestream_wrapper_Seek,
4738 bytestream_wrapper_Flush,
4739 bytestream_wrapper_Close,
4742 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
4743 REFIID riid, void **obj)
4745 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4746 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4749 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
4751 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4752 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4755 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
4757 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4758 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4761 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
4763 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4765 TRACE("%p.\n", iface);
4767 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
4770 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
4772 bytestream_wrapper_cache_control_QueryInterface,
4773 bytestream_wrapper_cache_control_AddRef,
4774 bytestream_wrapper_cache_control_Release,
4775 bytestream_wrapper_cache_control_StopBackgroundTransfer,
4778 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
4779 REFIID riid, void **obj)
4781 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4782 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4785 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
4787 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4788 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4791 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
4793 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4794 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4797 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
4798 MFBYTESTREAM_BUFFERING_PARAMS *params)
4800 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4802 TRACE("%p, %p.\n", iface, params);
4804 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
4807 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
4808 BOOL enable)
4810 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4812 TRACE("%p, %d.\n", iface, enable);
4814 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
4817 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
4819 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4821 TRACE("%p.\n", iface);
4823 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
4826 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
4828 bytestream_wrapper_buffering_QueryInterface,
4829 bytestream_wrapper_buffering_AddRef,
4830 bytestream_wrapper_buffering_Release,
4831 bytestream_wrapper_buffering_SetBufferingParams,
4832 bytestream_wrapper_buffering_EnableBuffering,
4833 bytestream_wrapper_buffering_StopBuffering,
4836 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
4837 REFIID riid, void **obj)
4839 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4840 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4843 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
4845 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4846 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4849 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
4851 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4852 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4855 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
4857 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4859 TRACE("%p, %p.\n", iface, result);
4861 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
4864 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
4866 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4868 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4870 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
4873 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
4874 QWORD *stop_time, QWORD *duration)
4876 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4878 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
4880 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
4883 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
4885 bytestream_wrapper_timeseek_QueryInterface,
4886 bytestream_wrapper_timeseek_AddRef,
4887 bytestream_wrapper_timeseek_Release,
4888 bytestream_wrapper_timeseek_IsTimeSeekSupported,
4889 bytestream_wrapper_timeseek_TimeSeek,
4890 bytestream_wrapper_timeseek_GetTimeSeekResult,
4893 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
4895 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4896 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4899 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
4901 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4902 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4905 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
4907 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4908 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4911 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
4913 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4915 TRACE("%p, %#x, %p.\n", iface, flags, event);
4917 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
4920 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
4922 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4924 TRACE("%p, %p, %p.\n", iface, callback, state);
4926 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
4929 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
4931 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4933 TRACE("%p, %p, %p.\n", iface, result, event);
4935 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
4938 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
4939 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
4941 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
4943 TRACE("%p, %d, %s, %#x, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
4945 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
4948 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
4950 bytestream_wrapper_events_QueryInterface,
4951 bytestream_wrapper_events_AddRef,
4952 bytestream_wrapper_events_Release,
4953 bytestream_wrapper_events_GetEvent,
4954 bytestream_wrapper_events_BeginGetEvent,
4955 bytestream_wrapper_events_EndGetEvent,
4956 bytestream_wrapper_events_QueueEvent,
4959 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
4961 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
4962 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4965 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
4967 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
4968 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4971 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
4973 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
4974 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4977 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
4978 IMFAsyncCallback *callback, IUnknown *state)
4980 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
4982 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
4984 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
4987 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
4989 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
4991 TRACE("%p, %p.\n", iface, result);
4993 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
4996 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
4998 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5000 TRACE("%p.\n", iface);
5002 return IMFSampleOutputStream_Close(wrapper->sample_output);
5005 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5007 bytestream_wrapper_sample_output_QueryInterface,
5008 bytestream_wrapper_sample_output_AddRef,
5009 bytestream_wrapper_sample_output_Release,
5010 bytestream_wrapper_sample_output_BeginWriteSample,
5011 bytestream_wrapper_sample_output_EndWriteSample,
5012 bytestream_wrapper_sample_output_Close,
5015 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5017 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5018 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5021 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5023 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5024 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5027 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5029 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5030 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5033 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5035 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5037 TRACE("%p, %p.\n", iface, count);
5039 return IPropertyStore_GetCount(wrapper->propstore, count);
5042 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5044 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5046 TRACE("%p, %u, %p.\n", iface, prop, key);
5048 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5051 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5053 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5055 TRACE("%p, %p, %p.\n", iface, key, value);
5057 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5060 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5061 const PROPVARIANT *value)
5063 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5065 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5067 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5070 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5072 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5074 TRACE("%p.\n", iface);
5076 return IPropertyStore_Commit(wrapper->propstore);
5079 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5081 bytestream_wrapper_propstore_QueryInterface,
5082 bytestream_wrapper_propstore_AddRef,
5083 bytestream_wrapper_propstore_Release,
5084 bytestream_wrapper_propstore_GetCount,
5085 bytestream_wrapper_propstore_GetAt,
5086 bytestream_wrapper_propstore_GetValue,
5087 bytestream_wrapper_propstore_SetValue,
5088 bytestream_wrapper_propstore_Commit,
5091 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5093 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5094 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5097 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5099 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5100 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5103 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5105 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5106 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5109 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5111 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5113 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5115 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5118 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5120 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5122 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5124 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5127 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5128 REFPROPVARIANT value, BOOL *result)
5130 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5132 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5134 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5137 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5138 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5140 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5142 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5144 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5147 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5149 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5151 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5153 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5156 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5158 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5160 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5162 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5165 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5167 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5169 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5171 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5174 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5176 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5178 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5180 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5183 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5185 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5187 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5189 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5192 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5193 UINT32 size, UINT32 *length)
5195 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5197 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5199 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5202 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5204 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5206 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5208 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5211 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5213 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5215 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5217 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5220 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5221 UINT32 bufsize, UINT32 *blobsize)
5223 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5225 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5227 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5230 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5232 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5234 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5236 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5239 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5241 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5243 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5245 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5248 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5250 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5252 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5254 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5257 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5259 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5261 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5263 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5266 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5268 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5270 TRACE("%p.\n", iface);
5272 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5275 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5277 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5279 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5281 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5284 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5286 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5288 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5290 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5293 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5295 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5297 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5299 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5302 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5304 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5306 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5308 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5311 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5313 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5315 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5317 return IMFAttributes_SetString(wrapper->attributes, key, value);
5320 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5322 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5324 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5326 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5329 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5331 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5333 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5335 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5338 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5340 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5342 TRACE("%p.\n", iface);
5344 return IMFAttributes_LockStore(wrapper->attributes);
5347 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5349 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5351 TRACE("%p.\n", iface);
5353 return IMFAttributes_UnlockStore(wrapper->attributes);
5356 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5358 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5360 TRACE("%p, %p.\n", iface, count);
5362 return IMFAttributes_GetCount(wrapper->attributes, count);
5365 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5367 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5369 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5371 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5374 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5376 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5378 TRACE("%p, %p.\n", iface, dest);
5380 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5383 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5385 bytestream_wrapper_attributes_QueryInterface,
5386 bytestream_wrapper_attributes_AddRef,
5387 bytestream_wrapper_attributes_Release,
5388 bytestream_wrapper_attributes_GetItem,
5389 bytestream_wrapper_attributes_GetItemType,
5390 bytestream_wrapper_attributes_CompareItem,
5391 bytestream_wrapper_attributes_Compare,
5392 bytestream_wrapper_attributes_GetUINT32,
5393 bytestream_wrapper_attributes_GetUINT64,
5394 bytestream_wrapper_attributes_GetDouble,
5395 bytestream_wrapper_attributes_GetGUID,
5396 bytestream_wrapper_attributes_GetStringLength,
5397 bytestream_wrapper_attributes_GetString,
5398 bytestream_wrapper_attributes_GetAllocatedString,
5399 bytestream_wrapper_attributes_GetBlobSize,
5400 bytestream_wrapper_attributes_GetBlob,
5401 bytestream_wrapper_attributes_GetAllocatedBlob,
5402 bytestream_wrapper_attributes_GetUnknown,
5403 bytestream_wrapper_attributes_SetItem,
5404 bytestream_wrapper_attributes_DeleteItem,
5405 bytestream_wrapper_attributes_DeleteAllItems,
5406 bytestream_wrapper_attributes_SetUINT32,
5407 bytestream_wrapper_attributes_SetUINT64,
5408 bytestream_wrapper_attributes_SetDouble,
5409 bytestream_wrapper_attributes_SetGUID,
5410 bytestream_wrapper_attributes_SetString,
5411 bytestream_wrapper_attributes_SetBlob,
5412 bytestream_wrapper_attributes_SetUnknown,
5413 bytestream_wrapper_attributes_LockStore,
5414 bytestream_wrapper_attributes_UnlockStore,
5415 bytestream_wrapper_attributes_GetCount,
5416 bytestream_wrapper_attributes_GetItemByIndex,
5417 bytestream_wrapper_attributes_CopyAllItems
5420 /***********************************************************************
5421 * MFCreateMFByteStreamWrapper (mfplat.@)
5423 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5425 struct bytestream_wrapper *object;
5427 TRACE("%p, %p.\n", stream, wrapper);
5429 object = heap_alloc_zero(sizeof(*object));
5430 if (!object)
5431 return E_OUTOFMEMORY;
5433 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5434 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5435 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5436 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5437 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5438 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5439 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5440 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5442 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5443 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5444 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5445 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5446 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5447 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5448 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5450 object->stream = stream;
5451 IMFByteStream_AddRef(object->stream);
5453 object->refcount = 1;
5455 *wrapper = &object->IMFByteStream_iface;
5457 return S_OK;
5460 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5462 if(IsEqualGUID(riid, &IID_IUnknown)) {
5463 TRACE("(IID_IUnknown %p)\n", ppv);
5464 *ppv = iface;
5465 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5466 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5467 *ppv = iface;
5468 }else {
5469 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5470 *ppv = NULL;
5471 return E_NOINTERFACE;
5474 IUnknown_AddRef((IUnknown*)*ppv);
5475 return S_OK;
5478 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5480 TRACE("\n");
5481 return 2;
5484 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5486 TRACE("\n");
5487 return 1;
5490 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5491 const WCHAR *selector, CLSID *clsid)
5493 FIXME("(%d %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5494 return E_NOTIMPL;
5497 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5498 DWORD index, WCHAR **selector, CLSID *clsid)
5500 FIXME("(%d %d %p %p)\n", plugin_type, index, selector, clsid);
5501 return E_NOTIMPL;
5504 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5505 const WCHAR *selector, const CLSID *clsid)
5507 FIXME("(%d %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5508 return E_NOTIMPL;
5511 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5513 FIXME("(%d %s)\n", plugin_type, debugstr_guid(clsid));
5514 return E_NOTIMPL;
5517 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5519 FIXME("(%d %d %p)\n", plugin_type, index, clsid);
5520 return E_NOTIMPL;
5523 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5525 FIXME("(%d %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5526 return E_NOTIMPL;
5529 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5530 MFPluginControl_QueryInterface,
5531 MFPluginControl_AddRef,
5532 MFPluginControl_Release,
5533 MFPluginControl_GetPreferredClsid,
5534 MFPluginControl_GetPreferredClsidByIndex,
5535 MFPluginControl_SetPreferredClsid,
5536 MFPluginControl_IsDisabled,
5537 MFPluginControl_GetDisabledByIndex,
5538 MFPluginControl_SetDisabled
5541 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5543 /***********************************************************************
5544 * MFGetPluginControl (mfplat.@)
5546 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5548 TRACE("(%p)\n", ret);
5550 *ret = &plugin_control;
5551 return S_OK;
5554 typedef struct _mfsource
5556 IMFMediaSource IMFMediaSource_iface;
5557 LONG ref;
5558 } mfsource;
5560 static inline mfsource *impl_from_IMFMediaSource(IMFMediaSource *iface)
5562 return CONTAINING_RECORD(iface, mfsource, IMFMediaSource_iface);
5565 static HRESULT WINAPI mfsource_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
5567 mfsource *This = impl_from_IMFMediaSource(iface);
5569 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), out);
5571 if (IsEqualIID(riid, &IID_IMFMediaSource) ||
5572 IsEqualIID(riid, &IID_IMFMediaEventGenerator) ||
5573 IsEqualIID(riid, &IID_IUnknown))
5575 *out = &This->IMFMediaSource_iface;
5577 else
5579 FIXME("(%s, %p)\n", debugstr_guid(riid), out);
5580 *out = NULL;
5581 return E_NOINTERFACE;
5584 IUnknown_AddRef((IUnknown*)*out);
5585 return S_OK;
5588 static ULONG WINAPI mfsource_AddRef(IMFMediaSource *iface)
5590 mfsource *This = impl_from_IMFMediaSource(iface);
5591 ULONG ref = InterlockedIncrement(&This->ref);
5593 TRACE("(%p) ref=%u\n", This, ref);
5595 return ref;
5598 static ULONG WINAPI mfsource_Release(IMFMediaSource *iface)
5600 mfsource *This = impl_from_IMFMediaSource(iface);
5601 ULONG ref = InterlockedDecrement(&This->ref);
5603 TRACE("(%p) ref=%u\n", This, ref);
5605 if (!ref)
5607 HeapFree(GetProcessHeap(), 0, This);
5610 return ref;
5613 static HRESULT WINAPI mfsource_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
5615 mfsource *This = impl_from_IMFMediaSource(iface);
5617 FIXME("(%p)->(%#x, %p)\n", This, flags, event);
5619 return E_NOTIMPL;
5622 static HRESULT WINAPI mfsource_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
5624 mfsource *This = impl_from_IMFMediaSource(iface);
5626 FIXME("(%p)->(%p, %p)\n", This, callback, state);
5628 return E_NOTIMPL;
5631 static HRESULT WINAPI mfsource_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5633 mfsource *This = impl_from_IMFMediaSource(iface);
5635 FIXME("(%p)->(%p, %p)\n", This, result, event);
5637 return E_NOTIMPL;
5640 static HRESULT WINAPI mfsource_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
5641 HRESULT hr, const PROPVARIANT *value)
5643 mfsource *This = impl_from_IMFMediaSource(iface);
5645 FIXME("(%p)->(%d, %s, %#x, %p)\n", This, event_type, debugstr_guid(ext_type), hr, value);
5647 return E_NOTIMPL;
5650 static HRESULT WINAPI mfsource_GetCharacteristics(IMFMediaSource *iface, DWORD *characteristics)
5652 mfsource *This = impl_from_IMFMediaSource(iface);
5654 FIXME("(%p)->(%p): stub\n", This, characteristics);
5656 return E_NOTIMPL;
5659 static HRESULT WINAPI mfsource_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **descriptor)
5661 mfsource *This = impl_from_IMFMediaSource(iface);
5662 IMFStreamDescriptor *sd;
5663 IMFMediaType *mediatype;
5664 HRESULT hr;
5666 FIXME("(%p)->(%p): stub\n", This, descriptor);
5668 if (FAILED(hr = MFCreateMediaType(&mediatype)))
5669 return hr;
5671 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
5672 IMFMediaType_Release(mediatype);
5673 if (FAILED(hr))
5674 return hr;
5676 hr = MFCreatePresentationDescriptor(1, &sd, descriptor);
5677 IMFStreamDescriptor_Release(sd);
5679 return hr;
5682 static HRESULT WINAPI mfsource_Start(IMFMediaSource *iface, IMFPresentationDescriptor *descriptor,
5683 const GUID *time_format, const PROPVARIANT *start_position)
5685 mfsource *This = impl_from_IMFMediaSource(iface);
5687 FIXME("(%p)->(%p, %p, %p): stub\n", This, descriptor, time_format, start_position);
5689 return E_NOTIMPL;
5692 static HRESULT WINAPI mfsource_Stop(IMFMediaSource *iface)
5694 mfsource *This = impl_from_IMFMediaSource(iface);
5696 FIXME("(%p): stub\n", This);
5698 return E_NOTIMPL;
5701 static HRESULT WINAPI mfsource_Pause(IMFMediaSource *iface)
5703 mfsource *This = impl_from_IMFMediaSource(iface);
5705 FIXME("(%p): stub\n", This);
5707 return E_NOTIMPL;
5710 static HRESULT WINAPI mfsource_Shutdown(IMFMediaSource *iface)
5712 mfsource *This = impl_from_IMFMediaSource(iface);
5714 FIXME("(%p): stub\n", This);
5716 return S_OK;
5719 static const IMFMediaSourceVtbl mfsourcevtbl =
5721 mfsource_QueryInterface,
5722 mfsource_AddRef,
5723 mfsource_Release,
5724 mfsource_GetEvent,
5725 mfsource_BeginGetEvent,
5726 mfsource_EndGetEvent,
5727 mfsource_QueueEvent,
5728 mfsource_GetCharacteristics,
5729 mfsource_CreatePresentationDescriptor,
5730 mfsource_Start,
5731 mfsource_Stop,
5732 mfsource_Pause,
5733 mfsource_Shutdown,
5736 enum resolved_object_origin
5738 OBJECT_FROM_BYTESTREAM,
5739 OBJECT_FROM_URL,
5742 struct resolver_queued_result
5744 struct list entry;
5745 IUnknown *object;
5746 MF_OBJECT_TYPE obj_type;
5747 HRESULT hr;
5748 IRtwqAsyncResult *inner_result;
5749 enum resolved_object_origin origin;
5752 struct resolver_cancel_object
5754 IUnknown IUnknown_iface;
5755 LONG refcount;
5756 union
5758 IUnknown *handler;
5759 IMFByteStreamHandler *stream_handler;
5760 IMFSchemeHandler *scheme_handler;
5761 } u;
5762 IUnknown *cancel_cookie;
5763 enum resolved_object_origin origin;
5766 struct source_resolver
5768 IMFSourceResolver IMFSourceResolver_iface;
5769 LONG refcount;
5770 IRtwqAsyncCallback stream_callback;
5771 IRtwqAsyncCallback url_callback;
5772 CRITICAL_SECTION cs;
5773 struct list pending;
5776 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5778 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5781 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5783 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5786 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5788 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5791 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5792 IRtwqAsyncResult *result)
5794 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5795 struct resolver_queued_result *queued_result;
5796 union
5798 IUnknown *handler;
5799 IMFByteStreamHandler *stream_handler;
5800 IMFSchemeHandler *scheme_handler;
5801 } handler;
5803 queued_result = heap_alloc_zero(sizeof(*queued_result));
5805 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5807 switch (origin)
5809 case OBJECT_FROM_BYTESTREAM:
5810 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5811 &queued_result->obj_type, &queued_result->object);
5812 break;
5813 case OBJECT_FROM_URL:
5814 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5815 &queued_result->obj_type, &queued_result->object);
5816 break;
5817 default:
5818 queued_result->hr = E_FAIL;
5821 IUnknown_Release(handler.handler);
5823 if (SUCCEEDED(queued_result->hr))
5825 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5827 if (data->hEvent)
5829 queued_result->inner_result = inner_result;
5830 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5833 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5834 EnterCriticalSection(&resolver->cs);
5835 list_add_tail(&resolver->pending, &queued_result->entry);
5836 LeaveCriticalSection(&resolver->cs);
5838 if (data->hEvent)
5839 SetEvent(data->hEvent);
5840 else
5842 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5843 IRtwqAsyncResult *caller_result;
5845 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5847 RtwqInvokeCallback(caller_result);
5848 IRtwqAsyncResult_Release(caller_result);
5852 else
5853 heap_free(queued_result);
5855 return S_OK;
5858 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5860 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5863 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5865 if (IsEqualIID(riid, &IID_IUnknown))
5867 *obj = iface;
5868 IUnknown_AddRef(iface);
5869 return S_OK;
5872 *obj = NULL;
5873 return E_NOINTERFACE;
5876 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
5878 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5879 return InterlockedIncrement(&object->refcount);
5882 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
5884 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5885 ULONG refcount = InterlockedDecrement(&object->refcount);
5887 if (!refcount)
5889 if (object->cancel_cookie)
5890 IUnknown_Release(object->cancel_cookie);
5891 IUnknown_Release(object->u.handler);
5892 heap_free(object);
5895 return refcount;
5898 static const IUnknownVtbl resolver_cancel_object_vtbl =
5900 resolver_cancel_object_QueryInterface,
5901 resolver_cancel_object_AddRef,
5902 resolver_cancel_object_Release,
5905 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
5907 if (!iface)
5908 return NULL;
5910 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
5911 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
5914 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
5915 IUnknown *cancel_cookie, IUnknown **cancel_object)
5917 struct resolver_cancel_object *object;
5919 object = heap_alloc_zero(sizeof(*object));
5920 if (!object)
5921 return E_OUTOFMEMORY;
5923 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
5924 object->refcount = 1;
5925 object->u.handler = handler;
5926 IUnknown_AddRef(object->u.handler);
5927 object->cancel_cookie = cancel_cookie;
5928 IUnknown_AddRef(object->cancel_cookie);
5929 object->origin = origin;
5931 *cancel_object = &object->IUnknown_iface;
5933 return S_OK;
5936 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
5938 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
5939 IsEqualIID(riid, &IID_IUnknown))
5941 *obj = iface;
5942 IRtwqAsyncCallback_AddRef(iface);
5943 return S_OK;
5946 *obj = NULL;
5947 return E_NOINTERFACE;
5950 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
5952 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5953 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5956 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
5958 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5959 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5962 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
5964 return E_NOTIMPL;
5967 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5969 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5971 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
5974 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
5976 source_resolver_callback_QueryInterface,
5977 source_resolver_callback_stream_AddRef,
5978 source_resolver_callback_stream_Release,
5979 source_resolver_callback_GetParameters,
5980 source_resolver_callback_stream_Invoke,
5983 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
5985 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5986 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5989 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
5991 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5992 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5995 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5997 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5999 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
6002 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
6004 source_resolver_callback_QueryInterface,
6005 source_resolver_callback_url_AddRef,
6006 source_resolver_callback_url_Release,
6007 source_resolver_callback_GetParameters,
6008 source_resolver_callback_url_Invoke,
6011 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
6013 unsigned int j = 0, name_length, type;
6014 HRESULT hr = E_FAIL;
6015 WCHAR clsidW[39];
6016 CLSID clsid;
6018 name_length = ARRAY_SIZE(clsidW);
6019 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
6021 if (type == REG_SZ)
6023 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
6025 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
6026 if (SUCCEEDED(hr))
6027 break;
6031 name_length = ARRAY_SIZE(clsidW);
6034 return hr;
6037 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
6038 IMFByteStreamHandler **handler)
6040 static const char streamhandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers";
6041 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6042 IMFAttributes *attributes;
6043 const WCHAR *url_ext;
6044 WCHAR *mimeW = NULL;
6045 HRESULT hr = E_FAIL;
6046 unsigned int i, j;
6047 UINT32 length;
6049 *handler = NULL;
6051 /* MIME type */
6052 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6054 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
6055 IMFAttributes_Release(attributes);
6058 /* Extension */
6059 url_ext = url ? wcsrchr(url, '.') : NULL;
6061 if (!url_ext && !mimeW)
6063 CoTaskMemFree(mimeW);
6064 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6067 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6069 struct local_handler *local_handler;
6071 EnterCriticalSection(&local_handlers_section);
6073 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
6075 if ((mimeW && !lstrcmpiW(mimeW, local_handler->u.bytestream.mime))
6076 || (url_ext && !lstrcmpiW(url_ext, local_handler->u.bytestream.extension)))
6078 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
6079 (void **)handler)))
6080 break;
6084 LeaveCriticalSection(&local_handlers_section);
6086 if (*handler)
6087 return hr;
6090 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
6092 const WCHAR *namesW[2] = { mimeW, url_ext };
6093 HKEY hkey, hkey_handler;
6095 if (RegOpenKeyA(hkey_roots[i], streamhandlerspath, &hkey))
6096 continue;
6098 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6100 if (!namesW[j])
6101 continue;
6103 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6105 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6106 RegCloseKey(hkey_handler);
6109 if (SUCCEEDED(hr))
6110 break;
6113 RegCloseKey(hkey);
6115 if (SUCCEEDED(hr))
6116 break;
6119 CoTaskMemFree(mimeW);
6120 return hr;
6123 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6125 static const char schemehandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers";
6126 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6127 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6128 unsigned int i;
6130 TRACE("%s, %#x, %p.\n", debugstr_w(scheme), flags, handler);
6132 *handler = NULL;
6134 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6136 struct local_handler *local_handler;
6138 EnterCriticalSection(&local_handlers_section);
6140 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6142 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6144 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6145 (void **)handler)))
6146 break;
6150 LeaveCriticalSection(&local_handlers_section);
6152 if (*handler)
6153 return hr;
6156 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6158 HKEY hkey, hkey_handler;
6160 hr = MF_E_UNSUPPORTED_SCHEME;
6162 if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey))
6163 continue;
6165 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6167 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6168 RegCloseKey(hkey_handler);
6171 RegCloseKey(hkey);
6173 if (SUCCEEDED(hr))
6174 break;
6177 return hr;
6180 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6182 static const WCHAR fileschemeW[] = {'f','i','l','e',':',0};
6183 const WCHAR *ptr = url;
6184 unsigned int len;
6185 WCHAR *scheme;
6186 HRESULT hr;
6188 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6189 while (*ptr)
6191 WCHAR ch = towlower(*ptr);
6193 if (*ptr == '*' && ptr == url)
6195 ptr++;
6196 break;
6198 else if (!(*ptr >= '0' && *ptr <= '9') &&
6199 !(ch >= 'a' && ch <= 'z') &&
6200 *ptr != '+' && *ptr != '-' && *ptr != '.')
6202 break;
6205 ptr++;
6208 /* Schemes must end with a ':', if not found try "file:" */
6209 if (ptr == url || *ptr != ':')
6211 url = fileschemeW;
6212 ptr = fileschemeW + ARRAY_SIZE(fileschemeW) - 1;
6215 len = ptr - url;
6216 scheme = heap_alloc((len + 1) * sizeof(WCHAR));
6217 if (!scheme)
6218 return E_OUTOFMEMORY;
6220 memcpy(scheme, url, len * sizeof(WCHAR));
6221 scheme[len] = 0;
6223 hr = resolver_create_scheme_handler(scheme, flags, handler);
6224 if (FAILED(hr) && url != fileschemeW)
6225 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6227 heap_free(scheme);
6229 return hr;
6232 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6233 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6235 struct resolver_queued_result *queued_result = NULL, *iter;
6236 IUnknown *object;
6237 HRESULT hr;
6239 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6240 return hr;
6242 EnterCriticalSection(&resolver->cs);
6244 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6246 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6248 list_remove(&iter->entry);
6249 queued_result = iter;
6250 break;
6254 LeaveCriticalSection(&resolver->cs);
6256 IUnknown_Release(object);
6258 if (queued_result)
6260 *out = queued_result->object;
6261 *obj_type = queued_result->obj_type;
6262 hr = queued_result->hr;
6263 if (queued_result->inner_result)
6264 IRtwqAsyncResult_Release(queued_result->inner_result);
6265 heap_free(queued_result);
6267 else
6268 hr = E_UNEXPECTED;
6270 return hr;
6273 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6275 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6277 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6279 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6280 IsEqualIID(riid, &IID_IUnknown))
6282 *obj = &resolver->IMFSourceResolver_iface;
6284 else
6286 *obj = NULL;
6287 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6288 return E_NOINTERFACE;
6291 IUnknown_AddRef((IUnknown *)*obj);
6292 return S_OK;
6295 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6297 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6298 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6300 TRACE("%p, refcount %d.\n", iface, refcount);
6302 return refcount;
6305 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6307 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6308 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6309 struct resolver_queued_result *result, *result2;
6311 TRACE("%p, refcount %d.\n", iface, refcount);
6313 if (!refcount)
6315 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6317 if (result->object)
6318 IUnknown_Release(result->object);
6319 list_remove(&result->entry);
6320 heap_free(result);
6322 DeleteCriticalSection(&resolver->cs);
6323 heap_free(resolver);
6326 return refcount;
6329 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6330 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6332 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6333 IMFSchemeHandler *handler;
6334 IRtwqAsyncResult *result;
6335 RTWQASYNCRESULT *data;
6336 HRESULT hr;
6338 TRACE("%p, %s, %#x, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6340 if (!url || !obj_type || !object)
6341 return E_POINTER;
6343 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6344 return hr;
6346 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6347 IMFSchemeHandler_Release(handler);
6348 if (FAILED(hr))
6349 return hr;
6351 data = (RTWQASYNCRESULT *)result;
6352 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6354 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6355 (IUnknown *)result);
6356 if (FAILED(hr))
6358 IRtwqAsyncResult_Release(result);
6359 return hr;
6362 WaitForSingleObject(data->hEvent, INFINITE);
6364 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6365 IRtwqAsyncResult_Release(result);
6367 return hr;
6370 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6371 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6373 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6374 IMFByteStreamHandler *handler;
6375 IRtwqAsyncResult *result;
6376 RTWQASYNCRESULT *data;
6377 HRESULT hr;
6379 TRACE("%p, %p, %s, %#x, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6381 if (!stream || !obj_type || !object)
6382 return E_POINTER;
6384 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6385 goto fallback;
6387 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6388 IMFByteStreamHandler_Release(handler);
6389 if (FAILED(hr))
6390 return hr;
6392 data = (RTWQASYNCRESULT *)result;
6393 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6395 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6396 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6397 if (FAILED(hr))
6399 IRtwqAsyncResult_Release(result);
6400 return hr;
6403 WaitForSingleObject(data->hEvent, INFINITE);
6405 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6406 IRtwqAsyncResult_Release(result);
6408 /* TODO: following stub is left intentionally until real source plugins are implemented. */
6409 if (SUCCEEDED(hr))
6410 return hr;
6412 fallback:
6413 if (flags & MF_RESOLUTION_MEDIASOURCE)
6415 mfsource *new_object;
6417 new_object = HeapAlloc( GetProcessHeap(), 0, sizeof(*new_object) );
6418 if (!new_object)
6419 return E_OUTOFMEMORY;
6421 new_object->IMFMediaSource_iface.lpVtbl = &mfsourcevtbl;
6422 new_object->ref = 1;
6424 *object = (IUnknown *)&new_object->IMFMediaSource_iface;
6425 *obj_type = MF_OBJECT_MEDIASOURCE;
6426 return S_OK;
6429 return E_NOTIMPL;
6432 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6433 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6435 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6436 IMFSchemeHandler *handler;
6437 IUnknown *inner_cookie = NULL;
6438 IRtwqAsyncResult *result;
6439 HRESULT hr;
6441 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6443 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6444 return hr;
6446 if (cancel_cookie)
6447 *cancel_cookie = NULL;
6449 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6450 IMFSchemeHandler_Release(handler);
6451 if (FAILED(hr))
6452 return hr;
6454 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6455 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6457 if (SUCCEEDED(hr) && inner_cookie)
6458 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6460 IRtwqAsyncResult_Release(result);
6462 return hr;
6465 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6466 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6468 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6470 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6472 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6475 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6476 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6477 IUnknown *state)
6479 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6480 IMFByteStreamHandler *handler;
6481 IUnknown *inner_cookie = NULL;
6482 IRtwqAsyncResult *result;
6483 HRESULT hr;
6485 TRACE("%p, %p, %s, %#x, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6486 callback, state);
6488 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6489 return hr;
6491 if (cancel_cookie)
6492 *cancel_cookie = NULL;
6494 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6495 IMFByteStreamHandler_Release(handler);
6496 if (FAILED(hr))
6497 return hr;
6499 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6500 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6502 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6503 if (SUCCEEDED(hr) && inner_cookie)
6504 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6506 IRtwqAsyncResult_Release(result);
6508 return hr;
6511 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6512 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6514 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6516 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6518 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6521 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6523 struct resolver_cancel_object *object;
6524 HRESULT hr;
6526 TRACE("%p, %p.\n", iface, cancel_cookie);
6528 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6529 return E_UNEXPECTED;
6531 switch (object->origin)
6533 case OBJECT_FROM_BYTESTREAM:
6534 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6535 break;
6536 case OBJECT_FROM_URL:
6537 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6538 break;
6539 default:
6540 hr = E_UNEXPECTED;
6543 return hr;
6546 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6548 source_resolver_QueryInterface,
6549 source_resolver_AddRef,
6550 source_resolver_Release,
6551 source_resolver_CreateObjectFromURL,
6552 source_resolver_CreateObjectFromByteStream,
6553 source_resolver_BeginCreateObjectFromURL,
6554 source_resolver_EndCreateObjectFromURL,
6555 source_resolver_BeginCreateObjectFromByteStream,
6556 source_resolver_EndCreateObjectFromByteStream,
6557 source_resolver_CancelObjectCreation,
6560 /***********************************************************************
6561 * MFCreateSourceResolver (mfplat.@)
6563 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6565 struct source_resolver *object;
6567 TRACE("%p\n", resolver);
6569 if (!resolver)
6570 return E_POINTER;
6572 object = heap_alloc_zero(sizeof(*object));
6573 if (!object)
6574 return E_OUTOFMEMORY;
6576 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6577 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6578 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6579 object->refcount = 1;
6580 list_init(&object->pending);
6581 InitializeCriticalSection(&object->cs);
6583 *resolver = &object->IMFSourceResolver_iface;
6585 return S_OK;
6588 struct media_event
6590 struct attributes attributes;
6591 IMFMediaEvent IMFMediaEvent_iface;
6593 MediaEventType type;
6594 GUID extended_type;
6595 HRESULT status;
6596 PROPVARIANT value;
6599 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6601 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6604 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6606 struct media_event *event = impl_from_IMFMediaEvent(iface);
6608 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6610 if(IsEqualGUID(riid, &IID_IUnknown) ||
6611 IsEqualGUID(riid, &IID_IMFAttributes) ||
6612 IsEqualGUID(riid, &IID_IMFMediaEvent))
6614 *out = &event->IMFMediaEvent_iface;
6616 else
6618 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6619 *out = NULL;
6620 return E_NOINTERFACE;
6623 IUnknown_AddRef((IUnknown*)*out);
6624 return S_OK;
6627 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6629 struct media_event *event = impl_from_IMFMediaEvent(iface);
6630 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6632 TRACE("%p, refcount %u.\n", iface, refcount);
6634 return refcount;
6637 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6639 struct media_event *event = impl_from_IMFMediaEvent(iface);
6640 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6642 TRACE("%p, refcount %u.\n", iface, refcount);
6644 if (!refcount)
6646 clear_attributes_object(&event->attributes);
6647 PropVariantClear(&event->value);
6648 heap_free(event);
6651 return refcount;
6654 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6656 struct media_event *event = impl_from_IMFMediaEvent(iface);
6658 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6660 return attributes_GetItem(&event->attributes, key, value);
6663 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6665 struct media_event *event = impl_from_IMFMediaEvent(iface);
6667 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6669 return attributes_GetItemType(&event->attributes, key, type);
6672 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6674 struct media_event *event = impl_from_IMFMediaEvent(iface);
6676 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6678 return attributes_CompareItem(&event->attributes, key, value, result);
6681 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6682 BOOL *result)
6684 struct media_event *event = impl_from_IMFMediaEvent(iface);
6686 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6688 return attributes_Compare(&event->attributes, attrs, type, result);
6691 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6693 struct media_event *event = impl_from_IMFMediaEvent(iface);
6695 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6697 return attributes_GetUINT32(&event->attributes, key, value);
6700 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6702 struct media_event *event = impl_from_IMFMediaEvent(iface);
6704 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6706 return attributes_GetUINT64(&event->attributes, key, value);
6709 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6711 struct media_event *event = impl_from_IMFMediaEvent(iface);
6713 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6715 return attributes_GetDouble(&event->attributes, key, value);
6718 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6720 struct media_event *event = impl_from_IMFMediaEvent(iface);
6722 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6724 return attributes_GetGUID(&event->attributes, key, value);
6727 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6729 struct media_event *event = impl_from_IMFMediaEvent(iface);
6731 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6733 return attributes_GetStringLength(&event->attributes, key, length);
6736 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6737 UINT32 size, UINT32 *length)
6739 struct media_event *event = impl_from_IMFMediaEvent(iface);
6741 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6743 return attributes_GetString(&event->attributes, key, value, size, length);
6746 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6747 WCHAR **value, UINT32 *length)
6749 struct media_event *event = impl_from_IMFMediaEvent(iface);
6751 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6753 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6756 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6758 struct media_event *event = impl_from_IMFMediaEvent(iface);
6760 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
6762 return attributes_GetBlobSize(&event->attributes, key, size);
6765 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
6766 UINT32 bufsize, UINT32 *blobsize)
6768 struct media_event *event = impl_from_IMFMediaEvent(iface);
6770 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
6772 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
6775 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
6777 struct media_event *event = impl_from_IMFMediaEvent(iface);
6779 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
6781 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
6784 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
6786 struct media_event *event = impl_from_IMFMediaEvent(iface);
6788 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
6790 return attributes_GetUnknown(&event->attributes, key, riid, out);
6793 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
6795 struct media_event *event = impl_from_IMFMediaEvent(iface);
6797 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
6799 return attributes_SetItem(&event->attributes, key, value);
6802 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
6804 struct media_event *event = impl_from_IMFMediaEvent(iface);
6806 TRACE("%p, %s.\n", iface, debugstr_attr(key));
6808 return attributes_DeleteItem(&event->attributes, key);
6811 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
6813 struct media_event *event = impl_from_IMFMediaEvent(iface);
6815 TRACE("%p.\n", iface);
6817 return attributes_DeleteAllItems(&event->attributes);
6820 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
6822 struct media_event *event = impl_from_IMFMediaEvent(iface);
6824 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
6826 return attributes_SetUINT32(&event->attributes, key, value);
6829 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
6831 struct media_event *event = impl_from_IMFMediaEvent(iface);
6833 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
6835 return attributes_SetUINT64(&event->attributes, key, value);
6838 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
6840 struct media_event *event = impl_from_IMFMediaEvent(iface);
6842 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
6844 return attributes_SetDouble(&event->attributes, key, value);
6847 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
6849 struct media_event *event = impl_from_IMFMediaEvent(iface);
6851 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
6853 return attributes_SetGUID(&event->attributes, key, value);
6856 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
6858 struct media_event *event = impl_from_IMFMediaEvent(iface);
6860 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
6862 return attributes_SetString(&event->attributes, key, value);
6865 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
6867 struct media_event *event = impl_from_IMFMediaEvent(iface);
6869 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
6871 return attributes_SetBlob(&event->attributes, key, buf, size);
6874 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
6876 struct media_event *event = impl_from_IMFMediaEvent(iface);
6878 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
6880 return attributes_SetUnknown(&event->attributes, key, unknown);
6883 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
6885 struct media_event *event = impl_from_IMFMediaEvent(iface);
6887 TRACE("%p.\n", iface);
6889 return attributes_LockStore(&event->attributes);
6892 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
6894 struct media_event *event = impl_from_IMFMediaEvent(iface);
6896 TRACE("%p.\n", iface);
6898 return attributes_UnlockStore(&event->attributes);
6901 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
6903 struct media_event *event = impl_from_IMFMediaEvent(iface);
6905 TRACE("%p, %p.\n", iface, count);
6907 return attributes_GetCount(&event->attributes, count);
6910 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
6912 struct media_event *event = impl_from_IMFMediaEvent(iface);
6914 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
6916 return attributes_GetItemByIndex(&event->attributes, index, key, value);
6919 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
6921 struct media_event *event = impl_from_IMFMediaEvent(iface);
6923 TRACE("%p, %p.\n", iface, dest);
6925 return attributes_CopyAllItems(&event->attributes, dest);
6928 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
6930 struct media_event *event = impl_from_IMFMediaEvent(iface);
6932 TRACE("%p, %p.\n", iface, type);
6934 *type = event->type;
6936 return S_OK;
6939 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
6941 struct media_event *event = impl_from_IMFMediaEvent(iface);
6943 TRACE("%p, %p.\n", iface, extended_type);
6945 *extended_type = event->extended_type;
6947 return S_OK;
6950 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
6952 struct media_event *event = impl_from_IMFMediaEvent(iface);
6954 TRACE("%p, %p.\n", iface, status);
6956 *status = event->status;
6958 return S_OK;
6961 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
6963 struct media_event *event = impl_from_IMFMediaEvent(iface);
6965 TRACE("%p, %p.\n", iface, value);
6967 PropVariantCopy(value, &event->value);
6969 return S_OK;
6972 static const IMFMediaEventVtbl mfmediaevent_vtbl =
6974 mfmediaevent_QueryInterface,
6975 mfmediaevent_AddRef,
6976 mfmediaevent_Release,
6977 mfmediaevent_GetItem,
6978 mfmediaevent_GetItemType,
6979 mfmediaevent_CompareItem,
6980 mfmediaevent_Compare,
6981 mfmediaevent_GetUINT32,
6982 mfmediaevent_GetUINT64,
6983 mfmediaevent_GetDouble,
6984 mfmediaevent_GetGUID,
6985 mfmediaevent_GetStringLength,
6986 mfmediaevent_GetString,
6987 mfmediaevent_GetAllocatedString,
6988 mfmediaevent_GetBlobSize,
6989 mfmediaevent_GetBlob,
6990 mfmediaevent_GetAllocatedBlob,
6991 mfmediaevent_GetUnknown,
6992 mfmediaevent_SetItem,
6993 mfmediaevent_DeleteItem,
6994 mfmediaevent_DeleteAllItems,
6995 mfmediaevent_SetUINT32,
6996 mfmediaevent_SetUINT64,
6997 mfmediaevent_SetDouble,
6998 mfmediaevent_SetGUID,
6999 mfmediaevent_SetString,
7000 mfmediaevent_SetBlob,
7001 mfmediaevent_SetUnknown,
7002 mfmediaevent_LockStore,
7003 mfmediaevent_UnlockStore,
7004 mfmediaevent_GetCount,
7005 mfmediaevent_GetItemByIndex,
7006 mfmediaevent_CopyAllItems,
7007 mfmediaevent_GetType,
7008 mfmediaevent_GetExtendedType,
7009 mfmediaevent_GetStatus,
7010 mfmediaevent_GetValue,
7013 /***********************************************************************
7014 * MFCreateMediaEvent (mfplat.@)
7016 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
7017 IMFMediaEvent **event)
7019 struct media_event *object;
7020 HRESULT hr;
7022 TRACE("%s, %s, %#x, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
7023 debugstr_propvar(value), event);
7025 object = heap_alloc(sizeof(*object));
7026 if (!object)
7027 return E_OUTOFMEMORY;
7029 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
7031 heap_free(object);
7032 return hr;
7034 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
7036 object->type = type;
7037 object->extended_type = *extended_type;
7038 object->status = status;
7040 PropVariantInit(&object->value);
7041 if (value)
7042 PropVariantCopy(&object->value, value);
7044 *event = &object->IMFMediaEvent_iface;
7046 TRACE("Created event %p.\n", *event);
7048 return S_OK;
7051 struct event_queue
7053 IMFMediaEventQueue IMFMediaEventQueue_iface;
7054 LONG refcount;
7056 CRITICAL_SECTION cs;
7057 CONDITION_VARIABLE update_event;
7058 struct list events;
7059 BOOL is_shut_down;
7060 BOOL notified;
7061 IRtwqAsyncResult *subscriber;
7064 struct queued_event
7066 struct list entry;
7067 IMFMediaEvent *event;
7070 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
7072 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
7075 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
7077 struct list *head = list_head(&queue->events);
7078 struct queued_event *queued_event;
7079 IMFMediaEvent *event;
7081 if (!head)
7082 return NULL;
7084 queued_event = LIST_ENTRY(head, struct queued_event, entry);
7085 event = queued_event->event;
7086 list_remove(&queued_event->entry);
7087 heap_free(queued_event);
7088 return event;
7091 static void event_queue_cleanup(struct event_queue *queue)
7093 IMFMediaEvent *event;
7095 while ((event = queue_pop_event(queue)))
7096 IMFMediaEvent_Release(event);
7099 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7101 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7103 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7105 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7106 IsEqualIID(riid, &IID_IUnknown))
7108 *out = &queue->IMFMediaEventQueue_iface;
7109 IMFMediaEventQueue_AddRef(iface);
7110 return S_OK;
7113 WARN("Unsupported %s.\n", debugstr_guid(riid));
7114 *out = NULL;
7115 return E_NOINTERFACE;
7118 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7120 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7121 ULONG refcount = InterlockedIncrement(&queue->refcount);
7123 TRACE("%p, refcount %u.\n", iface, refcount);
7125 return refcount;
7128 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7130 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7131 ULONG refcount = InterlockedDecrement(&queue->refcount);
7133 TRACE("%p, refcount %u.\n", queue, refcount);
7135 if (!refcount)
7137 event_queue_cleanup(queue);
7138 DeleteCriticalSection(&queue->cs);
7139 heap_free(queue);
7142 return refcount;
7145 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7147 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7148 HRESULT hr = S_OK;
7150 TRACE("%p, %p.\n", iface, event);
7152 EnterCriticalSection(&queue->cs);
7154 if (queue->is_shut_down)
7155 hr = MF_E_SHUTDOWN;
7156 else if (queue->subscriber)
7157 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7158 else
7160 if (flags & MF_EVENT_FLAG_NO_WAIT)
7162 if (!(*event = queue_pop_event(queue)))
7163 hr = MF_E_NO_EVENTS_AVAILABLE;
7165 else
7167 while (list_empty(&queue->events) && !queue->is_shut_down)
7169 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7171 *event = queue_pop_event(queue);
7172 if (queue->is_shut_down)
7173 hr = MF_E_SHUTDOWN;
7177 LeaveCriticalSection(&queue->cs);
7179 return hr;
7182 static void queue_notify_subscriber(struct event_queue *queue)
7184 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7185 return;
7187 queue->notified = TRUE;
7188 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7191 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7193 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7194 MFASYNCRESULT *result_data = (MFASYNCRESULT *)queue->subscriber;
7195 HRESULT hr;
7197 TRACE("%p, %p, %p.\n", iface, callback, state);
7199 if (!callback)
7200 return E_INVALIDARG;
7202 EnterCriticalSection(&queue->cs);
7204 if (queue->is_shut_down)
7205 hr = MF_E_SHUTDOWN;
7206 else if (result_data)
7208 if (result_data->pCallback == callback)
7209 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7210 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7211 else
7212 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7214 else
7216 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7217 if (SUCCEEDED(hr))
7218 queue_notify_subscriber(queue);
7221 LeaveCriticalSection(&queue->cs);
7223 return hr;
7226 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7228 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7229 HRESULT hr = E_FAIL;
7231 TRACE("%p, %p, %p.\n", iface, result, event);
7233 EnterCriticalSection(&queue->cs);
7235 if (queue->is_shut_down)
7236 hr = MF_E_SHUTDOWN;
7237 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7239 *event = queue_pop_event(queue);
7240 if (queue->subscriber)
7241 IRtwqAsyncResult_Release(queue->subscriber);
7242 queue->subscriber = NULL;
7243 queue->notified = FALSE;
7244 hr = *event ? S_OK : E_FAIL;
7247 LeaveCriticalSection(&queue->cs);
7249 return hr;
7252 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7254 struct queued_event *queued_event;
7255 HRESULT hr = S_OK;
7257 queued_event = heap_alloc(sizeof(*queued_event));
7258 if (!queued_event)
7259 return E_OUTOFMEMORY;
7261 queued_event->event = event;
7263 EnterCriticalSection(&queue->cs);
7265 if (queue->is_shut_down)
7266 hr = MF_E_SHUTDOWN;
7267 else
7269 IMFMediaEvent_AddRef(queued_event->event);
7270 list_add_tail(&queue->events, &queued_event->entry);
7271 queue_notify_subscriber(queue);
7274 LeaveCriticalSection(&queue->cs);
7276 if (FAILED(hr))
7277 heap_free(queued_event);
7279 WakeAllConditionVariable(&queue->update_event);
7281 return hr;
7284 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7286 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7288 TRACE("%p, %p.\n", iface, event);
7290 return eventqueue_queue_event(queue, event);
7293 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7294 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7296 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7297 IMFMediaEvent *event;
7298 HRESULT hr;
7300 TRACE("%p, %s, %s, %#x, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7301 debugstr_propvar(value));
7303 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7304 return hr;
7306 hr = eventqueue_queue_event(queue, event);
7307 IMFMediaEvent_Release(event);
7308 return hr;
7311 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7312 REFGUID extended_type, HRESULT status, IUnknown *unk)
7314 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7315 IMFMediaEvent *event;
7316 PROPVARIANT value;
7317 HRESULT hr;
7319 TRACE("%p, %s, %s, %#x, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7321 value.vt = VT_UNKNOWN;
7322 value.u.punkVal = unk;
7324 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7325 return hr;
7327 hr = eventqueue_queue_event(queue, event);
7328 IMFMediaEvent_Release(event);
7329 return hr;
7332 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7334 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7336 TRACE("%p\n", queue);
7338 EnterCriticalSection(&queue->cs);
7340 if (!queue->is_shut_down)
7342 event_queue_cleanup(queue);
7343 queue->is_shut_down = TRUE;
7346 LeaveCriticalSection(&queue->cs);
7348 WakeAllConditionVariable(&queue->update_event);
7350 return S_OK;
7353 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7355 eventqueue_QueryInterface,
7356 eventqueue_AddRef,
7357 eventqueue_Release,
7358 eventqueue_GetEvent,
7359 eventqueue_BeginGetEvent,
7360 eventqueue_EndGetEvent,
7361 eventqueue_QueueEvent,
7362 eventqueue_QueueEventParamVar,
7363 eventqueue_QueueEventParamUnk,
7364 eventqueue_Shutdown
7367 /***********************************************************************
7368 * MFCreateEventQueue (mfplat.@)
7370 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7372 struct event_queue *object;
7374 TRACE("%p\n", queue);
7376 object = heap_alloc_zero(sizeof(*object));
7377 if (!object)
7378 return E_OUTOFMEMORY;
7380 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7381 object->refcount = 1;
7382 list_init(&object->events);
7383 InitializeCriticalSection(&object->cs);
7384 InitializeConditionVariable(&object->update_event);
7386 *queue = &object->IMFMediaEventQueue_iface;
7388 return S_OK;
7391 struct collection
7393 IMFCollection IMFCollection_iface;
7394 LONG refcount;
7395 IUnknown **elements;
7396 size_t capacity;
7397 size_t count;
7400 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7402 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7405 static void collection_clear(struct collection *collection)
7407 size_t i;
7409 for (i = 0; i < collection->count; ++i)
7411 if (collection->elements[i])
7412 IUnknown_Release(collection->elements[i]);
7415 heap_free(collection->elements);
7416 collection->elements = NULL;
7417 collection->count = 0;
7418 collection->capacity = 0;
7421 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7423 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7425 if (IsEqualIID(riid, &IID_IMFCollection) ||
7426 IsEqualIID(riid, &IID_IUnknown))
7428 *out = iface;
7429 IMFCollection_AddRef(iface);
7430 return S_OK;
7433 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7434 *out = NULL;
7435 return E_NOINTERFACE;
7438 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7440 struct collection *collection = impl_from_IMFCollection(iface);
7441 ULONG refcount = InterlockedIncrement(&collection->refcount);
7443 TRACE("%p, %d.\n", collection, refcount);
7445 return refcount;
7448 static ULONG WINAPI collection_Release(IMFCollection *iface)
7450 struct collection *collection = impl_from_IMFCollection(iface);
7451 ULONG refcount = InterlockedDecrement(&collection->refcount);
7453 TRACE("%p, %d.\n", collection, refcount);
7455 if (!refcount)
7457 collection_clear(collection);
7458 heap_free(collection->elements);
7459 heap_free(collection);
7462 return refcount;
7465 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7467 struct collection *collection = impl_from_IMFCollection(iface);
7469 TRACE("%p, %p.\n", iface, count);
7471 if (!count)
7472 return E_POINTER;
7474 *count = collection->count;
7476 return S_OK;
7479 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7481 struct collection *collection = impl_from_IMFCollection(iface);
7483 TRACE("%p, %u, %p.\n", iface, idx, element);
7485 if (!element)
7486 return E_POINTER;
7488 if (idx >= collection->count)
7489 return E_INVALIDARG;
7491 *element = collection->elements[idx];
7492 if (*element)
7493 IUnknown_AddRef(*element);
7495 return *element ? S_OK : E_UNEXPECTED;
7498 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7500 struct collection *collection = impl_from_IMFCollection(iface);
7502 TRACE("%p, %p.\n", iface, element);
7504 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7505 sizeof(*collection->elements)))
7506 return E_OUTOFMEMORY;
7508 collection->elements[collection->count++] = element;
7509 if (element)
7510 IUnknown_AddRef(element);
7512 return S_OK;
7515 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7517 struct collection *collection = impl_from_IMFCollection(iface);
7518 size_t count;
7520 TRACE("%p, %u, %p.\n", iface, idx, element);
7522 if (!element)
7523 return E_POINTER;
7525 if (idx >= collection->count)
7526 return E_INVALIDARG;
7528 *element = collection->elements[idx];
7530 count = collection->count - idx - 1;
7531 if (count)
7532 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7533 collection->count--;
7535 return S_OK;
7538 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7540 struct collection *collection = impl_from_IMFCollection(iface);
7541 size_t i;
7543 TRACE("%p, %u, %p.\n", iface, idx, element);
7545 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7546 sizeof(*collection->elements)))
7547 return E_OUTOFMEMORY;
7549 if (idx < collection->count)
7551 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7552 (collection->count - idx) * sizeof(*collection->elements));
7553 collection->count++;
7555 else
7557 for (i = collection->count; i < idx; ++i)
7558 collection->elements[i] = NULL;
7559 collection->count = idx + 1;
7562 collection->elements[idx] = element;
7563 if (collection->elements[idx])
7564 IUnknown_AddRef(collection->elements[idx]);
7566 return S_OK;
7569 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7571 struct collection *collection = impl_from_IMFCollection(iface);
7573 TRACE("%p.\n", iface);
7575 collection_clear(collection);
7577 return S_OK;
7580 static const IMFCollectionVtbl mfcollectionvtbl =
7582 collection_QueryInterface,
7583 collection_AddRef,
7584 collection_Release,
7585 collection_GetElementCount,
7586 collection_GetElement,
7587 collection_AddElement,
7588 collection_RemoveElement,
7589 collection_InsertElementAt,
7590 collection_RemoveAllElements,
7593 /***********************************************************************
7594 * MFCreateCollection (mfplat.@)
7596 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7598 struct collection *object;
7600 TRACE("%p\n", collection);
7602 if (!collection)
7603 return E_POINTER;
7605 object = heap_alloc_zero(sizeof(*object));
7606 if (!object)
7607 return E_OUTOFMEMORY;
7609 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7610 object->refcount = 1;
7612 *collection = &object->IMFCollection_iface;
7614 return S_OK;
7617 /***********************************************************************
7618 * MFHeapAlloc (mfplat.@)
7620 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7622 TRACE("%lu, %#x, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7623 return HeapAlloc(GetProcessHeap(), flags, size);
7626 /***********************************************************************
7627 * MFHeapFree (mfplat.@)
7629 void WINAPI MFHeapFree(void *p)
7631 TRACE("%p\n", p);
7632 HeapFree(GetProcessHeap(), 0, p);
7635 /***********************************************************************
7636 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7638 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7640 FIXME("(%p, %p): stub\n", stream, bytestream);
7642 return E_NOTIMPL;
7645 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7647 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7649 if (IsEqualIID(riid, &IID_IMFClock) ||
7650 IsEqualIID(riid, &IID_IUnknown))
7652 *obj = iface;
7653 IMFClock_AddRef(iface);
7654 return S_OK;
7657 WARN("Unsupported %s.\n", debugstr_guid(riid));
7658 *obj = NULL;
7659 return E_NOINTERFACE;
7662 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7664 struct system_clock *clock = impl_from_IMFClock(iface);
7665 ULONG refcount = InterlockedIncrement(&clock->refcount);
7667 TRACE("%p, refcount %u.\n", iface, refcount);
7669 return refcount;
7672 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7674 struct system_clock *clock = impl_from_IMFClock(iface);
7675 ULONG refcount = InterlockedDecrement(&clock->refcount);
7677 TRACE("%p, refcount %u.\n", iface, refcount);
7679 if (!refcount)
7680 heap_free(clock);
7682 return refcount;
7685 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7687 TRACE("%p, %p.\n", iface, flags);
7689 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7690 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7692 return S_OK;
7695 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7696 MFTIME *system_time)
7698 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7700 *clock_time = *system_time = MFGetSystemTime();
7702 return S_OK;
7705 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7707 TRACE("%p, %p.\n", iface, key);
7709 *key = 0;
7711 return S_OK;
7714 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7716 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7718 *state = MFCLOCK_STATE_RUNNING;
7720 return S_OK;
7723 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7725 TRACE("%p, %p.\n", iface, props);
7727 if (!props)
7728 return E_POINTER;
7730 memset(props, 0, sizeof(*props));
7731 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7732 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7733 props->dwClockJitter = 1;
7735 return S_OK;
7738 static const IMFClockVtbl system_clock_vtbl =
7740 system_clock_QueryInterface,
7741 system_clock_AddRef,
7742 system_clock_Release,
7743 system_clock_GetClockCharacteristics,
7744 system_clock_GetCorrelatedTime,
7745 system_clock_GetContinuityKey,
7746 system_clock_GetState,
7747 system_clock_GetProperties,
7750 static HRESULT create_system_clock(IMFClock **clock)
7752 struct system_clock *object;
7754 if (!(object = heap_alloc(sizeof(*object))))
7755 return E_OUTOFMEMORY;
7757 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7758 object->refcount = 1;
7760 *clock = &object->IMFClock_iface;
7762 return S_OK;
7765 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7767 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7769 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7771 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7772 IsEqualIID(riid, &IID_IUnknown))
7774 *obj = &source->IMFPresentationTimeSource_iface;
7776 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
7778 *obj = &source->IMFClockStateSink_iface;
7780 else
7782 WARN("Unsupported %s.\n", debugstr_guid(riid));
7783 *obj = NULL;
7784 return E_NOINTERFACE;
7787 IUnknown_AddRef((IUnknown *)*obj);
7788 return S_OK;
7791 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
7793 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7794 ULONG refcount = InterlockedIncrement(&source->refcount);
7796 TRACE("%p, refcount %u.\n", iface, refcount);
7798 return refcount;
7801 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
7803 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7804 ULONG refcount = InterlockedDecrement(&source->refcount);
7806 TRACE("%p, refcount %u.\n", iface, refcount);
7808 if (!refcount)
7810 if (source->clock)
7811 IMFClock_Release(source->clock);
7812 DeleteCriticalSection(&source->cs);
7813 heap_free(source);
7816 return refcount;
7819 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
7821 TRACE("%p, %p.\n", iface, flags);
7823 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7825 return S_OK;
7828 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
7829 LONGLONG *clock_time, MFTIME *system_time)
7831 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7832 HRESULT hr;
7834 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7836 EnterCriticalSection(&source->cs);
7837 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
7839 if (source->state == MFCLOCK_STATE_RUNNING)
7841 system_time_source_apply_rate(source, clock_time);
7842 *clock_time += source->start_offset;
7844 else
7845 *clock_time = source->start_offset;
7847 LeaveCriticalSection(&source->cs);
7849 return hr;
7852 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
7854 TRACE("%p, %p.\n", iface, key);
7856 *key = 0;
7858 return S_OK;
7861 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
7862 MFCLOCK_STATE *state)
7864 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7866 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7868 EnterCriticalSection(&source->cs);
7869 *state = source->state;
7870 LeaveCriticalSection(&source->cs);
7872 return S_OK;
7875 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
7877 TRACE("%p, %p.\n", iface, props);
7879 if (!props)
7880 return E_POINTER;
7882 memset(props, 0, sizeof(*props));
7883 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7884 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7885 props->dwClockJitter = 1;
7887 return S_OK;
7890 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
7892 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7894 TRACE("%p, %p.\n", iface, clock);
7896 *clock = source->clock;
7897 IMFClock_AddRef(*clock);
7899 return S_OK;
7902 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
7904 system_time_source_QueryInterface,
7905 system_time_source_AddRef,
7906 system_time_source_Release,
7907 system_time_source_GetClockCharacteristics,
7908 system_time_source_GetCorrelatedTime,
7909 system_time_source_GetContinuityKey,
7910 system_time_source_GetState,
7911 system_time_source_GetProperties,
7912 system_time_source_GetUnderlyingClock,
7915 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
7917 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7918 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
7921 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
7923 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7924 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
7927 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
7929 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7930 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
7933 enum clock_command
7935 CLOCK_CMD_START = 0,
7936 CLOCK_CMD_STOP,
7937 CLOCK_CMD_PAUSE,
7938 CLOCK_CMD_RESTART,
7939 CLOCK_CMD_MAX,
7942 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
7944 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
7945 { /* S S* P R */
7946 /* INVALID */ { 1, 0, 1, 0 },
7947 /* RUNNING */ { 1, 1, 1, 0 },
7948 /* STOPPED */ { 1, 1, 0, 0 },
7949 /* PAUSED */ { 1, 1, 0, 1 },
7951 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
7953 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
7954 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
7955 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
7956 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
7959 /* Special case that go against usual state change vs return value behavior. */
7960 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
7961 return S_OK;
7963 if (!state_change_is_allowed[source->state][command])
7964 return MF_E_INVALIDREQUEST;
7966 source->state = states[command];
7968 return S_OK;
7971 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
7972 LONGLONG start_offset)
7974 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7975 HRESULT hr;
7977 TRACE("%p, %s, %s.\n", iface, wine_dbgstr_longlong(system_time), wine_dbgstr_longlong(start_offset));
7979 EnterCriticalSection(&source->cs);
7980 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
7982 system_time_source_apply_rate(source, &system_time);
7983 source->start_offset = -system_time + start_offset;
7985 LeaveCriticalSection(&source->cs);
7987 return hr;
7990 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
7992 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7993 HRESULT hr;
7995 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(system_time));
7997 EnterCriticalSection(&source->cs);
7998 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
7999 source->start_offset = 0;
8000 LeaveCriticalSection(&source->cs);
8002 return hr;
8005 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
8007 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8008 HRESULT hr;
8010 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(system_time));
8012 EnterCriticalSection(&source->cs);
8013 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
8015 system_time_source_apply_rate(source, &system_time);
8016 source->start_offset += system_time;
8018 LeaveCriticalSection(&source->cs);
8020 return hr;
8023 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
8025 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8026 HRESULT hr;
8028 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(system_time));
8030 EnterCriticalSection(&source->cs);
8031 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
8033 system_time_source_apply_rate(source, &system_time);
8034 source->start_offset -= system_time;
8036 LeaveCriticalSection(&source->cs);
8038 return hr;
8041 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
8043 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8044 double intpart;
8046 TRACE("%p, %s, %f.\n", iface, wine_dbgstr_longlong(system_time), rate);
8048 if (rate == 0.0f)
8049 return MF_E_UNSUPPORTED_RATE;
8051 modf(rate, &intpart);
8053 EnterCriticalSection(&source->cs);
8054 source->rate = rate;
8055 source->i_rate = rate == intpart ? rate : 0;
8056 LeaveCriticalSection(&source->cs);
8058 return S_OK;
8061 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8063 system_time_source_sink_QueryInterface,
8064 system_time_source_sink_AddRef,
8065 system_time_source_sink_Release,
8066 system_time_source_sink_OnClockStart,
8067 system_time_source_sink_OnClockStop,
8068 system_time_source_sink_OnClockPause,
8069 system_time_source_sink_OnClockRestart,
8070 system_time_source_sink_OnClockSetRate,
8073 /***********************************************************************
8074 * MFCreateSystemTimeSource (mfplat.@)
8076 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8078 struct system_time_source *object;
8079 HRESULT hr;
8081 TRACE("%p.\n", time_source);
8083 object = heap_alloc_zero(sizeof(*object));
8084 if (!object)
8085 return E_OUTOFMEMORY;
8087 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8088 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8089 object->refcount = 1;
8090 object->rate = 1.0f;
8091 object->i_rate = 1;
8092 InitializeCriticalSection(&object->cs);
8094 if (FAILED(hr = create_system_clock(&object->clock)))
8096 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8097 return hr;
8100 *time_source = &object->IMFPresentationTimeSource_iface;
8102 return S_OK;
8105 struct async_create_file
8107 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8108 LONG refcount;
8109 MF_FILE_ACCESSMODE access_mode;
8110 MF_FILE_OPENMODE open_mode;
8111 MF_FILE_FLAGS flags;
8112 WCHAR *path;
8115 struct async_create_file_result
8117 struct list entry;
8118 IRtwqAsyncResult *result;
8119 IMFByteStream *stream;
8122 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8123 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8125 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8127 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8130 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8132 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8133 IsEqualIID(riid, &IID_IUnknown))
8135 *obj = iface;
8136 IRtwqAsyncCallback_AddRef(iface);
8137 return S_OK;
8140 *obj = NULL;
8141 return E_NOINTERFACE;
8144 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8146 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8147 ULONG refcount = InterlockedIncrement(&async->refcount);
8149 TRACE("%p, refcount %u.\n", iface, refcount);
8151 return refcount;
8154 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8156 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8157 ULONG refcount = InterlockedDecrement(&async->refcount);
8159 TRACE("%p, refcount %u.\n", iface, refcount);
8161 if (!refcount)
8163 heap_free(async->path);
8164 heap_free(async);
8167 return refcount;
8170 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8172 return E_NOTIMPL;
8175 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8177 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8178 IRtwqAsyncResult *caller;
8179 IMFByteStream *stream;
8180 HRESULT hr;
8182 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8184 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8185 if (SUCCEEDED(hr))
8187 struct async_create_file_result *result_item;
8189 result_item = heap_alloc(sizeof(*result_item));
8190 if (result_item)
8192 result_item->result = caller;
8193 IRtwqAsyncResult_AddRef(caller);
8194 result_item->stream = stream;
8195 IMFByteStream_AddRef(stream);
8197 EnterCriticalSection(&async_create_file_cs);
8198 list_add_tail(&async_create_file_results, &result_item->entry);
8199 LeaveCriticalSection(&async_create_file_cs);
8202 IMFByteStream_Release(stream);
8204 else
8205 IRtwqAsyncResult_SetStatus(caller, hr);
8207 RtwqInvokeCallback(caller);
8209 return S_OK;
8212 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8214 async_create_file_callback_QueryInterface,
8215 async_create_file_callback_AddRef,
8216 async_create_file_callback_Release,
8217 async_create_file_callback_GetParameters,
8218 async_create_file_callback_Invoke,
8221 /***********************************************************************
8222 * MFBeginCreateFile (mfplat.@)
8224 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8225 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8227 struct async_create_file *async = NULL;
8228 IRtwqAsyncResult *caller, *item = NULL;
8229 HRESULT hr;
8231 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8232 cancel_cookie);
8234 if (cancel_cookie)
8235 *cancel_cookie = NULL;
8237 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8238 return hr;
8240 async = heap_alloc(sizeof(*async));
8241 if (!async)
8243 hr = E_OUTOFMEMORY;
8244 goto failed;
8247 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8248 async->refcount = 1;
8249 async->access_mode = access_mode;
8250 async->open_mode = open_mode;
8251 async->flags = flags;
8252 if (FAILED(hr = heap_strdupW(path, &async->path)))
8253 goto failed;
8255 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8256 if (FAILED(hr))
8257 goto failed;
8259 if (cancel_cookie)
8261 *cancel_cookie = (IUnknown *)caller;
8262 IUnknown_AddRef(*cancel_cookie);
8265 hr = RtwqInvokeCallback(item);
8267 failed:
8268 if (async)
8269 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8270 if (item)
8271 IRtwqAsyncResult_Release(item);
8272 if (caller)
8273 IRtwqAsyncResult_Release(caller);
8275 return hr;
8278 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8280 struct async_create_file_result *item;
8281 HRESULT hr = MF_E_UNEXPECTED;
8282 IRtwqAsyncResult *result;
8284 *stream = NULL;
8286 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8287 return hr;
8289 EnterCriticalSection(&async_create_file_cs);
8291 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8293 if (result == item->result)
8295 *stream = item->stream;
8296 IRtwqAsyncResult_Release(item->result);
8297 list_remove(&item->entry);
8298 heap_free(item);
8299 break;
8303 LeaveCriticalSection(&async_create_file_cs);
8305 if (*stream)
8306 hr = IRtwqAsyncResult_GetStatus(result);
8308 IRtwqAsyncResult_Release(result);
8310 return hr;
8313 /***********************************************************************
8314 * MFEndCreateFile (mfplat.@)
8316 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8318 TRACE("%p, %p.\n", result, stream);
8320 return async_create_file_pull_result((IUnknown *)result, stream);
8323 /***********************************************************************
8324 * MFCancelCreateFile (mfplat.@)
8326 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8328 IMFByteStream *stream = NULL;
8329 HRESULT hr;
8331 TRACE("%p.\n", cancel_cookie);
8333 hr = async_create_file_pull_result(cancel_cookie, &stream);
8335 if (stream)
8336 IMFByteStream_Release(stream);
8338 return hr;
8341 /***********************************************************************
8342 * MFRegisterLocalSchemeHandler (mfplat.@)
8344 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8346 struct local_handler *handler;
8347 HRESULT hr;
8349 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8351 if (!scheme || !activate)
8352 return E_INVALIDARG;
8354 if (!(handler = heap_alloc(sizeof(*handler))))
8355 return E_OUTOFMEMORY;
8357 if (FAILED(hr = heap_strdupW(scheme, &handler->u.scheme)))
8359 heap_free(handler);
8360 return hr;
8362 handler->activate = activate;
8363 IMFActivate_AddRef(handler->activate);
8365 EnterCriticalSection(&local_handlers_section);
8366 list_add_head(&local_scheme_handlers, &handler->entry);
8367 LeaveCriticalSection(&local_handlers_section);
8369 return S_OK;
8372 /***********************************************************************
8373 * MFRegisterLocalByteStreamHandler (mfplat.@)
8375 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8377 struct local_handler *handler;
8378 HRESULT hr;
8380 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8382 if ((!extension && !mime) || !activate)
8383 return E_INVALIDARG;
8385 if (!(handler = heap_alloc_zero(sizeof(*handler))))
8386 return E_OUTOFMEMORY;
8388 hr = heap_strdupW(extension, &handler->u.bytestream.extension);
8389 if (SUCCEEDED(hr))
8390 hr = heap_strdupW(mime, &handler->u.bytestream.mime);
8392 if (FAILED(hr))
8393 goto failed;
8395 EnterCriticalSection(&local_handlers_section);
8396 list_add_head(&local_bytestream_handlers, &handler->entry);
8397 LeaveCriticalSection(&local_handlers_section);
8399 return hr;
8401 failed:
8402 heap_free(handler->u.bytestream.extension);
8403 heap_free(handler->u.bytestream.mime);
8404 heap_free(handler);
8406 return hr;
8409 struct property_store
8411 IPropertyStore IPropertyStore_iface;
8412 LONG refcount;
8413 CRITICAL_SECTION cs;
8414 size_t count, capacity;
8415 struct
8417 PROPERTYKEY key;
8418 PROPVARIANT value;
8419 } *values;
8422 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8424 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8427 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8429 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8431 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8433 *obj = iface;
8434 IPropertyStore_AddRef(iface);
8435 return S_OK;
8438 *obj = NULL;
8439 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8440 return E_NOINTERFACE;
8443 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8445 struct property_store *store = impl_from_IPropertyStore(iface);
8446 ULONG refcount = InterlockedIncrement(&store->refcount);
8448 TRACE("%p, refcount %d.\n", iface, refcount);
8450 return refcount;
8453 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8455 struct property_store *store = impl_from_IPropertyStore(iface);
8456 ULONG refcount = InterlockedDecrement(&store->refcount);
8458 TRACE("%p, refcount %d.\n", iface, refcount);
8460 if (!refcount)
8462 DeleteCriticalSection(&store->cs);
8463 heap_free(store->values);
8464 heap_free(store);
8467 return refcount;
8470 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8472 struct property_store *store = impl_from_IPropertyStore(iface);
8474 TRACE("%p, %p.\n", iface, count);
8476 if (!count)
8477 return E_INVALIDARG;
8479 EnterCriticalSection(&store->cs);
8480 *count = store->count;
8481 LeaveCriticalSection(&store->cs);
8482 return S_OK;
8485 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8487 struct property_store *store = impl_from_IPropertyStore(iface);
8489 TRACE("%p, %u, %p.\n", iface, index, key);
8491 EnterCriticalSection(&store->cs);
8493 if (index >= store->count)
8495 LeaveCriticalSection(&store->cs);
8496 return E_INVALIDARG;
8499 *key = store->values[index].key;
8501 LeaveCriticalSection(&store->cs);
8502 return S_OK;
8505 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8507 struct property_store *store = impl_from_IPropertyStore(iface);
8508 unsigned int i;
8510 TRACE("%p, %p, %p.\n", iface, key, value);
8512 if (!value)
8513 return E_INVALIDARG;
8515 if (!key)
8516 return S_FALSE;
8518 EnterCriticalSection(&store->cs);
8520 for (i = 0; i < store->count; ++i)
8522 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8524 PropVariantCopy(value, &store->values[i].value);
8525 LeaveCriticalSection(&store->cs);
8526 return S_OK;
8530 LeaveCriticalSection(&store->cs);
8531 return S_FALSE;
8534 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8536 struct property_store *store = impl_from_IPropertyStore(iface);
8537 unsigned int i;
8539 TRACE("%p, %p, %p.\n", iface, key, value);
8541 EnterCriticalSection(&store->cs);
8543 for (i = 0; i < store->count; ++i)
8545 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8547 PropVariantCopy(&store->values[i].value, value);
8548 LeaveCriticalSection(&store->cs);
8549 return S_OK;
8553 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8555 LeaveCriticalSection(&store->cs);
8556 return E_OUTOFMEMORY;
8559 store->values[store->count].key = *key;
8560 PropVariantCopy(&store->values[store->count].value, value);
8561 ++store->count;
8563 LeaveCriticalSection(&store->cs);
8564 return S_OK;
8567 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8569 TRACE("%p.\n", iface);
8571 return E_NOTIMPL;
8574 static const IPropertyStoreVtbl property_store_vtbl =
8576 property_store_QueryInterface,
8577 property_store_AddRef,
8578 property_store_Release,
8579 property_store_GetCount,
8580 property_store_GetAt,
8581 property_store_GetValue,
8582 property_store_SetValue,
8583 property_store_Commit,
8586 /***********************************************************************
8587 * CreatePropertyStore (mfplat.@)
8589 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8591 struct property_store *object;
8593 TRACE("%p.\n", store);
8595 if (!store)
8596 return E_INVALIDARG;
8598 if (!(object = heap_alloc_zero(sizeof(*object))))
8599 return E_OUTOFMEMORY;
8601 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8602 object->refcount = 1;
8603 InitializeCriticalSection(&object->cs);
8605 TRACE("Created store %p.\n", object);
8606 *store = &object->IPropertyStore_iface;
8608 return S_OK;
8611 struct dxgi_device_manager
8613 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8614 LONG refcount;
8615 UINT token;
8616 IDXGIDevice *device;
8619 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8621 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8624 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8626 TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj);
8628 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8629 IsEqualGUID(riid, &IID_IUnknown))
8631 *obj = iface;
8632 IMFDXGIDeviceManager_AddRef(iface);
8633 return S_OK;
8636 WARN("Unsupported %s.\n", debugstr_guid(riid));
8637 *obj = NULL;
8638 return E_NOINTERFACE;
8641 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8643 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8644 ULONG refcount = InterlockedIncrement(&manager->refcount);
8646 TRACE("(%p) ref=%u.\n", iface, refcount);
8648 return refcount;
8651 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8653 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8654 ULONG refcount = InterlockedDecrement(&manager->refcount);
8656 TRACE("(%p) ref=%u.\n", iface, refcount);
8658 if (!refcount)
8660 if (manager->device)
8661 IDXGIDevice_Release(manager->device);
8662 heap_free(manager);
8665 return refcount;
8668 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE device)
8670 FIXME("(%p, %p): stub.\n", iface, device);
8672 return E_NOTIMPL;
8675 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE device,
8676 REFIID riid, void **service)
8678 FIXME("(%p, %p, %s, %p): stub.\n", iface, device, debugstr_guid(riid), service);
8680 return E_NOTIMPL;
8683 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE device,
8684 REFIID riid, void **ppv, BOOL block)
8686 FIXME("(%p, %p, %s, %p, %d): stub.\n", iface, device, wine_dbgstr_guid(riid), ppv, block);
8688 return E_NOTIMPL;
8691 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *device)
8693 FIXME("(%p, %p): stub.\n", iface, device);
8695 return E_NOTIMPL;
8698 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
8700 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8701 IDXGIDevice *dxgi_device;
8702 HRESULT hr;
8704 TRACE("(%p, %p, %u).\n", iface, device, token);
8706 if (!device || token != manager->token)
8707 return E_INVALIDARG;
8709 hr = IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
8710 if (SUCCEEDED(hr))
8712 if (manager->device)
8713 IDXGIDevice_Release(manager->device);
8714 manager->device = dxgi_device;
8716 else
8717 hr = E_INVALIDARG;
8719 return hr;
8722 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE device)
8724 FIXME("(%p, %p): stub.\n", iface, device);
8726 return E_NOTIMPL;
8729 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE device, BOOL state)
8731 FIXME("(%p, %p, %d): stub.\n", iface, device, state);
8733 return E_NOTIMPL;
8736 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
8738 dxgi_device_manager_QueryInterface,
8739 dxgi_device_manager_AddRef,
8740 dxgi_device_manager_Release,
8741 dxgi_device_manager_CloseDeviceHandle,
8742 dxgi_device_manager_GetVideoService,
8743 dxgi_device_manager_LockDevice,
8744 dxgi_device_manager_OpenDeviceHandle,
8745 dxgi_device_manager_ResetDevice,
8746 dxgi_device_manager_TestDevice,
8747 dxgi_device_manager_UnlockDevice,
8750 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8752 struct dxgi_device_manager *object;
8754 TRACE("(%p, %p).\n", token, manager);
8756 if (!token || !manager)
8757 return E_POINTER;
8759 object = heap_alloc(sizeof(*object));
8760 if (!object)
8761 return E_OUTOFMEMORY;
8763 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
8764 object->refcount = 1;
8765 object->token = GetTickCount();
8766 object->device = NULL;
8768 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
8770 *token = object->token;
8771 *manager = &object->IMFDXGIDeviceManager_iface;
8773 return S_OK;