mf/session: Forward more events to the application.
[wine/zf.git] / dlls / mfplat / main.c
blob6fb8661dba4908a40552b701e43ae18cbc3faf3a
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 "d3d11.h"
36 #include "uuids.h"
38 #include "wine/debug.h"
39 #include "wine/list.h"
41 #include "mfplat_private.h"
42 #include "mfreadwrite.h"
43 #include "mfmediaengine.h"
44 #include "propvarutil.h"
45 #include "strsafe.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
49 static HRESULT heap_strdupW(const WCHAR *str, WCHAR **dest)
51 HRESULT hr = S_OK;
53 if (str)
55 unsigned int size;
57 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
58 *dest = heap_alloc(size);
59 if (*dest)
60 memcpy(*dest, str, size);
61 else
62 hr = E_OUTOFMEMORY;
64 else
65 *dest = NULL;
67 return hr;
70 struct local_handler
72 struct list entry;
73 union
75 WCHAR *scheme;
76 struct
78 WCHAR *extension;
79 WCHAR *mime;
80 } bytestream;
81 } u;
82 IMFActivate *activate;
85 static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
87 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
88 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
90 struct mft_registration
92 struct list entry;
93 IClassFactory *factory;
94 CLSID clsid;
95 GUID category;
96 WCHAR *name;
97 DWORD flags;
98 MFT_REGISTER_TYPE_INFO *input_types;
99 UINT32 input_types_count;
100 MFT_REGISTER_TYPE_INFO *output_types;
101 UINT32 output_types_count;
102 BOOL local;
105 static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
107 static struct list local_mfts = LIST_INIT(local_mfts);
109 struct transform_activate
111 struct attributes attributes;
112 IMFActivate IMFActivate_iface;
113 IClassFactory *factory;
114 IMFTransform *transform;
117 struct system_clock
119 IMFClock IMFClock_iface;
120 LONG refcount;
123 struct system_time_source
125 IMFPresentationTimeSource IMFPresentationTimeSource_iface;
126 IMFClockStateSink IMFClockStateSink_iface;
127 LONG refcount;
128 MFCLOCK_STATE state;
129 IMFClock *clock;
130 LONGLONG start_offset;
131 float rate;
132 int i_rate;
133 CRITICAL_SECTION cs;
136 static void system_time_source_apply_rate(const struct system_time_source *source, LONGLONG *value)
138 if (source->i_rate)
139 *value *= source->i_rate;
140 else
141 *value *= source->rate;
144 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
146 return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
149 static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
151 return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
154 static struct system_clock *impl_from_IMFClock(IMFClock *iface)
156 return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
159 static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface)
161 return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface);
164 static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out)
166 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
168 if (IsEqualIID(riid, &IID_IMFActivate) ||
169 IsEqualIID(riid, &IID_IMFAttributes) ||
170 IsEqualIID(riid, &IID_IUnknown))
172 *out = iface;
173 IMFActivate_AddRef(iface);
174 return S_OK;
177 WARN("Unsupported %s.\n", debugstr_guid(riid));
178 *out = NULL;
179 return E_NOINTERFACE;
182 static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface)
184 struct transform_activate *activate = impl_from_IMFActivate(iface);
185 ULONG refcount = InterlockedIncrement(&activate->attributes.ref);
187 TRACE("%p, refcount %u.\n", iface, refcount);
189 return refcount;
192 static ULONG WINAPI transform_activate_Release(IMFActivate *iface)
194 struct transform_activate *activate = impl_from_IMFActivate(iface);
195 ULONG refcount = InterlockedDecrement(&activate->attributes.ref);
197 TRACE("%p, refcount %u.\n", iface, refcount);
199 if (!refcount)
201 clear_attributes_object(&activate->attributes);
202 if (activate->factory)
203 IClassFactory_Release(activate->factory);
204 if (activate->transform)
205 IMFTransform_Release(activate->transform);
206 heap_free(activate);
209 return refcount;
212 static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
214 struct transform_activate *activate = impl_from_IMFActivate(iface);
216 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
218 return attributes_GetItem(&activate->attributes, key, value);
221 static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
223 struct transform_activate *activate = impl_from_IMFActivate(iface);
225 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
227 return attributes_GetItemType(&activate->attributes, key, type);
230 static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value,
231 BOOL *result)
233 struct transform_activate *activate = impl_from_IMFActivate(iface);
235 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
237 return attributes_CompareItem(&activate->attributes, key, value, result);
240 static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs,
241 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
243 struct transform_activate *activate = impl_from_IMFActivate(iface);
245 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
247 return attributes_Compare(&activate->attributes, theirs, match_type, ret);
250 static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
252 struct transform_activate *activate = impl_from_IMFActivate(iface);
254 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
256 return attributes_GetUINT32(&activate->attributes, key, value);
259 static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
261 struct transform_activate *activate = impl_from_IMFActivate(iface);
263 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
265 return attributes_GetUINT64(&activate->attributes, key, value);
268 static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value)
270 struct transform_activate *activate = impl_from_IMFActivate(iface);
272 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
274 return attributes_GetDouble(&activate->attributes, key, value);
277 static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
279 struct transform_activate *activate = impl_from_IMFActivate(iface);
281 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
283 return attributes_GetGUID(&activate->attributes, key, value);
286 static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
288 struct transform_activate *activate = impl_from_IMFActivate(iface);
290 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
292 return attributes_GetStringLength(&activate->attributes, key, length);
295 static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
296 UINT32 size, UINT32 *length)
298 struct transform_activate *activate = impl_from_IMFActivate(iface);
300 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
302 return attributes_GetString(&activate->attributes, key, value, size, length);
305 static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value,
306 UINT32 *length)
308 struct transform_activate *activate = impl_from_IMFActivate(iface);
310 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
312 return attributes_GetAllocatedString(&activate->attributes, key, value, length);
315 static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
317 struct transform_activate *activate = impl_from_IMFActivate(iface);
319 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
321 return attributes_GetBlobSize(&activate->attributes, key, size);
324 static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize,
325 UINT32 *blobsize)
327 struct transform_activate *activate = impl_from_IMFActivate(iface);
329 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
331 return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize);
334 static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
336 struct transform_activate *activate = impl_from_IMFActivate(iface);
338 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
340 return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size);
343 static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out)
345 struct transform_activate *activate = impl_from_IMFActivate(iface);
347 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
349 return attributes_GetUnknown(&activate->attributes, key, riid, out);
352 static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
354 struct transform_activate *activate = impl_from_IMFActivate(iface);
356 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
358 return attributes_SetItem(&activate->attributes, key, value);
361 static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key)
363 struct transform_activate *activate = impl_from_IMFActivate(iface);
365 TRACE("%p, %s.\n", iface, debugstr_attr(key));
367 return attributes_DeleteItem(&activate->attributes, key);
370 static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface)
372 struct transform_activate *activate = impl_from_IMFActivate(iface);
374 TRACE("%p.\n", iface);
376 return attributes_DeleteAllItems(&activate->attributes);
379 static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
381 struct transform_activate *activate = impl_from_IMFActivate(iface);
383 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
385 return attributes_SetUINT32(&activate->attributes, key, value);
388 static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
390 struct transform_activate *activate = impl_from_IMFActivate(iface);
392 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
394 return attributes_SetUINT64(&activate->attributes, key, value);
397 static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value)
399 struct transform_activate *activate = impl_from_IMFActivate(iface);
401 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
403 return attributes_SetDouble(&activate->attributes, key, value);
406 static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
408 struct transform_activate *activate = impl_from_IMFActivate(iface);
410 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
412 return attributes_SetGUID(&activate->attributes, key, value);
415 static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
417 struct transform_activate *activate = impl_from_IMFActivate(iface);
419 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
421 return attributes_SetString(&activate->attributes, key, value);
424 static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
426 struct transform_activate *activate = impl_from_IMFActivate(iface);
428 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
430 return attributes_SetBlob(&activate->attributes, key, buf, size);
433 static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
435 struct transform_activate *activate = impl_from_IMFActivate(iface);
437 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
439 return attributes_SetUnknown(&activate->attributes, key, unknown);
442 static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface)
444 struct transform_activate *activate = impl_from_IMFActivate(iface);
446 TRACE("%p.\n", iface);
448 return attributes_LockStore(&activate->attributes);
451 static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface)
453 struct transform_activate *activate = impl_from_IMFActivate(iface);
455 TRACE("%p.\n", iface);
457 return attributes_UnlockStore(&activate->attributes);
460 static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count)
462 struct transform_activate *activate = impl_from_IMFActivate(iface);
464 TRACE("%p, %p.\n", iface, count);
466 return attributes_GetCount(&activate->attributes, count);
469 static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key,
470 PROPVARIANT *value)
472 struct transform_activate *activate = impl_from_IMFActivate(iface);
474 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
476 return attributes_GetItemByIndex(&activate->attributes, index, key, value);
479 static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
481 struct transform_activate *activate = impl_from_IMFActivate(iface);
483 TRACE("%p, %p.\n", iface, dest);
485 return attributes_CopyAllItems(&activate->attributes, dest);
488 static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
490 struct transform_activate *activate = impl_from_IMFActivate(iface);
491 CLSID clsid;
492 HRESULT hr;
494 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
496 EnterCriticalSection(&activate->attributes.cs);
498 if (!activate->transform)
500 if (activate->factory)
502 if (FAILED(hr = IClassFactory_CreateInstance(activate->factory, NULL, &IID_IMFTransform,
503 (void **)&activate->transform)))
505 hr = MF_E_INVALIDREQUEST;
508 else
510 if (SUCCEEDED(hr = attributes_GetGUID(&activate->attributes, &MFT_TRANSFORM_CLSID_Attribute, &clsid)))
512 if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
513 (void **)&activate->transform)))
515 hr = MF_E_INVALIDREQUEST;
521 if (activate->transform)
522 hr = IMFTransform_QueryInterface(activate->transform, riid, obj);
524 LeaveCriticalSection(&activate->attributes.cs);
526 return hr;
529 static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface)
531 struct transform_activate *activate = impl_from_IMFActivate(iface);
533 TRACE("%p.\n", iface);
535 EnterCriticalSection(&activate->attributes.cs);
537 if (activate->transform)
539 IMFTransform_Release(activate->transform);
540 activate->transform = NULL;
543 LeaveCriticalSection(&activate->attributes.cs);
545 return S_OK;
548 static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface)
550 TRACE("%p.\n", iface);
552 return E_NOTIMPL;
555 static const IMFActivateVtbl transform_activate_vtbl =
557 transform_activate_QueryInterface,
558 transform_activate_AddRef,
559 transform_activate_Release,
560 transform_activate_GetItem,
561 transform_activate_GetItemType,
562 transform_activate_CompareItem,
563 transform_activate_Compare,
564 transform_activate_GetUINT32,
565 transform_activate_GetUINT64,
566 transform_activate_GetDouble,
567 transform_activate_GetGUID,
568 transform_activate_GetStringLength,
569 transform_activate_GetString,
570 transform_activate_GetAllocatedString,
571 transform_activate_GetBlobSize,
572 transform_activate_GetBlob,
573 transform_activate_GetAllocatedBlob,
574 transform_activate_GetUnknown,
575 transform_activate_SetItem,
576 transform_activate_DeleteItem,
577 transform_activate_DeleteAllItems,
578 transform_activate_SetUINT32,
579 transform_activate_SetUINT64,
580 transform_activate_SetDouble,
581 transform_activate_SetGUID,
582 transform_activate_SetString,
583 transform_activate_SetBlob,
584 transform_activate_SetUnknown,
585 transform_activate_LockStore,
586 transform_activate_UnlockStore,
587 transform_activate_GetCount,
588 transform_activate_GetItemByIndex,
589 transform_activate_CopyAllItems,
590 transform_activate_ActivateObject,
591 transform_activate_ShutdownObject,
592 transform_activate_DetachObject,
595 static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate)
597 struct transform_activate *object;
598 HRESULT hr;
600 object = heap_alloc_zero(sizeof(*object));
601 if (!object)
602 return E_OUTOFMEMORY;
604 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
606 heap_free(object);
607 return hr;
610 object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl;
611 object->factory = factory;
612 if (object->factory)
613 IClassFactory_AddRef(object->factory);
615 *activate = &object->IMFActivate_iface;
617 return S_OK;
620 HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate)
622 TRACE("%p.\n", activate);
624 return create_transform_activate(NULL, activate);
627 static const WCHAR transform_keyW[] = L"MediaFoundation\\Transforms";
628 static const WCHAR categories_keyW[] = L"MediaFoundation\\Transforms\\Categories";
630 static const BYTE guid_conv_table[256] =
632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
635 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
636 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
637 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
638 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
641 static WCHAR* GUIDToString(WCHAR *str, REFGUID guid)
643 swprintf(str, 39, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
644 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
645 guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
646 guid->Data4[6], guid->Data4[7]);
648 return str;
651 static inline BOOL is_valid_hex(WCHAR c)
653 if (!(((c >= '0') && (c <= '9')) ||
654 ((c >= 'a') && (c <= 'f')) ||
655 ((c >= 'A') && (c <= 'F'))))
656 return FALSE;
657 return TRUE;
660 static BOOL GUIDFromString(LPCWSTR s, GUID *id)
662 int i;
664 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
666 id->Data1 = 0;
667 for (i = 0; i < 8; i++)
669 if (!is_valid_hex(s[i])) return FALSE;
670 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
672 if (s[8]!='-') return FALSE;
674 id->Data2 = 0;
675 for (i = 9; i < 13; i++)
677 if (!is_valid_hex(s[i])) return FALSE;
678 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
680 if (s[13]!='-') return FALSE;
682 id->Data3 = 0;
683 for (i = 14; i < 18; i++)
685 if (!is_valid_hex(s[i])) return FALSE;
686 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
688 if (s[18]!='-') return FALSE;
690 for (i = 19; i < 36; i+=2)
692 if (i == 23)
694 if (s[i]!='-') return FALSE;
695 i++;
697 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
698 id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
701 if (!s[36]) return TRUE;
702 return FALSE;
705 static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags,
706 UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
707 const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
709 HRESULT hr = S_OK;
710 HKEY hclsid = 0;
711 WCHAR buffer[64];
712 DWORD size, ret;
713 WCHAR str[250];
714 UINT8 *blob;
716 GUIDToString(buffer, clsid);
717 swprintf(str, ARRAY_SIZE(str), L"%s\\%s", transform_keyW, buffer);
719 if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)))
720 hr = HRESULT_FROM_WIN32(ret);
722 if (SUCCEEDED(hr))
724 size = (lstrlenW(name) + 1) * sizeof(WCHAR);
725 if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)))
726 hr = HRESULT_FROM_WIN32(ret);
729 if (SUCCEEDED(hr) && cinput && input_types)
731 size = cinput * sizeof(MFT_REGISTER_TYPE_INFO);
732 if ((ret = RegSetValueExW(hclsid, L"InputTypes", 0, REG_BINARY, (BYTE *)input_types, size)))
733 hr = HRESULT_FROM_WIN32(ret);
736 if (SUCCEEDED(hr) && coutput && output_types)
738 size = coutput * sizeof(MFT_REGISTER_TYPE_INFO);
739 if ((ret = RegSetValueExW(hclsid, L"OutputTypes", 0, REG_BINARY, (BYTE *)output_types, size)))
740 hr = HRESULT_FROM_WIN32(ret);
743 if (SUCCEEDED(hr) && attributes)
745 if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size)))
747 if ((blob = heap_alloc(size)))
749 if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size)))
751 if ((ret = RegSetValueExW(hclsid, L"Attributes", 0, REG_BINARY, blob, size)))
752 hr = HRESULT_FROM_WIN32(ret);
754 heap_free(blob);
756 else
757 hr = E_OUTOFMEMORY;
761 if (SUCCEEDED(hr) && flags)
763 if ((ret = RegSetValueExW(hclsid, L"MFTFlags", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags))))
764 hr = HRESULT_FROM_WIN32(ret);
767 RegCloseKey(hclsid);
768 return hr;
771 static HRESULT register_category(CLSID *clsid, GUID *category)
773 HKEY htmp1;
774 WCHAR guid1[64], guid2[64];
775 WCHAR str[350];
777 GUIDToString(guid1, category);
778 GUIDToString(guid2, clsid);
780 swprintf(str, ARRAY_SIZE(str), L"%s\\%s\\%s", categories_keyW, guid1, guid2);
782 if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &htmp1))
783 return E_FAIL;
785 RegCloseKey(htmp1);
786 return S_OK;
789 /***********************************************************************
790 * MFTRegister (mfplat.@)
792 HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
793 MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
794 MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
796 HRESULT hr;
798 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category),
799 debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
801 hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes);
802 if(FAILED(hr))
803 ERR("Failed to write register transform\n");
805 if (SUCCEEDED(hr))
806 hr = register_category(&clsid, &category);
808 return hr;
811 static void release_mft_registration(struct mft_registration *mft)
813 if (mft->factory)
814 IClassFactory_Release(mft->factory);
815 heap_free(mft->name);
816 heap_free(mft->input_types);
817 heap_free(mft->output_types);
818 heap_free(mft);
821 static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
822 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
823 const MFT_REGISTER_TYPE_INFO *output_types)
825 struct mft_registration *mft, *cur, *unreg_mft = NULL;
826 HRESULT hr;
828 if (!factory && !clsid)
830 WARN("Can't register without factory or CLSID.\n");
831 return E_FAIL;
834 mft = heap_alloc_zero(sizeof(*mft));
835 if (!mft)
836 return E_OUTOFMEMORY;
838 mft->factory = factory;
839 if (mft->factory)
840 IClassFactory_AddRef(mft->factory);
841 if (clsid)
842 mft->clsid = *clsid;
843 mft->category = *category;
844 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
845 flags |= MFT_ENUM_FLAG_SYNCMFT;
846 mft->flags = flags;
847 mft->local = TRUE;
848 if (FAILED(hr = heap_strdupW(name, &mft->name)))
849 goto failed;
851 if (input_count && input_types)
853 mft->input_types_count = input_count;
854 if (!(mft->input_types = heap_calloc(mft->input_types_count, sizeof(*input_types))))
856 hr = E_OUTOFMEMORY;
857 goto failed;
859 memcpy(mft->input_types, input_types, mft->input_types_count * sizeof(*input_types));
862 if (output_count && output_types)
864 mft->output_types_count = output_count;
865 if (!(mft->output_types = heap_calloc(mft->output_types_count, sizeof(*output_types))))
867 hr = E_OUTOFMEMORY;
868 goto failed;
870 memcpy(mft->output_types, output_types, mft->output_types_count * sizeof(*output_types));
873 EnterCriticalSection(&local_mfts_section);
875 LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct mft_registration, entry)
877 if (cur->factory == factory)
879 unreg_mft = cur;
880 list_remove(&cur->entry);
881 break;
884 list_add_tail(&local_mfts, &mft->entry);
886 LeaveCriticalSection(&local_mfts_section);
888 if (unreg_mft)
889 release_mft_registration(unreg_mft);
891 failed:
892 if (FAILED(hr))
893 release_mft_registration(mft);
895 return hr;
898 HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name, UINT32 flags,
899 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
900 const MFT_REGISTER_TYPE_INFO *output_types)
902 TRACE("%p, %s, %s, %#x, %u, %p, %u, %p.\n", factory, debugstr_guid(category), debugstr_w(name), flags, input_count,
903 input_types, output_count, output_types);
905 return mft_register_local(factory, NULL, category, name, flags, input_count, input_types, output_count, output_types);
908 HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
909 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
910 const MFT_REGISTER_TYPE_INFO *output_types)
912 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
913 input_count, input_types, output_count, output_types);
915 return mft_register_local(NULL, clsid, category, name, flags, input_count, input_types, output_count, output_types);
918 static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
920 struct mft_registration *cur, *cur2;
921 BOOL unregister_all = !factory && !clsid;
922 struct list unreg;
924 list_init(&unreg);
926 EnterCriticalSection(&local_mfts_section);
928 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct mft_registration, entry)
930 if (!unregister_all)
932 if ((factory && cur->factory == factory) || IsEqualCLSID(&cur->clsid, clsid))
934 list_remove(&cur->entry);
935 list_add_tail(&unreg, &cur->entry);
936 break;
939 else
941 list_remove(&cur->entry);
942 list_add_tail(&unreg, &cur->entry);
946 LeaveCriticalSection(&local_mfts_section);
948 if (!unregister_all && list_empty(&unreg))
949 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
951 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct mft_registration, entry)
953 list_remove(&cur->entry);
954 release_mft_registration(cur);
957 return S_OK;
960 HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid)
962 TRACE("%s.\n", debugstr_guid(&clsid));
964 return mft_unregister_local(NULL, &clsid);
967 HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
969 TRACE("%p.\n", factory);
971 return mft_unregister_local(factory, NULL);
974 MFTIME WINAPI MFGetSystemTime(void)
976 MFTIME mf;
978 GetSystemTimeAsFileTime( (FILETIME*)&mf );
980 return mf;
983 static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *category, UINT32 flags,
984 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
985 const MFT_REGISTER_TYPE_INFO *output_type)
987 BOOL matching = TRUE;
988 DWORD model;
989 int i;
991 if (!IsEqualGUID(category, &mft->category))
992 return FALSE;
994 /* Default model is synchronous. */
995 model = mft->flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE);
996 if (!model)
997 model = MFT_ENUM_FLAG_SYNCMFT;
998 if (!(model & flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
999 return FALSE;
1001 /* These flags should be explicitly enabled. */
1002 if (mft->flags & ~flags & (MFT_ENUM_FLAG_FIELDOFUSE | MFT_ENUM_FLAG_TRANSCODE_ONLY))
1003 return FALSE;
1005 if (flags & MFT_ENUM_FLAG_SORTANDFILTER && !mft->factory && plugin_control
1006 && IMFPluginControl_IsDisabled(plugin_control, MF_Plugin_Type_MFT, &mft->clsid) == S_OK)
1008 return FALSE;
1011 if (input_type)
1013 for (i = 0, matching = FALSE; input_type && i < mft->input_types_count; ++i)
1015 if (!memcmp(&mft->input_types[i], input_type, sizeof(*input_type)))
1017 matching = TRUE;
1018 break;
1023 if (output_type && matching)
1025 for (i = 0, matching = FALSE; i < mft->output_types_count; ++i)
1027 if (!memcmp(&mft->output_types[i], output_type, sizeof(*output_type)))
1029 matching = TRUE;
1030 break;
1035 return matching;
1038 static void mft_get_reg_type_info(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type,
1039 UINT32 *count)
1041 HKEY htransform, hfilter;
1042 DWORD reg_type, size;
1044 *type = NULL;
1045 *count = 0;
1047 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1048 return;
1050 if (RegOpenKeyW(htransform, clsidW, &hfilter))
1052 RegCloseKey(htransform);
1053 return;
1056 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, NULL, &size))
1057 goto out;
1059 if (reg_type != REG_BINARY)
1060 goto out;
1062 if (!size || size % sizeof(**type))
1063 goto out;
1065 if (!(*type = heap_alloc(size)))
1066 goto out;
1068 *count = size / sizeof(**type);
1070 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, (BYTE *)*type, &size))
1072 heap_free(*type);
1073 *type = NULL;
1074 *count = 0;
1077 out:
1078 RegCloseKey(hfilter);
1079 RegCloseKey(htransform);
1082 static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags)
1084 DWORD ret, reg_type, size;
1085 HKEY hroot, hmft;
1087 *flags = 0;
1089 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot))
1090 return;
1092 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1093 RegCloseKey(hroot);
1094 if (ret)
1095 return;
1097 reg_type = 0;
1098 if (!RegQueryValueExW(hmft, nameW, NULL, &reg_type, NULL, &size) && reg_type == REG_DWORD)
1099 RegQueryValueExW(hmft, nameW, NULL, &reg_type, (BYTE *)flags, &size);
1101 RegCloseKey(hmft);
1104 static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, UINT32 flags,
1105 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1106 const MFT_REGISTER_TYPE_INFO *output_type)
1108 struct mft_registration mft, *cur;
1109 HKEY hcategory, hlist;
1110 WCHAR clsidW[64];
1111 DWORD ret, size;
1112 int index = 0;
1114 if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1115 return E_FAIL;
1117 GUIDToString(clsidW, category);
1118 ret = RegOpenKeyW(hcategory, clsidW, &hlist);
1119 RegCloseKey(hcategory);
1120 if (ret)
1121 return E_FAIL;
1123 size = ARRAY_SIZE(clsidW);
1124 while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL))
1126 memset(&mft, 0, sizeof(mft));
1127 mft.category = *category;
1128 if (!GUIDFromString(clsidW, &mft.clsid))
1129 goto next;
1131 mft_get_reg_flags(clsidW, L"MFTFlags", &mft.flags);
1133 if (output_type)
1134 mft_get_reg_type_info(clsidW, L"OutputTypes", &mft.output_types, &mft.output_types_count);
1136 if (input_type)
1137 mft_get_reg_type_info(clsidW, L"InputTypes", &mft.input_types, &mft.input_types_count);
1139 if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type))
1141 heap_free(mft.input_types);
1142 heap_free(mft.output_types);
1143 goto next;
1146 cur = heap_alloc(sizeof(*cur));
1147 /* Reuse allocated type arrays. */
1148 *cur = mft;
1149 list_add_tail(mfts, &cur->entry);
1151 next:
1152 size = ARRAY_SIZE(clsidW);
1153 index++;
1156 return S_OK;
1159 static BOOL mft_is_preferred(IMFPluginControl *plugin_control, const CLSID *clsid)
1161 CLSID preferred;
1162 WCHAR *selector;
1163 int index = 0;
1165 while (SUCCEEDED(IMFPluginControl_GetPreferredClsidByIndex(plugin_control, MF_Plugin_Type_MFT, index++, &selector,
1166 &preferred)))
1168 CoTaskMemFree(selector);
1170 if (IsEqualGUID(&preferred, clsid))
1171 return TRUE;
1174 return FALSE;
1177 static HRESULT mft_enum(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1178 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1180 IMFPluginControl *plugin_control = NULL;
1181 struct list mfts, mfts_sorted, *result = &mfts;
1182 struct mft_registration *mft, *mft2;
1183 unsigned int obj_count;
1184 HRESULT hr;
1186 *count = 0;
1187 *activate = NULL;
1189 if (!flags)
1190 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER;
1192 /* Synchronous processing is default. */
1193 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1194 flags |= MFT_ENUM_FLAG_SYNCMFT;
1196 if (FAILED(hr = MFGetPluginControl(&plugin_control)))
1198 WARN("Failed to get plugin control instance, hr %#x.\n", hr);
1199 return hr;
1202 list_init(&mfts);
1204 /* Collect from registry */
1205 mft_collect_machine_reg(&mfts, &category, flags, plugin_control, input_type, output_type);
1207 /* Collect locally registered ones. */
1208 if (flags & MFT_ENUM_FLAG_LOCALMFT)
1210 struct mft_registration *local;
1212 EnterCriticalSection(&local_mfts_section);
1214 LIST_FOR_EACH_ENTRY(local, &local_mfts, struct mft_registration, entry)
1216 if (mft_is_type_info_match(local, &category, flags, plugin_control, input_type, output_type))
1218 mft = heap_alloc_zero(sizeof(*mft));
1220 mft->clsid = local->clsid;
1221 mft->factory = local->factory;
1222 if (mft->factory)
1223 IClassFactory_AddRef(mft->factory);
1224 mft->flags = local->flags;
1225 mft->local = local->local;
1227 list_add_tail(&mfts, &mft->entry);
1231 LeaveCriticalSection(&local_mfts_section);
1234 list_init(&mfts_sorted);
1236 if (flags & MFT_ENUM_FLAG_SORTANDFILTER)
1238 /* Local registrations. */
1239 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1241 if (mft->local)
1243 list_remove(&mft->entry);
1244 list_add_tail(&mfts_sorted, &mft->entry);
1248 /* FIXME: Sort by merit value, for the ones that got it. Currently not handled. */
1250 /* Preferred transforms. */
1251 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1253 if (!mft->factory && mft_is_preferred(plugin_control, &mft->clsid))
1255 list_remove(&mft->entry);
1256 list_add_tail(&mfts_sorted, &mft->entry);
1260 /* Append the rest. */
1261 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1263 list_remove(&mft->entry);
1264 list_add_tail(&mfts_sorted, &mft->entry);
1267 result = &mfts_sorted;
1270 IMFPluginControl_Release(plugin_control);
1272 /* Create activation objects from CLSID/IClassFactory. */
1274 obj_count = list_count(result);
1276 if (obj_count)
1278 if (!(*activate = CoTaskMemAlloc(obj_count * sizeof(**activate))))
1279 hr = E_OUTOFMEMORY;
1281 obj_count = 0;
1283 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, result, struct mft_registration, entry)
1285 IMFActivate *mft_activate;
1287 if (*activate)
1289 if (SUCCEEDED(create_transform_activate(mft->factory, &mft_activate)))
1291 (*activate)[obj_count] = mft_activate;
1293 if (mft->local)
1295 IMFActivate_SetUINT32(mft_activate, &MFT_PROCESS_LOCAL_Attribute, 1);
1297 else
1299 if (mft->name)
1300 IMFActivate_SetString(mft_activate, &MFT_FRIENDLY_NAME_Attribute, mft->name);
1301 if (mft->input_types)
1302 IMFActivate_SetBlob(mft_activate, &MFT_INPUT_TYPES_Attributes, (const UINT8 *)mft->input_types,
1303 sizeof(*mft->input_types) * mft->input_types_count);
1304 if (mft->output_types)
1305 IMFActivate_SetBlob(mft_activate, &MFT_OUTPUT_TYPES_Attributes, (const UINT8 *)mft->output_types,
1306 sizeof(*mft->output_types) * mft->output_types_count);
1309 if (!mft->factory)
1310 IMFActivate_SetGUID(mft_activate, &MFT_TRANSFORM_CLSID_Attribute, &mft->clsid);
1312 IMFActivate_SetUINT32(mft_activate, &MF_TRANSFORM_FLAGS_Attribute, mft->flags);
1313 IMFActivate_SetGUID(mft_activate, &MF_TRANSFORM_CATEGORY_Attribute, &mft->category);
1315 obj_count++;
1319 list_remove(&mft->entry);
1320 release_mft_registration(mft);
1324 if (!obj_count)
1326 CoTaskMemFree(*activate);
1327 *activate = NULL;
1329 *count = obj_count;
1331 return hr;
1334 /***********************************************************************
1335 * MFTEnum (mfplat.@)
1337 HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
1338 MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count)
1340 struct mft_registration *mft, *mft2;
1341 unsigned int mft_count;
1342 struct list mfts;
1343 HRESULT hr;
1345 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1346 clsids, count);
1348 if (!clsids || !count)
1349 return E_INVALIDARG;
1351 *count = 0;
1353 list_init(&mfts);
1355 if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
1356 return hr;
1358 mft_count = list_count(&mfts);
1360 if (mft_count)
1362 if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
1363 hr = E_OUTOFMEMORY;
1365 mft_count = 0;
1366 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1368 if (*clsids)
1369 (*clsids)[mft_count++] = mft->clsid;
1370 list_remove(&mft->entry);
1371 release_mft_registration(mft);
1375 if (!mft_count)
1377 CoTaskMemFree(*clsids);
1378 *clsids = NULL;
1380 *count = mft_count;
1382 return hr;
1385 /***********************************************************************
1386 * MFTEnumEx (mfplat.@)
1388 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1389 const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count)
1391 TRACE("%s, %#x, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, activate, count);
1393 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1396 /***********************************************************************
1397 * MFTEnum2 (mfplat.@)
1399 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1400 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1402 TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
1403 activate, count);
1405 if (attributes)
1406 FIXME("Ignoring attributes.\n");
1408 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1411 /***********************************************************************
1412 * MFTUnregister (mfplat.@)
1414 HRESULT WINAPI MFTUnregister(CLSID clsid)
1416 WCHAR buffer[64], category[MAX_PATH];
1417 HKEY htransform, hcategory, htmp;
1418 DWORD size = MAX_PATH;
1419 DWORD index = 0;
1421 TRACE("(%s)\n", debugstr_guid(&clsid));
1423 GUIDToString(buffer, &clsid);
1425 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1427 RegDeleteKeyW(htransform, buffer);
1428 RegCloseKey(htransform);
1431 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1433 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1435 if (!RegOpenKeyW(hcategory, category, &htmp))
1437 RegDeleteKeyW(htmp, buffer);
1438 RegCloseKey(htmp);
1440 size = MAX_PATH;
1441 index++;
1443 RegCloseKey(hcategory);
1446 return S_OK;
1449 /***********************************************************************
1450 * MFStartup (mfplat.@)
1452 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1454 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1455 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1457 TRACE("%#x, %#x.\n", version, flags);
1459 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1460 return MF_E_BAD_STARTUP_VERSION;
1462 RtwqStartup();
1464 return S_OK;
1467 /***********************************************************************
1468 * MFShutdown (mfplat.@)
1470 HRESULT WINAPI MFShutdown(void)
1472 TRACE("\n");
1474 RtwqShutdown();
1476 return S_OK;
1479 /***********************************************************************
1480 * MFCopyImage (mfplat.@)
1482 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1484 TRACE("%p, %d, %p, %d, %u, %u.\n", dest, deststride, src, srcstride, width, lines);
1486 while (lines--)
1488 memcpy(dest, src, width);
1489 dest += deststride;
1490 src += srcstride;
1493 return S_OK;
1496 struct guid_def
1498 const GUID *guid;
1499 const char *name;
1502 static int __cdecl debug_compare_guid(const void *a, const void *b)
1504 const GUID *guid = a;
1505 const struct guid_def *guid_def = b;
1506 return memcmp(guid, guid_def->guid, sizeof(*guid));
1509 const char *debugstr_attr(const GUID *guid)
1511 static const struct guid_def guid_defs[] =
1513 #define X(g) { &(g), #g }
1514 #define MF_READER_WRITER_D3D_MANAGER MF_SOURCE_READER_D3D_MANAGER
1515 X(MF_READWRITE_MMCSS_CLASS),
1516 X(MF_TOPONODE_MARKIN_HERE),
1517 X(MF_MT_H264_SUPPORTED_SYNC_FRAME_TYPES),
1518 X(MF_TOPONODE_MARKOUT_HERE),
1519 X(EVRConfig_ForceBob),
1520 X(MF_TOPONODE_DECODER),
1521 X(EVRConfig_AllowDropToBob),
1522 X(MF_TOPOLOGY_PROJECTSTART),
1523 X(EVRConfig_ForceThrottle),
1524 X(MF_VIDEO_MAX_MB_PER_SEC),
1525 X(MF_TOPOLOGY_PROJECTSTOP),
1526 X(MF_SINK_WRITER_ENCODER_CONFIG),
1527 X(EVRConfig_AllowDropToThrottle),
1528 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1529 X(EVRConfig_ForceHalfInterlace),
1530 X(EVRConfig_AllowDropToHalfInterlace),
1531 X(EVRConfig_ForceScaling),
1532 X(MF_MT_H264_CAPABILITIES),
1533 X(EVRConfig_AllowScaling),
1534 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1535 X(MFT_PREFERRED_ENCODER_PROFILE),
1536 X(EVRConfig_ForceBatching),
1537 X(EVRConfig_AllowBatching),
1538 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1539 X(MF_MT_VIDEO_PROFILE),
1540 X(MF_MT_MPEG2_PROFILE),
1541 X(MF_MT_DV_AAUX_CTRL_PACK_1),
1542 X(MF_MT_ALPHA_MODE),
1543 X(MF_MT_MPEG2_TIMECODE),
1544 X(MF_PMP_SERVER_CONTEXT),
1545 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1546 X(MF_MEDIA_ENGINE_TRACK_ID),
1547 X(MF_MT_CUSTOM_VIDEO_PRIMARIES),
1548 X(MF_MT_TIMESTAMP_CAN_BE_DTS),
1549 X(MFT_CODEC_MERIT_Attribute),
1550 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1551 X(MF_LOW_LATENCY),
1552 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1553 X(MF_MT_MPEG2_FLAGS),
1554 X(MF_MEDIA_ENGINE_AUDIO_CATEGORY),
1555 X(MF_MT_PIXEL_ASPECT_RATIO),
1556 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1557 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1558 X(MF_MT_REALTIME_CONTENT),
1559 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS),
1560 X(MF_MT_WRAPPED_TYPE),
1561 X(MF_MT_DRM_FLAGS),
1562 X(MF_MT_AVG_BITRATE),
1563 X(MF_MT_DECODER_USE_MAX_RESOLUTION),
1564 X(MF_MT_MAX_LUMINANCE_LEVEL),
1565 X(MFT_CONNECTED_TO_HW_STREAM),
1566 X(MF_SA_D3D_AWARE),
1567 X(MF_MT_MAX_KEYFRAME_SPACING),
1568 X(MFT_TRANSFORM_CLSID_Attribute),
1569 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1570 X(MF_MT_AM_FORMAT_TYPE),
1571 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1572 X(MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE),
1573 X(MF_MT_H264_MAX_MB_PER_SEC),
1574 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1575 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1576 X(MF_PD_PMPHOST_CONTEXT),
1577 X(MF_PD_APP_CONTEXT),
1578 X(MF_PD_DURATION),
1579 X(MF_PD_TOTAL_FILE_SIZE),
1580 X(MF_PD_AUDIO_ENCODING_BITRATE),
1581 X(MF_PD_VIDEO_ENCODING_BITRATE),
1582 X(MFSampleExtension_TargetGlobalLuminance),
1583 X(MF_PD_MIME_TYPE),
1584 X(MF_MT_H264_SUPPORTED_SLICE_MODES),
1585 X(MF_PD_LAST_MODIFIED_TIME),
1586 X(MF_PD_PLAYBACK_ELEMENT_ID),
1587 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9),
1588 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1589 X(MF_PD_PREFERRED_LANGUAGE),
1590 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1591 X(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID),
1592 X(MF_ACTIVATE_MFT_LOCKED),
1593 X(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT),
1594 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1595 X(MF_MT_FRAME_SIZE),
1596 X(MF_MT_H264_SIMULCAST_SUPPORT),
1597 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1598 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1599 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1600 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1601 X(MF_MT_FRAME_RATE_RANGE_MAX),
1602 X(MF_MT_PALETTE),
1603 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1604 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1605 X(MF_SA_D3D11_USAGE),
1606 X(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK),
1607 X(MF_MT_GEOMETRIC_APERTURE),
1608 X(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
1609 X(MF_MT_DV_AAUX_SRC_PACK_1),
1610 X(MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL),
1611 X(MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE),
1612 X(MF_MEDIA_ENGINE_EXTENSION),
1613 X(MF_MT_DEFAULT_STRIDE),
1614 X(MF_MT_ARBITRARY_FORMAT),
1615 X(MF_TRANSFORM_CATEGORY_Attribute),
1616 X(MF_MT_MPEG2_HDCP),
1617 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1618 X(MF_MT_SPATIAL_AUDIO_MAX_DYNAMIC_OBJECTS),
1619 X(MF_MT_DECODER_MAX_DPB_COUNT),
1620 X(MFSampleExtension_ForwardedDecodeUnits),
1621 X(MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
1622 X(MF_MT_DV_AAUX_CTRL_PACK_0),
1623 X(MF_MT_YUV_MATRIX),
1624 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1625 X(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
1626 X(MF_MT_MAX_FRAME_AVERAGE_LUMINANCE_LEVEL),
1627 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1628 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1629 X(MF_MT_VIDEO_ROTATION),
1630 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1631 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11),
1632 X(MF_MT_USER_DATA),
1633 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID),
1634 X(MF_MT_MIN_MASTERING_LUMINANCE),
1635 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE),
1636 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS),
1637 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID),
1638 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1639 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE),
1640 X(MF_MT_AUDIO_CHANNEL_MASK),
1641 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1642 X(MF_READWRITE_DISABLE_CONVERTERS),
1643 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE),
1644 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS),
1645 X(MF_MT_MINIMUM_DISPLAY_APERTURE),
1646 X(MFSampleExtension_Token),
1647 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1648 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1649 X(MF_TRANSFORM_ASYNC_UNLOCK),
1650 X(MF_DISABLE_FRAME_CORRUPTION_INFO),
1651 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1652 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1653 X(MF_MEDIA_ENGINE_PLAYBACK_VISUAL),
1654 X(MF_MT_VIDEO_CHROMA_SITING),
1655 X(MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY),
1656 X(MF_SA_BUFFERS_PER_SAMPLE),
1657 X(MFSampleExtension_3DVideo_SampleFormat),
1658 X(MF_MT_H264_RESOLUTION_SCALING),
1659 X(MF_MT_VIDEO_LEVEL),
1660 X(MF_MT_MPEG2_LEVEL),
1661 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1662 X(MF_MT_SAMPLE_SIZE),
1663 X(MF_MT_AAC_PAYLOAD_TYPE),
1664 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1665 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1666 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1667 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1668 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1669 X(MF_TRANSFORM_FLAGS_Attribute),
1670 X(MF_MT_H264_SUPPORTED_RATE_CONTROL_MODES),
1671 X(MF_PD_SAMI_STYLELIST),
1672 X(MF_MT_AUDIO_WMADRC_AVGREF),
1673 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1674 X(MF_SD_LANGUAGE),
1675 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1676 X(MF_SD_PROTECTED),
1677 X(MF_SESSION_TOPOLOADER),
1678 X(MF_SESSION_GLOBAL_TIME),
1679 X(MF_SESSION_QUALITY_MANAGER),
1680 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1681 X(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
1682 X(MF_MT_MPEG_START_TIME_CODE),
1683 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1684 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1685 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1686 X(MF_MT_H264_MAX_CODEC_CONFIG_DELAY),
1687 X(MF_MT_DV_AAUX_SRC_PACK_0),
1688 X(MF_BYTESTREAM_ORIGIN_NAME),
1689 X(MF_BYTESTREAM_CONTENT_TYPE),
1690 X(MF_MT_DEPTH_MEASUREMENT),
1691 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10),
1692 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1693 X(MF_BYTESTREAM_DURATION),
1694 X(MF_SD_SAMI_LANGUAGE),
1695 X(MF_EVENT_OUTPUT_NODE),
1696 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1697 X(MFT_ENUM_ADAPTER_LUID),
1698 X(MF_MT_FRAME_RATE_RANGE_MIN),
1699 X(MF_BYTESTREAM_IFO_FILE_URI),
1700 X(MF_EVENT_TOPOLOGY_STATUS),
1701 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1702 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1703 X(MF_MT_MAJOR_TYPE),
1704 X(MF_MT_IN_BAND_PARAMETER_SET),
1705 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1706 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1707 X(MF_SESSION_SERVER_CONTEXT),
1708 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1709 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1710 X(MF_PD_ADAPTIVE_STREAMING),
1711 X(MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE),
1712 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE),
1713 X(MF_MT_H264_SUPPORTED_USAGES),
1714 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1715 X(MFSampleExtension_Timestamp),
1716 X(MF_TOPONODE_PRIMARYOUTPUT),
1717 X(MF_MT_SUBTYPE),
1718 X(MF_TRANSFORM_ASYNC),
1719 X(MF_TOPONODE_STREAMID),
1720 X(MF_MEDIA_ENGINE_PLAYBACK_HWND),
1721 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1722 X(MF_MT_VIDEO_LIGHTING),
1723 X(MF_SD_MUTUALLY_EXCLUSIVE),
1724 X(MF_SD_STREAM_NAME),
1725 X(MF_MT_DV_VAUX_SRC_PACK),
1726 X(MF_TOPONODE_RATELESS),
1727 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1728 X(MF_TOPONODE_DISABLE_PREROLL),
1729 X(MF_SA_D3D11_ALLOW_DYNAMIC_YUV_TEXTURE),
1730 X(MF_MT_VIDEO_3D_FORMAT),
1731 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1732 X(MF_READER_WRITER_D3D_MANAGER),
1733 X(MFSampleExtension_3DVideo),
1734 X(MF_MT_H264_USAGE),
1735 X(MF_MEDIA_ENGINE_EME_CALLBACK),
1736 X(MF_EVENT_SOURCE_FAKE_START),
1737 X(MF_EVENT_SOURCE_PROJECTSTART),
1738 X(MF_EVENT_SOURCE_ACTUAL_START),
1739 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER),
1740 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1741 X(MFT_ENUM_HARDWARE_URL_Attribute),
1742 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1743 X(MF_MT_OUTPUT_BUFFER_NUM),
1744 X(MF_SA_D3D11_BINDFLAGS),
1745 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1746 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1747 X(MFT_FRIENDLY_NAME_Attribute),
1748 X(MF_MT_FIXED_SIZE_SAMPLES),
1749 X(MFT_SUPPORT_3DVIDEO),
1750 X(MFT_SUPPORT_3DVIDEO),
1751 X(MFT_INPUT_TYPES_Attributes),
1752 X(MF_MT_H264_LAYOUT_PER_STREAM),
1753 X(MF_EVENT_SCRUBSAMPLE_TIME),
1754 X(MF_MT_SPATIAL_AUDIO_MAX_METADATA_ITEMS),
1755 X(MF_MT_MPEG2_ONE_FRAME_PER_PACKET),
1756 X(MF_MT_INTERLACE_MODE),
1757 X(MF_MEDIA_ENGINE_CALLBACK),
1758 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1759 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1760 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1761 X(MF_MT_H264_SVC_CAPABILITIES),
1762 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1763 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_LENGTH),
1764 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_FORMAT_ID),
1765 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1766 X(MF_SA_D3D11_SHARED),
1767 X(MF_MT_PAN_SCAN_ENABLED),
1768 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID),
1769 X(MF_MT_DV_VAUX_CTRL_PACK),
1770 X(MFSampleExtension_ForwardedDecodeUnitType),
1771 X(MF_SA_D3D11_AWARE),
1772 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1773 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1774 X(MF_MT_SPATIAL_AUDIO_MIN_METADATA_ITEM_OFFSET_SPACING),
1775 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1776 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1777 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1778 X(MF_MT_SOURCE_CONTENT_HINT),
1779 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1780 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1781 X(MF_READWRITE_MMCSS_PRIORITY),
1782 X(MF_MT_VIDEO_3D),
1783 X(MF_EVENT_START_PRESENTATION_TIME),
1784 X(MF_EVENT_SESSIONCAPS),
1785 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1786 X(MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE),
1787 X(MF_EVENT_SESSIONCAPS_DELTA),
1788 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1789 X(MFSampleExtension_DecodeTimestamp),
1790 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE),
1791 X(MF_MT_VIDEO_H264_NO_FMOASO),
1792 X(MF_MT_AVG_BIT_ERROR_RATE),
1793 X(MF_MT_VIDEO_PRIMARIES),
1794 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1795 X(MF_MT_H264_RATE_CONTROL_MODES),
1796 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1797 X(MF_READWRITE_D3D_OPTIONAL),
1798 X(MF_SA_D3D11_HW_PROTECTED),
1799 X(MF_MEDIA_ENGINE_DXGI_MANAGER),
1800 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1801 X(MF_MEDIA_ENGINE_COREWINDOW),
1802 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1803 X(MF_MT_MPEG4_TRACK_TYPE),
1804 X(MF_ACTIVATE_VIDEO_WINDOW),
1805 X(MF_MT_PAN_SCAN_APERTURE),
1806 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1807 X(MF_MT_ORIGINAL_4CC),
1808 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1809 X(MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS),
1810 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE),
1811 X(MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID),
1812 X(MF_MT_MPEG2_CONTENT_PACKET),
1813 X(MFT_PROCESS_LOCAL_Attribute),
1814 X(MFT_PROCESS_LOCAL_Attribute),
1815 X(MF_MT_PAD_CONTROL_FLAGS),
1816 X(MF_MT_VIDEO_NOMINAL_RANGE),
1817 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1818 X(MF_MT_MPEG_SEQUENCE_HEADER),
1819 X(MF_MEDIA_ENGINE_OPM_HWND),
1820 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1821 X(MF_MT_SPATIAL_AUDIO_DATA_PRESENT),
1822 X(MF_MT_FRAME_RATE),
1823 X(MF_TOPONODE_FLUSH),
1824 X(MF_MT_MPEG2_STANDARD),
1825 X(MF_TOPONODE_DRAIN),
1826 X(MF_MT_TRANSFER_FUNCTION),
1827 X(MF_TOPONODE_MEDIASTART),
1828 X(MF_TOPONODE_MEDIASTOP),
1829 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
1830 X(MF_TOPONODE_SOURCE),
1831 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
1832 X(MF_TOPONODE_D3DAWARE),
1833 X(MF_MT_COMPRESSED),
1834 X(MF_TOPONODE_STREAM_DESCRIPTOR),
1835 X(MF_TOPONODE_ERRORCODE),
1836 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
1837 X(MF_EVENT_MFT_CONTEXT),
1838 X(MF_MT_FORWARD_CUSTOM_SEI),
1839 X(MF_TOPONODE_CONNECT_METHOD),
1840 X(MFT_OUTPUT_TYPES_Attributes),
1841 X(MF_MT_IMAGE_LOSS_TOLERANT),
1842 X(MF_SESSION_REMOTE_SOURCE_MODE),
1843 X(MF_MT_DEPTH_VALUE_UNIT),
1844 X(MF_MT_AUDIO_NUM_CHANNELS),
1845 X(MF_MT_ARBITRARY_HEADER),
1846 X(MF_TOPOLOGY_DXVA_MODE),
1847 X(MF_TOPONODE_LOCKED),
1848 X(MF_TOPONODE_WORKQUEUE_ID),
1849 X(MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR),
1850 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
1851 X(MF_TOPONODE_DECRYPTOR),
1852 X(MF_EVENT_DO_THINNING),
1853 X(MF_TOPONODE_DISCARDABLE),
1854 X(MF_TOPOLOGY_HARDWARE_MODE),
1855 X(MF_SOURCE_READER_DISABLE_DXVA),
1856 X(MF_MT_FORWARD_CUSTOM_NALU),
1857 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10),
1858 X(MF_TOPONODE_ERROR_MAJORTYPE),
1859 X(MF_MT_SECURE),
1860 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
1861 X(MF_TOPONODE_ERROR_SUBTYPE),
1862 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
1863 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE),
1864 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
1865 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
1866 #undef MF_READER_WRITER_D3D_MANAGER
1867 #undef X
1869 struct guid_def *ret = NULL;
1871 if (guid)
1872 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
1874 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
1877 const char *debugstr_mf_guid(const GUID *guid)
1879 static const struct guid_def guid_defs[] =
1881 #define X(g) { &(g), #g }
1882 X(MFAudioFormat_ADTS),
1883 X(MFAudioFormat_PCM),
1884 X(MFAudioFormat_PCM_HDCP),
1885 X(MFAudioFormat_Float),
1886 X(MFAudioFormat_DTS),
1887 X(MFAudioFormat_DRM),
1888 X(MFAudioFormat_MSP1),
1889 X(MFAudioFormat_Vorbis),
1890 X(MFAudioFormat_AAC),
1891 X(MFVideoFormat_RGB24),
1892 X(MFVideoFormat_ARGB32),
1893 X(MFVideoFormat_RGB32),
1894 X(MFVideoFormat_RGB565),
1895 X(MFVideoFormat_RGB555),
1896 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
1897 X(MFVideoFormat_A2R10G10B10),
1898 X(MFMediaType_Script),
1899 X(MFMediaType_Image),
1900 X(MFMediaType_HTML),
1901 X(MFMediaType_Binary),
1902 X(MFVideoFormat_MPEG2),
1903 X(MFMediaType_FileTransfer),
1904 X(MFVideoFormat_RGB8),
1905 X(MFAudioFormat_Dolby_AC3),
1906 X(MFVideoFormat_L8),
1907 X(MFAudioFormat_LPCM),
1908 X(MFVideoFormat_420O),
1909 X(MFVideoFormat_AI44),
1910 X(MFVideoFormat_AV1),
1911 X(MFVideoFormat_AYUV),
1912 X(MFVideoFormat_H263),
1913 X(MFVideoFormat_H264),
1914 X(MFVideoFormat_H265),
1915 X(MFVideoFormat_HEVC),
1916 X(MFVideoFormat_HEVC_ES),
1917 X(MFVideoFormat_I420),
1918 X(MFVideoFormat_IYUV),
1919 X(MFVideoFormat_M4S2),
1920 X(MFVideoFormat_MJPG),
1921 X(MFVideoFormat_MP43),
1922 X(MFVideoFormat_MP4S),
1923 X(MFVideoFormat_MP4V),
1924 X(MFVideoFormat_MPG1),
1925 X(MFVideoFormat_MSS1),
1926 X(MFVideoFormat_MSS2),
1927 X(MFVideoFormat_NV11),
1928 X(MFVideoFormat_NV12),
1929 X(MFVideoFormat_ORAW),
1930 X(MFAudioFormat_Opus),
1931 X(MFVideoFormat_D16),
1932 X(MFAudioFormat_MPEG),
1933 X(MFVideoFormat_P010),
1934 X(MFVideoFormat_P016),
1935 X(MFVideoFormat_P210),
1936 X(MFVideoFormat_P216),
1937 X(MFVideoFormat_L16),
1938 X(MFAudioFormat_MP3),
1939 X(MFVideoFormat_UYVY),
1940 X(MFVideoFormat_VP10),
1941 X(MFVideoFormat_VP80),
1942 X(MFVideoFormat_VP90),
1943 X(MFVideoFormat_WMV1),
1944 X(MFVideoFormat_WMV2),
1945 X(MFVideoFormat_WMV3),
1946 X(MFVideoFormat_WVC1),
1947 X(MFVideoFormat_Y210),
1948 X(MFVideoFormat_Y216),
1949 X(MFVideoFormat_Y410),
1950 X(MFVideoFormat_Y416),
1951 X(MFVideoFormat_Y41P),
1952 X(MFVideoFormat_Y41T),
1953 X(MFVideoFormat_Y42T),
1954 X(MFVideoFormat_YUY2),
1955 X(MFVideoFormat_YV12),
1956 X(MFVideoFormat_YVU9),
1957 X(MFVideoFormat_YVYU),
1958 X(MFAudioFormat_WMAudioV8),
1959 X(MFAudioFormat_ALAC),
1960 X(MFAudioFormat_AMR_NB),
1961 X(MFMediaType_Audio),
1962 X(MFAudioFormat_WMAudioV9),
1963 X(MFAudioFormat_AMR_WB),
1964 X(MFAudioFormat_WMAudio_Lossless),
1965 X(MFAudioFormat_AMR_WP),
1966 X(MFAudioFormat_WMASPDIF),
1967 X(MFVideoFormat_DV25),
1968 X(MFVideoFormat_DV50),
1969 X(MFVideoFormat_DVC),
1970 X(MFVideoFormat_DVH1),
1971 X(MFVideoFormat_DVHD),
1972 X(MFVideoFormat_DVSD),
1973 X(MFVideoFormat_DVSL),
1974 X(MFVideoFormat_A16B16G16R16F),
1975 X(MFVideoFormat_v210),
1976 X(MFVideoFormat_v216),
1977 X(MFVideoFormat_v410),
1978 X(MFMediaType_Video),
1979 X(MFAudioFormat_AAC_HDCP),
1980 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
1981 X(MFAudioFormat_Dolby_AC3_HDCP),
1982 X(MFMediaType_Subtitle),
1983 X(MFMediaType_Stream),
1984 X(MFAudioFormat_Dolby_AC3_SPDIF),
1985 X(MFAudioFormat_Float_SpatialObjects),
1986 X(MFMediaType_SAMI),
1987 X(MFAudioFormat_ADTS_HDCP),
1988 X(MFAudioFormat_FLAC),
1989 X(MFAudioFormat_Dolby_DDPlus),
1990 X(MFMediaType_MultiplexedFrames),
1991 X(MFAudioFormat_Base_HDCP),
1992 X(MFVideoFormat_Base_HDCP),
1993 X(MFVideoFormat_H264_HDCP),
1994 X(MFVideoFormat_HEVC_HDCP),
1995 X(MFMediaType_Default),
1996 X(MFMediaType_Protected),
1997 X(MFVideoFormat_H264_ES),
1998 X(MFMediaType_Perception),
1999 #undef X
2001 struct guid_def *ret = NULL;
2003 if (guid)
2004 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2006 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2009 struct event_id
2011 DWORD id;
2012 const char *name;
2015 static int __cdecl debug_event_id(const void *a, const void *b)
2017 const DWORD *id = a;
2018 const struct event_id *event_id = b;
2019 return *id - event_id->id;
2022 static const char *debugstr_eventid(DWORD event)
2024 static const struct event_id
2026 DWORD id;
2027 const char *name;
2029 event_ids[] =
2031 #define X(e) { e, #e }
2032 X(MEUnknown),
2033 X(MEError),
2034 X(MEExtendedType),
2035 X(MENonFatalError),
2036 X(MESessionUnknown),
2037 X(MESessionTopologySet),
2038 X(MESessionTopologiesCleared),
2039 X(MESessionStarted),
2040 X(MESessionPaused),
2041 X(MESessionStopped),
2042 X(MESessionClosed),
2043 X(MESessionEnded),
2044 X(MESessionRateChanged),
2045 X(MESessionScrubSampleComplete),
2046 X(MESessionCapabilitiesChanged),
2047 X(MESessionTopologyStatus),
2048 X(MESessionNotifyPresentationTime),
2049 X(MENewPresentation),
2050 X(MELicenseAcquisitionStart),
2051 X(MELicenseAcquisitionCompleted),
2052 X(MEIndividualizationStart),
2053 X(MEIndividualizationCompleted),
2054 X(MEEnablerProgress),
2055 X(MEEnablerCompleted),
2056 X(MEPolicyError),
2057 X(MEPolicyReport),
2058 X(MEBufferingStarted),
2059 X(MEBufferingStopped),
2060 X(MEConnectStart),
2061 X(MEConnectEnd),
2062 X(MEReconnectStart),
2063 X(MEReconnectEnd),
2064 X(MERendererEvent),
2065 X(MESessionStreamSinkFormatChanged),
2066 X(MESourceUnknown),
2067 X(MESourceStarted),
2068 X(MEStreamStarted),
2069 X(MESourceSeeked),
2070 X(MEStreamSeeked),
2071 X(MENewStream),
2072 X(MEUpdatedStream),
2073 X(MESourceStopped),
2074 X(MEStreamStopped),
2075 X(MESourcePaused),
2076 X(MEStreamPaused),
2077 X(MEEndOfPresentation),
2078 X(MEEndOfStream),
2079 X(MEMediaSample),
2080 X(MEStreamTick),
2081 X(MEStreamThinMode),
2082 X(MEStreamFormatChanged),
2083 X(MESourceRateChanged),
2084 X(MEEndOfPresentationSegment),
2085 X(MESourceCharacteristicsChanged),
2086 X(MESourceRateChangeRequested),
2087 X(MESourceMetadataChanged),
2088 X(MESequencerSourceTopologyUpdated),
2089 X(MESinkUnknown),
2090 X(MEStreamSinkStarted),
2091 X(MEStreamSinkStopped),
2092 X(MEStreamSinkPaused),
2093 X(MEStreamSinkRateChanged),
2094 X(MEStreamSinkRequestSample),
2095 X(MEStreamSinkMarker),
2096 X(MEStreamSinkPrerolled),
2097 X(MEStreamSinkScrubSampleComplete),
2098 X(MEStreamSinkFormatChanged),
2099 X(MEStreamSinkDeviceChanged),
2100 X(MEQualityNotify),
2101 X(MESinkInvalidated),
2102 X(MEAudioSessionNameChanged),
2103 X(MEAudioSessionVolumeChanged),
2104 X(MEAudioSessionDeviceRemoved),
2105 X(MEAudioSessionServerShutdown),
2106 X(MEAudioSessionGroupingParamChanged),
2107 X(MEAudioSessionIconChanged),
2108 X(MEAudioSessionFormatChanged),
2109 X(MEAudioSessionDisconnected),
2110 X(MEAudioSessionExclusiveModeOverride),
2111 X(METrustUnknown),
2112 X(MEPolicyChanged),
2113 X(MEContentProtectionMessage),
2114 X(MEPolicySet),
2115 X(MEWMDRMLicenseBackupCompleted),
2116 X(MEWMDRMLicenseBackupProgress),
2117 X(MEWMDRMLicenseRestoreCompleted),
2118 X(MEWMDRMLicenseRestoreProgress),
2119 X(MEWMDRMLicenseAcquisitionCompleted),
2120 X(MEWMDRMIndividualizationCompleted),
2121 X(MEWMDRMIndividualizationProgress),
2122 X(MEWMDRMProximityCompleted),
2123 X(MEWMDRMLicenseStoreCleaned),
2124 X(MEWMDRMRevocationDownloadCompleted),
2125 X(METransformUnknown),
2126 X(METransformNeedInput),
2127 X(METransformHaveOutput),
2128 X(METransformDrainComplete),
2129 X(METransformMarker),
2130 X(METransformInputStreamStateChanged),
2131 X(MEByteStreamCharacteristicsChanged),
2132 X(MEVideoCaptureDeviceRemoved),
2133 X(MEVideoCaptureDevicePreempted),
2134 X(MEStreamSinkFormatInvalidated),
2135 X(MEEncodingParameters),
2136 X(MEContentProtectionMetadata),
2137 X(MEDeviceThermalStateChanged),
2138 #undef X
2141 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2142 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%u", event);
2145 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2147 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2150 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2152 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2154 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2155 IsEqualGUID(riid, &IID_IUnknown))
2157 *out = iface;
2158 IMFAttributes_AddRef(iface);
2159 return S_OK;
2162 WARN("Unsupported %s.\n", debugstr_guid(riid));
2163 *out = NULL;
2164 return E_NOINTERFACE;
2167 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2169 struct attributes *attributes = impl_from_IMFAttributes(iface);
2170 ULONG refcount = InterlockedIncrement(&attributes->ref);
2172 TRACE("%p, refcount %d.\n", iface, refcount);
2174 return refcount;
2177 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2179 struct attributes *attributes = impl_from_IMFAttributes(iface);
2180 ULONG refcount = InterlockedDecrement(&attributes->ref);
2182 TRACE("%p, refcount %d.\n", iface, refcount);
2184 if (!refcount)
2186 clear_attributes_object(attributes);
2187 heap_free(attributes);
2190 return refcount;
2193 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2195 size_t i;
2197 for (i = 0; i < attributes->count; ++i)
2199 if (IsEqualGUID(key, &attributes->attributes[i].key))
2201 if (index)
2202 *index = i;
2203 return &attributes->attributes[i];
2207 return NULL;
2210 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2212 struct attribute *attribute;
2213 HRESULT hr;
2215 EnterCriticalSection(&attributes->cs);
2217 attribute = attributes_find_item(attributes, key, NULL);
2218 if (attribute)
2220 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.punkVal))
2221 hr = PropVariantCopy(value, &attribute->value);
2222 else
2223 hr = MF_E_INVALIDTYPE;
2225 else
2226 hr = MF_E_ATTRIBUTENOTFOUND;
2228 LeaveCriticalSection(&attributes->cs);
2230 return hr;
2233 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2235 struct attribute *attribute;
2236 HRESULT hr;
2238 EnterCriticalSection(&attributes->cs);
2240 if ((attribute = attributes_find_item(attributes, key, NULL)))
2241 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2242 else
2243 hr = MF_E_ATTRIBUTENOTFOUND;
2245 LeaveCriticalSection(&attributes->cs);
2247 return hr;
2250 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2252 struct attribute *attribute;
2253 HRESULT hr = S_OK;
2255 EnterCriticalSection(&attributes->cs);
2257 if ((attribute = attributes_find_item(attributes, key, NULL)))
2259 *type = attribute->value.vt;
2261 else
2262 hr = MF_E_ATTRIBUTENOTFOUND;
2264 LeaveCriticalSection(&attributes->cs);
2266 return hr;
2269 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2271 struct attribute *attribute;
2273 *result = FALSE;
2275 EnterCriticalSection(&attributes->cs);
2277 if ((attribute = attributes_find_item(attributes, key, NULL)))
2279 *result = attribute->value.vt == value->vt &&
2280 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2283 LeaveCriticalSection(&attributes->cs);
2285 return S_OK;
2288 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2289 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2291 IMFAttributes *smaller, *other;
2292 MF_ATTRIBUTE_TYPE type;
2293 HRESULT hr = S_OK;
2294 UINT32 count;
2295 BOOL result;
2296 size_t i;
2298 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2299 return hr;
2301 EnterCriticalSection(&attributes->cs);
2303 result = TRUE;
2305 switch (match_type)
2307 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2308 for (i = 0; i < attributes->count; ++i)
2310 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2311 &attributes->attributes[i].value, &result)))
2312 break;
2313 if (!result)
2314 break;
2316 break;
2317 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2318 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2319 break;
2320 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2321 if (count != attributes->count)
2323 result = FALSE;
2324 break;
2326 for (i = 0; i < count; ++i)
2328 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2329 &attributes->attributes[i].value, &result)))
2330 break;
2331 if (!result)
2332 break;
2334 break;
2335 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2336 for (i = 0; i < attributes->count; ++i)
2338 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2339 continue;
2341 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2342 &attributes->attributes[i].value, &result)))
2343 break;
2345 if (!result)
2346 break;
2348 break;
2349 case MF_ATTRIBUTES_MATCH_SMALLER:
2350 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2351 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2352 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2353 break;
2354 default:
2355 WARN("Unknown match type %d.\n", match_type);
2356 hr = E_INVALIDARG;
2359 LeaveCriticalSection(&attributes->cs);
2361 if (SUCCEEDED(hr))
2362 *ret = result;
2364 return hr;
2367 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2369 PROPVARIANT attrval;
2370 HRESULT hr;
2372 PropVariantInit(&attrval);
2373 attrval.vt = VT_UI4;
2374 hr = attributes_get_item(attributes, key, &attrval);
2375 if (SUCCEEDED(hr))
2376 *value = attrval.ulVal;
2378 return hr;
2381 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2383 PROPVARIANT attrval;
2384 HRESULT hr;
2386 PropVariantInit(&attrval);
2387 attrval.vt = VT_UI8;
2388 hr = attributes_get_item(attributes, key, &attrval);
2389 if (SUCCEEDED(hr))
2390 *value = attrval.uhVal.QuadPart;
2392 return hr;
2395 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2397 PROPVARIANT attrval;
2398 HRESULT hr;
2400 PropVariantInit(&attrval);
2401 attrval.vt = VT_R8;
2402 hr = attributes_get_item(attributes, key, &attrval);
2403 if (SUCCEEDED(hr))
2404 *value = attrval.dblVal;
2406 return hr;
2409 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
2411 struct attribute *attribute;
2412 HRESULT hr = S_OK;
2414 EnterCriticalSection(&attributes->cs);
2416 attribute = attributes_find_item(attributes, key, NULL);
2417 if (attribute)
2419 if (attribute->value.vt == MF_ATTRIBUTE_GUID)
2420 *value = *attribute->value.puuid;
2421 else
2422 hr = MF_E_INVALIDTYPE;
2424 else
2425 hr = MF_E_ATTRIBUTENOTFOUND;
2427 LeaveCriticalSection(&attributes->cs);
2429 return hr;
2432 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2434 struct attribute *attribute;
2435 HRESULT hr = S_OK;
2437 EnterCriticalSection(&attributes->cs);
2439 attribute = attributes_find_item(attributes, key, NULL);
2440 if (attribute)
2442 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2443 *length = lstrlenW(attribute->value.pwszVal);
2444 else
2445 hr = MF_E_INVALIDTYPE;
2447 else
2448 hr = MF_E_ATTRIBUTENOTFOUND;
2450 LeaveCriticalSection(&attributes->cs);
2452 return hr;
2455 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2456 UINT32 size, UINT32 *length)
2458 struct attribute *attribute;
2459 HRESULT hr = S_OK;
2461 EnterCriticalSection(&attributes->cs);
2463 attribute = attributes_find_item(attributes, key, NULL);
2464 if (attribute)
2466 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2468 int len = lstrlenW(attribute->value.pwszVal);
2470 if (length)
2471 *length = len;
2473 if (size <= len)
2474 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2475 else
2476 memcpy(value, attribute->value.pwszVal, (len + 1) * sizeof(WCHAR));
2478 else
2479 hr = MF_E_INVALIDTYPE;
2481 else
2482 hr = MF_E_ATTRIBUTENOTFOUND;
2484 LeaveCriticalSection(&attributes->cs);
2486 return hr;
2489 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2491 PROPVARIANT attrval;
2492 HRESULT hr;
2494 PropVariantInit(&attrval);
2495 attrval.vt = VT_LPWSTR;
2496 hr = attributes_get_item(attributes, key, &attrval);
2497 if (SUCCEEDED(hr))
2499 *value = attrval.pwszVal;
2500 *length = lstrlenW(*value);
2503 return hr;
2506 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2508 struct attribute *attribute;
2509 HRESULT hr = S_OK;
2511 EnterCriticalSection(&attributes->cs);
2513 attribute = attributes_find_item(attributes, key, NULL);
2514 if (attribute)
2516 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2517 *size = attribute->value.caub.cElems;
2518 else
2519 hr = MF_E_INVALIDTYPE;
2521 else
2522 hr = MF_E_ATTRIBUTENOTFOUND;
2524 LeaveCriticalSection(&attributes->cs);
2526 return hr;
2529 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2531 struct attribute *attribute;
2532 HRESULT hr;
2534 EnterCriticalSection(&attributes->cs);
2536 attribute = attributes_find_item(attributes, key, NULL);
2537 if (attribute)
2539 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2541 UINT32 size = attribute->value.caub.cElems;
2543 if (bufsize >= size)
2544 hr = PropVariantToBuffer(&attribute->value, buf, size);
2545 else
2546 hr = E_NOT_SUFFICIENT_BUFFER;
2548 if (blobsize)
2549 *blobsize = size;
2551 else
2552 hr = MF_E_INVALIDTYPE;
2554 else
2555 hr = MF_E_ATTRIBUTENOTFOUND;
2557 LeaveCriticalSection(&attributes->cs);
2559 return hr;
2562 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2564 PROPVARIANT attrval;
2565 HRESULT hr;
2567 attrval.vt = VT_VECTOR | VT_UI1;
2568 hr = attributes_get_item(attributes, key, &attrval);
2569 if (SUCCEEDED(hr))
2571 *buf = attrval.caub.pElems;
2572 *size = attrval.caub.cElems;
2575 return hr;
2578 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2580 PROPVARIANT attrval;
2581 HRESULT hr;
2583 PropVariantInit(&attrval);
2584 attrval.vt = VT_UNKNOWN;
2585 hr = attributes_get_item(attributes, key, &attrval);
2586 if (SUCCEEDED(hr))
2587 hr = IUnknown_QueryInterface(attrval.punkVal, riid, out);
2588 PropVariantClear(&attrval);
2589 return hr;
2592 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2594 struct attribute *attribute;
2596 EnterCriticalSection(&attributes->cs);
2598 attribute = attributes_find_item(attributes, key, NULL);
2599 if (!attribute)
2601 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2602 sizeof(*attributes->attributes)))
2604 LeaveCriticalSection(&attributes->cs);
2605 return E_OUTOFMEMORY;
2607 attributes->attributes[attributes->count].key = *key;
2608 attribute = &attributes->attributes[attributes->count++];
2610 else
2611 PropVariantClear(&attribute->value);
2613 PropVariantCopy(&attribute->value, value);
2615 LeaveCriticalSection(&attributes->cs);
2617 return S_OK;
2620 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2622 PROPVARIANT empty;
2624 switch (value->vt)
2626 case MF_ATTRIBUTE_UINT32:
2627 case MF_ATTRIBUTE_UINT64:
2628 case MF_ATTRIBUTE_DOUBLE:
2629 case MF_ATTRIBUTE_GUID:
2630 case MF_ATTRIBUTE_STRING:
2631 case MF_ATTRIBUTE_BLOB:
2632 case MF_ATTRIBUTE_IUNKNOWN:
2633 return attributes_set_item(attributes, key, value);
2634 default:
2635 PropVariantInit(&empty);
2636 attributes_set_item(attributes, key, &empty);
2637 return MF_E_INVALIDTYPE;
2641 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2643 struct attribute *attribute;
2644 size_t index = 0;
2646 EnterCriticalSection(&attributes->cs);
2648 if ((attribute = attributes_find_item(attributes, key, &index)))
2650 size_t count;
2652 PropVariantClear(&attribute->value);
2654 attributes->count--;
2655 count = attributes->count - index;
2656 if (count)
2657 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2660 LeaveCriticalSection(&attributes->cs);
2662 return S_OK;
2665 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2667 EnterCriticalSection(&attributes->cs);
2669 while (attributes->count)
2671 PropVariantClear(&attributes->attributes[--attributes->count].value);
2673 heap_free(attributes->attributes);
2674 attributes->attributes = NULL;
2675 attributes->capacity = 0;
2677 LeaveCriticalSection(&attributes->cs);
2679 return S_OK;
2682 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2684 PROPVARIANT attrval;
2686 attrval.vt = VT_UI4;
2687 attrval.ulVal = value;
2688 return attributes_set_item(attributes, key, &attrval);
2691 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2693 PROPVARIANT attrval;
2695 attrval.vt = VT_UI8;
2696 attrval.uhVal.QuadPart = value;
2697 return attributes_set_item(attributes, key, &attrval);
2700 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2702 PROPVARIANT attrval;
2704 attrval.vt = VT_R8;
2705 attrval.dblVal = value;
2706 return attributes_set_item(attributes, key, &attrval);
2709 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2711 PROPVARIANT attrval;
2713 attrval.vt = VT_CLSID;
2714 attrval.puuid = (CLSID *)value;
2715 return attributes_set_item(attributes, key, &attrval);
2718 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2720 PROPVARIANT attrval;
2722 attrval.vt = VT_LPWSTR;
2723 attrval.pwszVal = (WCHAR *)value;
2724 return attributes_set_item(attributes, key, &attrval);
2727 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2729 PROPVARIANT attrval;
2731 attrval.vt = VT_VECTOR | VT_UI1;
2732 attrval.caub.cElems = size;
2733 attrval.caub.pElems = (UINT8 *)buf;
2734 return attributes_set_item(attributes, key, &attrval);
2737 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2739 PROPVARIANT attrval;
2741 attrval.vt = VT_UNKNOWN;
2742 attrval.punkVal = unknown;
2743 return attributes_set_item(attributes, key, &attrval);
2746 HRESULT attributes_LockStore(struct attributes *attributes)
2748 EnterCriticalSection(&attributes->cs);
2750 return S_OK;
2753 HRESULT attributes_UnlockStore(struct attributes *attributes)
2755 LeaveCriticalSection(&attributes->cs);
2757 return S_OK;
2760 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2762 EnterCriticalSection(&attributes->cs);
2763 *count = attributes->count;
2764 LeaveCriticalSection(&attributes->cs);
2766 return S_OK;
2769 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2771 HRESULT hr = S_OK;
2773 EnterCriticalSection(&attributes->cs);
2775 if (index < attributes->count)
2777 *key = attributes->attributes[index].key;
2778 if (value)
2779 PropVariantCopy(value, &attributes->attributes[index].value);
2781 else
2782 hr = E_INVALIDARG;
2784 LeaveCriticalSection(&attributes->cs);
2786 return hr;
2789 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2791 HRESULT hr = S_OK;
2792 size_t i;
2794 EnterCriticalSection(&attributes->cs);
2796 IMFAttributes_LockStore(dest);
2798 IMFAttributes_DeleteAllItems(dest);
2800 for (i = 0; i < attributes->count; ++i)
2802 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2803 if (FAILED(hr))
2804 break;
2807 IMFAttributes_UnlockStore(dest);
2809 LeaveCriticalSection(&attributes->cs);
2811 return hr;
2814 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2816 struct attributes *attributes = impl_from_IMFAttributes(iface);
2818 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2820 return attributes_GetItem(attributes, key, value);
2823 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2825 struct attributes *attributes = impl_from_IMFAttributes(iface);
2827 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
2829 return attributes_GetItemType(attributes, key, type);
2832 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
2834 struct attributes *attributes = impl_from_IMFAttributes(iface);
2836 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
2838 return attributes_CompareItem(attributes, key, value, result);
2841 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2842 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2844 struct attributes *attributes = impl_from_IMFAttributes(iface);
2846 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
2848 return attributes_Compare(attributes, theirs, match_type, ret);
2851 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2853 struct attributes *attributes = impl_from_IMFAttributes(iface);
2855 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2857 return attributes_GetUINT32(attributes, key, value);
2860 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2862 struct attributes *attributes = impl_from_IMFAttributes(iface);
2864 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2866 return attributes_GetUINT64(attributes, key, value);
2869 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2871 struct attributes *attributes = impl_from_IMFAttributes(iface);
2873 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2875 return attributes_GetDouble(attributes, key, value);
2878 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2880 struct attributes *attributes = impl_from_IMFAttributes(iface);
2882 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
2884 return attributes_GetGUID(attributes, key, value);
2887 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
2889 struct attributes *attributes = impl_from_IMFAttributes(iface);
2891 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
2893 return attributes_GetStringLength(attributes, key, length);
2896 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2897 UINT32 size, UINT32 *length)
2899 struct attributes *attributes = impl_from_IMFAttributes(iface);
2901 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
2903 return attributes_GetString(attributes, key, value, size, length);
2906 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
2908 struct attributes *attributes = impl_from_IMFAttributes(iface);
2910 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
2912 return attributes_GetAllocatedString(attributes, key, value, length);
2915 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2917 struct attributes *attributes = impl_from_IMFAttributes(iface);
2919 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
2921 return attributes_GetBlobSize(attributes, key, size);
2924 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2925 UINT32 bufsize, UINT32 *blobsize)
2927 struct attributes *attributes = impl_from_IMFAttributes(iface);
2929 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
2931 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
2934 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
2936 struct attributes *attributes = impl_from_IMFAttributes(iface);
2938 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
2940 return attributes_GetAllocatedBlob(attributes, key, buf, size);
2943 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2945 struct attributes *attributes = impl_from_IMFAttributes(iface);
2947 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
2949 return attributes_GetUnknown(attributes, key, riid, out);
2952 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2954 struct attributes *attributes = impl_from_IMFAttributes(iface);
2956 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
2958 return attributes_SetItem(attributes, key, value);
2961 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2963 struct attributes *attributes = impl_from_IMFAttributes(iface);
2965 TRACE("%p, %s.\n", iface, debugstr_attr(key));
2967 return attributes_DeleteItem(attributes, key);
2970 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
2972 struct attributes *attributes = impl_from_IMFAttributes(iface);
2974 TRACE("%p.\n", iface);
2976 return attributes_DeleteAllItems(attributes);
2979 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2981 struct attributes *attributes = impl_from_IMFAttributes(iface);
2983 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
2985 return attributes_SetUINT32(attributes, key, value);
2988 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
2990 struct attributes *attributes = impl_from_IMFAttributes(iface);
2992 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
2994 return attributes_SetUINT64(attributes, key, value);
2997 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
2999 struct attributes *attributes = impl_from_IMFAttributes(iface);
3001 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
3003 return attributes_SetDouble(attributes, key, value);
3006 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
3008 struct attributes *attributes = impl_from_IMFAttributes(iface);
3010 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
3012 return attributes_SetGUID(attributes, key, value);
3015 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
3017 struct attributes *attributes = impl_from_IMFAttributes(iface);
3019 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
3021 return attributes_SetString(attributes, key, value);
3024 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
3026 struct attributes *attributes = impl_from_IMFAttributes(iface);
3028 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
3030 return attributes_SetBlob(attributes, key, buf, size);
3033 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
3035 struct attributes *attributes = impl_from_IMFAttributes(iface);
3037 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
3039 return attributes_SetUnknown(attributes, key, unknown);
3042 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
3044 struct attributes *attributes = impl_from_IMFAttributes(iface);
3046 TRACE("%p.\n", iface);
3048 return attributes_LockStore(attributes);
3051 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
3053 struct attributes *attributes = impl_from_IMFAttributes(iface);
3055 TRACE("%p.\n", iface);
3057 return attributes_UnlockStore(attributes);
3060 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
3062 struct attributes *attributes = impl_from_IMFAttributes(iface);
3064 TRACE("%p, %p.\n", iface, count);
3066 return attributes_GetCount(attributes, count);
3069 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
3071 struct attributes *attributes = impl_from_IMFAttributes(iface);
3073 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
3075 return attributes_GetItemByIndex(attributes, index, key, value);
3078 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
3080 struct attributes *attributes = impl_from_IMFAttributes(iface);
3082 TRACE("%p, %p.\n", iface, dest);
3084 return attributes_CopyAllItems(attributes, dest);
3087 static const IMFAttributesVtbl mfattributes_vtbl =
3089 mfattributes_QueryInterface,
3090 mfattributes_AddRef,
3091 mfattributes_Release,
3092 mfattributes_GetItem,
3093 mfattributes_GetItemType,
3094 mfattributes_CompareItem,
3095 mfattributes_Compare,
3096 mfattributes_GetUINT32,
3097 mfattributes_GetUINT64,
3098 mfattributes_GetDouble,
3099 mfattributes_GetGUID,
3100 mfattributes_GetStringLength,
3101 mfattributes_GetString,
3102 mfattributes_GetAllocatedString,
3103 mfattributes_GetBlobSize,
3104 mfattributes_GetBlob,
3105 mfattributes_GetAllocatedBlob,
3106 mfattributes_GetUnknown,
3107 mfattributes_SetItem,
3108 mfattributes_DeleteItem,
3109 mfattributes_DeleteAllItems,
3110 mfattributes_SetUINT32,
3111 mfattributes_SetUINT64,
3112 mfattributes_SetDouble,
3113 mfattributes_SetGUID,
3114 mfattributes_SetString,
3115 mfattributes_SetBlob,
3116 mfattributes_SetUnknown,
3117 mfattributes_LockStore,
3118 mfattributes_UnlockStore,
3119 mfattributes_GetCount,
3120 mfattributes_GetItemByIndex,
3121 mfattributes_CopyAllItems
3124 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3126 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3127 object->ref = 1;
3128 InitializeCriticalSection(&object->cs);
3130 object->attributes = NULL;
3131 object->count = 0;
3132 object->capacity = 0;
3133 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3134 sizeof(*object->attributes)))
3136 DeleteCriticalSection(&object->cs);
3137 return E_OUTOFMEMORY;
3140 return S_OK;
3143 void clear_attributes_object(struct attributes *object)
3145 size_t i;
3147 for (i = 0; i < object->count; i++)
3148 PropVariantClear(&object->attributes[i].value);
3149 heap_free(object->attributes);
3151 DeleteCriticalSection(&object->cs);
3154 /***********************************************************************
3155 * MFCreateAttributes (mfplat.@)
3157 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3159 struct attributes *object;
3160 HRESULT hr;
3162 TRACE("%p, %d\n", attributes, size);
3164 object = heap_alloc_zero(sizeof(*object));
3165 if (!object)
3166 return E_OUTOFMEMORY;
3168 if (FAILED(hr = init_attributes_object(object, size)))
3170 heap_free(object);
3171 return hr;
3173 *attributes = &object->IMFAttributes_iface;
3175 return S_OK;
3178 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3180 struct attributes_store_header
3182 DWORD magic;
3183 UINT32 count;
3186 struct attributes_store_item
3188 GUID key;
3189 QWORD type;
3190 union
3192 double f;
3193 UINT32 i32;
3194 UINT64 i64;
3195 struct
3197 DWORD size;
3198 DWORD offset;
3199 } subheader;
3200 } u;
3203 /***********************************************************************
3204 * MFGetAttributesAsBlobSize (mfplat.@)
3206 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3208 unsigned int i, count, length;
3209 HRESULT hr;
3210 GUID key;
3212 TRACE("%p, %p.\n", attributes, size);
3214 IMFAttributes_LockStore(attributes);
3216 hr = IMFAttributes_GetCount(attributes, &count);
3218 *size = sizeof(struct attributes_store_header);
3220 for (i = 0; i < count; ++i)
3222 MF_ATTRIBUTE_TYPE type;
3224 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3225 if (FAILED(hr))
3226 break;
3228 *size += sizeof(struct attributes_store_item);
3230 IMFAttributes_GetItemType(attributes, &key, &type);
3232 switch (type)
3234 case MF_ATTRIBUTE_GUID:
3235 *size += sizeof(GUID);
3236 break;
3237 case MF_ATTRIBUTE_STRING:
3238 IMFAttributes_GetStringLength(attributes, &key, &length);
3239 *size += (length + 1) * sizeof(WCHAR);
3240 break;
3241 case MF_ATTRIBUTE_BLOB:
3242 IMFAttributes_GetBlobSize(attributes, &key, &length);
3243 *size += length;
3244 break;
3245 case MF_ATTRIBUTE_UINT32:
3246 case MF_ATTRIBUTE_UINT64:
3247 case MF_ATTRIBUTE_DOUBLE:
3248 case MF_ATTRIBUTE_IUNKNOWN:
3249 default:
3254 IMFAttributes_UnlockStore(attributes);
3256 return hr;
3259 struct attr_serialize_context
3261 UINT8 *buffer;
3262 UINT8 *ptr;
3263 UINT32 size;
3266 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3268 memcpy(context->ptr, value, size);
3269 context->ptr += size;
3272 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3273 const void *value)
3275 switch (item->type)
3277 case MF_ATTRIBUTE_UINT32:
3278 case MF_ATTRIBUTE_UINT64:
3279 case MF_ATTRIBUTE_DOUBLE:
3280 attributes_serialize_write(context, item, sizeof(*item));
3281 break;
3282 case MF_ATTRIBUTE_GUID:
3283 case MF_ATTRIBUTE_STRING:
3284 case MF_ATTRIBUTE_BLOB:
3285 item->u.subheader.offset = context->size - item->u.subheader.size;
3286 attributes_serialize_write(context, item, sizeof(*item));
3287 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3288 context->size -= item->u.subheader.size;
3289 break;
3290 default:
3291 return FALSE;
3294 return TRUE;
3297 /***********************************************************************
3298 * MFGetAttributesAsBlob (mfplat.@)
3300 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3302 struct attributes_store_header header;
3303 struct attr_serialize_context context;
3304 unsigned int required_size, i;
3305 PROPVARIANT value;
3306 UINT32 count;
3307 HRESULT hr;
3309 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3311 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3312 return hr;
3314 if (required_size > size)
3315 return MF_E_BUFFERTOOSMALL;
3317 context.buffer = buffer;
3318 context.ptr = buffer;
3319 context.size = required_size;
3321 IMFAttributes_LockStore(attributes);
3323 header.magic = ATTRIBUTES_STORE_MAGIC;
3324 header.count = 0; /* Will be updated later */
3325 IMFAttributes_GetCount(attributes, &count);
3327 attributes_serialize_write(&context, &header, sizeof(header));
3329 for (i = 0; i < count; ++i)
3331 struct attributes_store_item item;
3332 const void *data = NULL;
3334 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3335 if (FAILED(hr))
3336 break;
3338 item.type = value.vt;
3340 switch (value.vt)
3342 case MF_ATTRIBUTE_UINT32:
3343 case MF_ATTRIBUTE_UINT64:
3344 item.u.i64 = value.uhVal.QuadPart;
3345 break;
3346 case MF_ATTRIBUTE_DOUBLE:
3347 item.u.f = value.dblVal;
3348 break;
3349 case MF_ATTRIBUTE_GUID:
3350 item.u.subheader.size = sizeof(*value.puuid);
3351 data = value.puuid;
3352 break;
3353 case MF_ATTRIBUTE_STRING:
3354 item.u.subheader.size = (lstrlenW(value.pwszVal) + 1) * sizeof(WCHAR);
3355 data = value.pwszVal;
3356 break;
3357 case MF_ATTRIBUTE_BLOB:
3358 item.u.subheader.size = value.caub.cElems;
3359 data = value.caub.pElems;
3360 break;
3361 case MF_ATTRIBUTE_IUNKNOWN:
3362 break;
3363 default:
3364 WARN("Unknown attribute type %#x.\n", value.vt);
3367 if (attributes_serialize_write_item(&context, &item, data))
3368 header.count++;
3370 PropVariantClear(&value);
3373 memcpy(context.buffer, &header, sizeof(header));
3375 IMFAttributes_UnlockStore(attributes);
3377 return S_OK;
3380 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3382 if (context->size < (context->ptr - context->buffer) + size)
3383 return E_INVALIDARG;
3385 memcpy(value, context->ptr, size);
3386 context->ptr += size;
3388 return S_OK;
3391 /***********************************************************************
3392 * MFInitAttributesFromBlob (mfplat.@)
3394 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3396 struct attr_serialize_context context;
3397 struct attributes_store_header header;
3398 struct attributes_store_item item;
3399 IMFAttributes *attributes;
3400 unsigned int i;
3401 HRESULT hr;
3403 TRACE("%p, %p, %u.\n", dest, buffer, size);
3405 context.buffer = (UINT8 *)buffer;
3406 context.ptr = (UINT8 *)buffer;
3407 context.size = size;
3409 /* Validate buffer structure. */
3410 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3411 return hr;
3413 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3414 return E_UNEXPECTED;
3416 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3417 return hr;
3419 for (i = 0; i < header.count; ++i)
3421 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3422 break;
3424 hr = E_UNEXPECTED;
3426 switch (item.type)
3428 case MF_ATTRIBUTE_UINT32:
3429 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3430 break;
3431 case MF_ATTRIBUTE_UINT64:
3432 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3433 break;
3434 case MF_ATTRIBUTE_DOUBLE:
3435 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3436 break;
3437 case MF_ATTRIBUTE_GUID:
3438 if (item.u.subheader.size == sizeof(GUID) &&
3439 item.u.subheader.offset + item.u.subheader.size <= context.size)
3441 hr = IMFAttributes_SetGUID(attributes, &item.key,
3442 (const GUID *)(context.buffer + item.u.subheader.offset));
3444 break;
3445 case MF_ATTRIBUTE_STRING:
3446 if (item.u.subheader.size >= sizeof(WCHAR) &&
3447 item.u.subheader.offset + item.u.subheader.size <= context.size)
3449 hr = IMFAttributes_SetString(attributes, &item.key,
3450 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3452 break;
3453 case MF_ATTRIBUTE_BLOB:
3454 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3456 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3457 item.u.subheader.size);
3459 break;
3460 default:
3464 if (FAILED(hr))
3465 break;
3468 if (SUCCEEDED(hr))
3470 IMFAttributes_DeleteAllItems(dest);
3471 hr = IMFAttributes_CopyAllItems(attributes, dest);
3474 IMFAttributes_Release(attributes);
3476 return hr;
3479 typedef struct bytestream
3481 struct attributes attributes;
3482 IMFByteStream IMFByteStream_iface;
3483 IMFGetService IMFGetService_iface;
3484 IRtwqAsyncCallback read_callback;
3485 IRtwqAsyncCallback write_callback;
3486 IStream *stream;
3487 HANDLE hfile;
3488 QWORD position;
3489 DWORD capabilities;
3490 struct list pending;
3491 CRITICAL_SECTION cs;
3492 } mfbytestream;
3494 static inline mfbytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3496 return CONTAINING_RECORD(iface, mfbytestream, IMFByteStream_iface);
3499 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3501 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3504 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3506 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3509 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3511 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3514 enum async_stream_op_type
3516 ASYNC_STREAM_OP_READ,
3517 ASYNC_STREAM_OP_WRITE,
3520 struct async_stream_op
3522 IUnknown IUnknown_iface;
3523 LONG refcount;
3524 union
3526 const BYTE *src;
3527 BYTE *dest;
3528 } u;
3529 QWORD position;
3530 ULONG requested_length;
3531 ULONG actual_length;
3532 IMFAsyncResult *caller;
3533 struct list entry;
3534 enum async_stream_op_type type;
3537 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3539 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3542 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3544 if (IsEqualIID(riid, &IID_IUnknown))
3546 *obj = iface;
3547 IUnknown_AddRef(iface);
3548 return S_OK;
3551 WARN("Unsupported %s.\n", debugstr_guid(riid));
3552 *obj = NULL;
3553 return E_NOINTERFACE;
3556 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3558 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3559 ULONG refcount = InterlockedIncrement(&op->refcount);
3561 TRACE("%p, refcount %d.\n", iface, refcount);
3563 return refcount;
3566 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3568 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3569 ULONG refcount = InterlockedDecrement(&op->refcount);
3571 TRACE("%p, refcount %d.\n", iface, refcount);
3573 if (!refcount)
3575 if (op->caller)
3576 IMFAsyncResult_Release(op->caller);
3577 heap_free(op);
3580 return refcount;
3583 static const IUnknownVtbl async_stream_op_vtbl =
3585 async_stream_op_QueryInterface,
3586 async_stream_op_AddRef,
3587 async_stream_op_Release,
3590 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3591 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3593 struct async_stream_op *op;
3594 IRtwqAsyncResult *request;
3595 HRESULT hr;
3597 op = heap_alloc(sizeof(*op));
3598 if (!op)
3599 return E_OUTOFMEMORY;
3601 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3602 op->refcount = 1;
3603 op->u.src = data;
3604 op->position = stream->position;
3605 op->requested_length = size;
3606 op->type = type;
3607 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3608 (IRtwqAsyncResult **)&op->caller)))
3610 goto failed;
3613 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3614 &stream->write_callback, NULL, &request)))
3615 goto failed;
3617 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, request);
3618 IRtwqAsyncResult_Release(request);
3620 failed:
3621 IUnknown_Release(&op->IUnknown_iface);
3622 return hr;
3625 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3626 IMFAsyncResult *result, ULONG *actual_length)
3628 struct async_stream_op *op = NULL, *cur;
3629 HRESULT hr;
3631 EnterCriticalSection(&stream->cs);
3632 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3634 if (cur->caller == result && cur->type == type)
3636 op = cur;
3637 list_remove(&cur->entry);
3638 break;
3641 LeaveCriticalSection(&stream->cs);
3643 if (!op)
3644 return E_INVALIDARG;
3646 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3647 *actual_length = op->actual_length;
3649 IUnknown_Release(&op->IUnknown_iface);
3651 return hr;
3654 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3656 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3657 IsEqualIID(riid, &IID_IUnknown))
3659 *obj = iface;
3660 IRtwqAsyncCallback_AddRef(iface);
3661 return S_OK;
3664 WARN("Unsupported %s.\n", debugstr_guid(riid));
3665 *obj = NULL;
3666 return E_NOINTERFACE;
3669 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3671 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3672 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3675 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3677 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3678 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3681 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3683 return E_NOTIMPL;
3686 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3688 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3689 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3692 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3694 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3695 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3698 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3700 struct bytestream *stream = impl_from_IMFByteStream(iface);
3702 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3704 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3705 IsEqualIID(riid, &IID_IUnknown))
3707 *out = &stream->IMFByteStream_iface;
3709 else if (IsEqualIID(riid, &IID_IMFAttributes))
3711 *out = &stream->attributes.IMFAttributes_iface;
3713 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3715 *out = &stream->IMFGetService_iface;
3717 else
3719 WARN("Unsupported %s.\n", debugstr_guid(riid));
3720 *out = NULL;
3721 return E_NOINTERFACE;
3724 IUnknown_AddRef((IUnknown*)*out);
3725 return S_OK;
3728 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3730 struct bytestream *stream = impl_from_IMFByteStream(iface);
3731 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3733 TRACE("%p, refcount %d.\n", iface, refcount);
3735 return refcount;
3738 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3740 struct bytestream *stream = impl_from_IMFByteStream(iface);
3741 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3742 struct async_stream_op *cur, *cur2;
3744 TRACE("%p, refcount %d.\n", iface, refcount);
3746 if (!refcount)
3748 clear_attributes_object(&stream->attributes);
3749 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3751 list_remove(&cur->entry);
3752 IUnknown_Release(&cur->IUnknown_iface);
3754 DeleteCriticalSection(&stream->cs);
3755 if (stream->stream)
3756 IStream_Release(stream->stream);
3757 if (stream->hfile)
3758 CloseHandle(stream->hfile);
3759 heap_free(stream);
3762 return refcount;
3765 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3767 struct bytestream *stream = impl_from_IMFByteStream(iface);
3768 STATSTG stat;
3769 HRESULT hr;
3771 TRACE("%p, %p.\n", iface, capabilities);
3773 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3774 return hr;
3776 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3777 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3778 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3780 return S_OK;
3783 static HRESULT WINAPI bytestream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3785 struct bytestream *stream = impl_from_IMFByteStream(iface);
3787 TRACE("%p, %p.\n", iface, capabilities);
3789 *capabilities = stream->capabilities;
3791 return S_OK;
3794 static HRESULT WINAPI mfbytestream_SetLength(IMFByteStream *iface, QWORD length)
3796 mfbytestream *This = impl_from_IMFByteStream(iface);
3798 FIXME("%p, %s\n", This, wine_dbgstr_longlong(length));
3800 return E_NOTIMPL;
3803 static HRESULT WINAPI bytestream_file_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3805 struct bytestream *stream = impl_from_IMFByteStream(iface);
3807 TRACE("%p, %p.\n", iface, position);
3809 if (!position)
3810 return E_INVALIDARG;
3812 *position = stream->position;
3814 return S_OK;
3817 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
3819 struct bytestream *stream = impl_from_IMFByteStream(iface);
3820 LARGE_INTEGER li;
3822 TRACE("%p, %p.\n", iface, length);
3824 if (!length)
3825 return E_INVALIDARG;
3827 if (GetFileSizeEx(stream->hfile, &li))
3828 *length = li.QuadPart;
3829 else
3830 return HRESULT_FROM_WIN32(GetLastError());
3832 return S_OK;
3835 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
3837 struct bytestream *stream = impl_from_IMFByteStream(iface);
3838 LARGE_INTEGER position, length;
3839 HRESULT hr = S_OK;
3841 TRACE("%p, %p.\n", iface, ret);
3843 EnterCriticalSection(&stream->cs);
3845 position.QuadPart = 0;
3846 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
3847 *ret = stream->position >= length.QuadPart;
3848 else
3849 hr = HRESULT_FROM_WIN32(GetLastError());
3851 LeaveCriticalSection(&stream->cs);
3853 return hr;
3856 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
3858 struct bytestream *stream = impl_from_IMFByteStream(iface);
3859 LARGE_INTEGER position;
3860 HRESULT hr = S_OK;
3861 BOOL ret;
3863 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
3865 EnterCriticalSection(&stream->cs);
3867 position.QuadPart = stream->position;
3868 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
3870 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
3871 stream->position += *read_len;
3874 if (!ret)
3875 hr = HRESULT_FROM_WIN32(GetLastError());
3877 LeaveCriticalSection(&stream->cs);
3879 return hr;
3882 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
3883 IUnknown *state)
3885 struct bytestream *stream = impl_from_IMFByteStream(iface);
3887 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3889 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_READ, data, size, callback, state);
3892 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
3894 struct bytestream *stream = impl_from_IMFByteStream(iface);
3896 TRACE("%p, %p, %p.\n", iface, result, byte_read);
3898 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
3901 static HRESULT WINAPI mfbytestream_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
3903 mfbytestream *This = impl_from_IMFByteStream(iface);
3905 FIXME("%p, %p, %u, %p\n", This, data, count, written);
3907 return E_NOTIMPL;
3910 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
3911 IMFAsyncCallback *callback, IUnknown *state)
3913 struct bytestream *stream = impl_from_IMFByteStream(iface);
3915 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
3917 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
3920 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
3922 struct bytestream *stream = impl_from_IMFByteStream(iface);
3924 TRACE("%p, %p, %p.\n", iface, result, written);
3926 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
3929 static HRESULT WINAPI mfbytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
3930 DWORD flags, QWORD *current)
3932 mfbytestream *This = impl_from_IMFByteStream(iface);
3934 FIXME("%p, %u, %s, 0x%08x, %p\n", This, seek, wine_dbgstr_longlong(offset), flags, current);
3936 return E_NOTIMPL;
3939 static HRESULT WINAPI mfbytestream_Flush(IMFByteStream *iface)
3941 mfbytestream *This = impl_from_IMFByteStream(iface);
3943 FIXME("%p\n", This);
3945 return E_NOTIMPL;
3948 static HRESULT WINAPI mfbytestream_Close(IMFByteStream *iface)
3950 mfbytestream *This = impl_from_IMFByteStream(iface);
3952 FIXME("%p\n", This);
3954 return E_NOTIMPL;
3957 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
3959 struct bytestream *stream = impl_from_IMFByteStream(iface);
3961 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
3963 EnterCriticalSection(&stream->cs);
3964 stream->position = position;
3965 LeaveCriticalSection(&stream->cs);
3967 return S_OK;
3970 static const IMFByteStreamVtbl bytestream_file_vtbl =
3972 bytestream_QueryInterface,
3973 bytestream_AddRef,
3974 bytestream_Release,
3975 bytestream_GetCapabilities,
3976 bytestream_file_GetLength,
3977 mfbytestream_SetLength,
3978 bytestream_file_GetCurrentPosition,
3979 bytestream_SetCurrentPosition,
3980 bytestream_file_IsEndOfStream,
3981 bytestream_file_Read,
3982 bytestream_BeginRead,
3983 bytestream_EndRead,
3984 mfbytestream_Write,
3985 bytestream_BeginWrite,
3986 bytestream_EndWrite,
3987 mfbytestream_Seek,
3988 mfbytestream_Flush,
3989 mfbytestream_Close
3992 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
3994 struct bytestream *stream = impl_from_IMFByteStream(iface);
3995 STATSTG statstg;
3996 HRESULT hr;
3998 TRACE("%p, %p.\n", iface, length);
4000 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4001 return hr;
4003 *length = statstg.cbSize.QuadPart;
4005 return S_OK;
4008 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
4010 struct bytestream *stream = impl_from_IMFByteStream(iface);
4011 ULARGE_INTEGER size;
4012 HRESULT hr;
4014 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4016 EnterCriticalSection(&stream->cs);
4018 size.QuadPart = length;
4019 hr = IStream_SetSize(stream->stream, size);
4021 LeaveCriticalSection(&stream->cs);
4023 return hr;
4026 static HRESULT WINAPI bytestream_stream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4028 struct bytestream *stream = impl_from_IMFByteStream(iface);
4030 TRACE("%p, %p.\n", iface, position);
4032 *position = stream->position;
4034 return S_OK;
4037 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4039 struct bytestream *stream = impl_from_IMFByteStream(iface);
4040 STATSTG statstg;
4041 HRESULT hr;
4043 TRACE("%p, %p.\n", iface, ret);
4045 EnterCriticalSection(&stream->cs);
4047 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4048 *ret = stream->position >= statstg.cbSize.QuadPart;
4050 LeaveCriticalSection(&stream->cs);
4052 return hr;
4055 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4057 struct bytestream *stream = impl_from_IMFByteStream(iface);
4058 LARGE_INTEGER position;
4059 HRESULT hr;
4061 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, read_len);
4063 EnterCriticalSection(&stream->cs);
4065 position.QuadPart = stream->position;
4066 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4068 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
4069 stream->position += *read_len;
4072 LeaveCriticalSection(&stream->cs);
4074 return hr;
4077 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
4079 struct bytestream *stream = impl_from_IMFByteStream(iface);
4080 LARGE_INTEGER position;
4081 HRESULT hr;
4083 TRACE("%p, %p, %u, %p.\n", iface, buffer, size, written);
4085 EnterCriticalSection(&stream->cs);
4087 position.QuadPart = stream->position;
4088 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4090 if (SUCCEEDED(hr = IStream_Write(stream->stream, buffer, size, written)))
4091 stream->position += *written;
4094 LeaveCriticalSection(&stream->cs);
4096 return hr;
4099 static HRESULT WINAPI bytestream_stream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
4100 DWORD flags, QWORD *current)
4102 struct bytestream *stream = impl_from_IMFByteStream(iface);
4103 HRESULT hr = S_OK;
4105 TRACE("%p, %u, %s, %#x, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
4107 EnterCriticalSection(&stream->cs);
4109 switch (origin)
4111 case msoBegin:
4112 stream->position = offset;
4113 break;
4114 case msoCurrent:
4115 stream->position += offset;
4116 break;
4117 default:
4118 WARN("Unknown origin mode %d.\n", origin);
4119 hr = E_INVALIDARG;
4122 *current = stream->position;
4124 LeaveCriticalSection(&stream->cs);
4126 return hr;
4129 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4131 struct bytestream *stream = impl_from_IMFByteStream(iface);
4133 TRACE("%p.\n", iface);
4135 return IStream_Commit(stream->stream, STGC_DEFAULT);
4138 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4140 TRACE("%p.\n", iface);
4142 return S_OK;
4145 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4147 bytestream_QueryInterface,
4148 bytestream_AddRef,
4149 bytestream_Release,
4150 bytestream_stream_GetCapabilities,
4151 bytestream_stream_GetLength,
4152 bytestream_stream_SetLength,
4153 bytestream_stream_GetCurrentPosition,
4154 bytestream_SetCurrentPosition,
4155 bytestream_stream_IsEndOfStream,
4156 bytestream_stream_Read,
4157 bytestream_BeginRead,
4158 bytestream_EndRead,
4159 bytestream_stream_Write,
4160 bytestream_BeginWrite,
4161 bytestream_EndWrite,
4162 bytestream_stream_Seek,
4163 bytestream_stream_Flush,
4164 bytestream_stream_Close,
4167 static inline mfbytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4169 return CONTAINING_RECORD(iface, mfbytestream, attributes.IMFAttributes_iface);
4172 static HRESULT WINAPI mfbytestream_attributes_QueryInterface(
4173 IMFAttributes *iface, REFIID riid, void **out)
4175 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4176 return IMFByteStream_QueryInterface(&This->IMFByteStream_iface, riid, out);
4179 static ULONG WINAPI mfbytestream_attributes_AddRef(IMFAttributes *iface)
4181 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4182 return IMFByteStream_AddRef(&This->IMFByteStream_iface);
4185 static ULONG WINAPI mfbytestream_attributes_Release(IMFAttributes *iface)
4187 mfbytestream *This = impl_from_IMFByteStream_IMFAttributes(iface);
4188 return IMFByteStream_Release(&This->IMFByteStream_iface);
4191 static const IMFAttributesVtbl mfbytestream_attributes_vtbl =
4193 mfbytestream_attributes_QueryInterface,
4194 mfbytestream_attributes_AddRef,
4195 mfbytestream_attributes_Release,
4196 mfattributes_GetItem,
4197 mfattributes_GetItemType,
4198 mfattributes_CompareItem,
4199 mfattributes_Compare,
4200 mfattributes_GetUINT32,
4201 mfattributes_GetUINT64,
4202 mfattributes_GetDouble,
4203 mfattributes_GetGUID,
4204 mfattributes_GetStringLength,
4205 mfattributes_GetString,
4206 mfattributes_GetAllocatedString,
4207 mfattributes_GetBlobSize,
4208 mfattributes_GetBlob,
4209 mfattributes_GetAllocatedBlob,
4210 mfattributes_GetUnknown,
4211 mfattributes_SetItem,
4212 mfattributes_DeleteItem,
4213 mfattributes_DeleteAllItems,
4214 mfattributes_SetUINT32,
4215 mfattributes_SetUINT64,
4216 mfattributes_SetDouble,
4217 mfattributes_SetGUID,
4218 mfattributes_SetString,
4219 mfattributes_SetBlob,
4220 mfattributes_SetUnknown,
4221 mfattributes_LockStore,
4222 mfattributes_UnlockStore,
4223 mfattributes_GetCount,
4224 mfattributes_GetItemByIndex,
4225 mfattributes_CopyAllItems
4228 static HRESULT WINAPI bytestream_stream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4230 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4231 struct async_stream_op *op;
4232 LARGE_INTEGER position;
4233 IUnknown *object;
4234 HRESULT hr;
4236 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4237 return hr;
4239 op = impl_async_stream_op_from_IUnknown(object);
4241 EnterCriticalSection(&stream->cs);
4243 position.QuadPart = op->position;
4244 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4246 if (SUCCEEDED(hr = IStream_Read(stream->stream, op->u.dest, op->requested_length, &op->actual_length)))
4247 stream->position += op->actual_length;
4250 IMFAsyncResult_SetStatus(op->caller, hr);
4251 list_add_tail(&stream->pending, &op->entry);
4253 LeaveCriticalSection(&stream->cs);
4255 MFInvokeCallback(op->caller);
4257 return S_OK;
4260 static HRESULT WINAPI bytestream_stream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4262 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4263 struct async_stream_op *op;
4264 LARGE_INTEGER position;
4265 IUnknown *object;
4266 HRESULT hr;
4268 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4269 return hr;
4271 op = impl_async_stream_op_from_IUnknown(object);
4273 EnterCriticalSection(&stream->cs);
4275 position.QuadPart = op->position;
4276 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4278 if (SUCCEEDED(hr = IStream_Write(stream->stream, op->u.src, op->requested_length, &op->actual_length)))
4279 stream->position += op->actual_length;
4282 IMFAsyncResult_SetStatus(op->caller, hr);
4283 list_add_tail(&stream->pending, &op->entry);
4285 LeaveCriticalSection(&stream->cs);
4287 MFInvokeCallback(op->caller);
4289 return S_OK;
4292 static const IRtwqAsyncCallbackVtbl bytestream_stream_read_callback_vtbl =
4294 bytestream_callback_QueryInterface,
4295 bytestream_read_callback_AddRef,
4296 bytestream_read_callback_Release,
4297 bytestream_callback_GetParameters,
4298 bytestream_stream_read_callback_Invoke,
4301 static const IRtwqAsyncCallbackVtbl bytestream_stream_write_callback_vtbl =
4303 bytestream_callback_QueryInterface,
4304 bytestream_write_callback_AddRef,
4305 bytestream_write_callback_Release,
4306 bytestream_callback_GetParameters,
4307 bytestream_stream_write_callback_Invoke,
4310 /***********************************************************************
4311 * MFCreateMFByteStreamOnStream (mfplat.@)
4313 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4315 struct bytestream *object;
4316 LARGE_INTEGER position;
4317 STATSTG stat;
4318 HRESULT hr;
4320 TRACE("%p, %p.\n", stream, bytestream);
4322 object = heap_alloc_zero(sizeof(*object));
4323 if (!object)
4324 return E_OUTOFMEMORY;
4326 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4328 heap_free(object);
4329 return hr;
4332 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4333 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4334 object->read_callback.lpVtbl = &bytestream_stream_read_callback_vtbl;
4335 object->write_callback.lpVtbl = &bytestream_stream_write_callback_vtbl;
4336 InitializeCriticalSection(&object->cs);
4337 list_init(&object->pending);
4339 object->stream = stream;
4340 IStream_AddRef(object->stream);
4341 position.QuadPart = 0;
4342 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4344 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4346 if (stat.pwcsName)
4348 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4349 stat.pwcsName);
4350 CoTaskMemFree(stat.pwcsName);
4354 *bytestream = &object->IMFByteStream_iface;
4356 return S_OK;
4359 static HRESULT WINAPI bytestream_file_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4361 FIXME("%p, %p.\n", iface, result);
4363 return E_NOTIMPL;
4366 static HRESULT WINAPI bytestream_file_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4368 FIXME("%p, %p.\n", iface, result);
4370 return E_NOTIMPL;
4373 static const IRtwqAsyncCallbackVtbl bytestream_file_read_callback_vtbl =
4375 bytestream_callback_QueryInterface,
4376 bytestream_read_callback_AddRef,
4377 bytestream_read_callback_Release,
4378 bytestream_callback_GetParameters,
4379 bytestream_file_read_callback_Invoke,
4382 static const IRtwqAsyncCallbackVtbl bytestream_file_write_callback_vtbl =
4384 bytestream_callback_QueryInterface,
4385 bytestream_write_callback_AddRef,
4386 bytestream_write_callback_Release,
4387 bytestream_callback_GetParameters,
4388 bytestream_file_write_callback_Invoke,
4391 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4393 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4394 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4397 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4399 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4400 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4403 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4405 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4406 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4409 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4410 REFIID riid, void **obj)
4412 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4414 return E_NOTIMPL;
4417 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4419 bytestream_file_getservice_QueryInterface,
4420 bytestream_file_getservice_AddRef,
4421 bytestream_file_getservice_Release,
4422 bytestream_file_getservice_GetService,
4425 /***********************************************************************
4426 * MFCreateFile (mfplat.@)
4428 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4429 LPCWSTR url, IMFByteStream **bytestream)
4431 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4432 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4433 DWORD filesharemode = FILE_SHARE_READ;
4434 struct bytestream *object;
4435 FILETIME writetime;
4436 HANDLE file;
4437 HRESULT hr;
4439 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(url), bytestream);
4441 switch (accessmode)
4443 case MF_ACCESSMODE_READ:
4444 fileaccessmode = GENERIC_READ;
4445 capabilities |= MFBYTESTREAM_IS_READABLE;
4446 break;
4447 case MF_ACCESSMODE_WRITE:
4448 fileaccessmode = GENERIC_WRITE;
4449 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4450 break;
4451 case MF_ACCESSMODE_READWRITE:
4452 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4453 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4454 break;
4457 switch (openmode)
4459 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4460 filecreation_disposition = OPEN_EXISTING;
4461 break;
4462 case MF_OPENMODE_FAIL_IF_EXIST:
4463 filecreation_disposition = CREATE_NEW;
4464 break;
4465 case MF_OPENMODE_RESET_IF_EXIST:
4466 filecreation_disposition = TRUNCATE_EXISTING;
4467 break;
4468 case MF_OPENMODE_APPEND_IF_EXIST:
4469 filecreation_disposition = OPEN_ALWAYS;
4470 fileaccessmode |= FILE_APPEND_DATA;
4471 break;
4472 case MF_OPENMODE_DELETE_IF_EXIST:
4473 filecreation_disposition = CREATE_ALWAYS;
4474 break;
4477 if (flags & MF_FILEFLAGS_NOBUFFERING)
4478 fileattributes |= FILE_FLAG_NO_BUFFERING;
4480 /* Open HANDLE to file */
4481 file = CreateFileW(url, fileaccessmode, filesharemode, NULL,
4482 filecreation_disposition, fileattributes, 0);
4484 if(file == INVALID_HANDLE_VALUE)
4485 return HRESULT_FROM_WIN32(GetLastError());
4487 object = heap_alloc_zero(sizeof(*object));
4488 if (!object)
4490 CloseHandle(file);
4491 return E_OUTOFMEMORY;
4494 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4496 CloseHandle(file);
4497 heap_free(object);
4498 return hr;
4500 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4501 object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
4502 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4503 object->read_callback.lpVtbl = &bytestream_file_read_callback_vtbl;
4504 object->write_callback.lpVtbl = &bytestream_file_write_callback_vtbl;
4505 InitializeCriticalSection(&object->cs);
4506 list_init(&object->pending);
4507 object->capabilities = capabilities;
4508 object->hfile = file;
4510 if (GetFileTime(file, NULL, NULL, &writetime))
4512 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4513 (const UINT8 *)&writetime, sizeof(writetime));
4516 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, url);
4518 *bytestream = &object->IMFByteStream_iface;
4520 return S_OK;
4523 struct bytestream_wrapper
4525 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4526 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4527 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4528 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4529 IMFSampleOutputStream IMFSampleOutputStream_iface;
4530 IPropertyStore IPropertyStore_iface;
4531 IMFByteStream IMFByteStream_iface;
4532 IMFAttributes IMFAttributes_iface;
4533 LONG refcount;
4535 IMFByteStreamCacheControl *cache_control;
4536 IMFByteStreamBuffering *stream_buffering;
4537 IMFMediaEventGenerator *event_generator;
4538 IMFByteStreamTimeSeek *time_seek;
4539 IMFSampleOutputStream *sample_output;
4540 IPropertyStore *propstore;
4541 IMFByteStream *stream;
4542 IMFAttributes *attributes;
4543 BOOL is_closed;
4546 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4548 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4551 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4553 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4556 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4558 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4561 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4563 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4566 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4568 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4571 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4573 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4576 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4578 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4581 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4583 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4586 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4588 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4590 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4592 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4593 IsEqualIID(riid, &IID_IUnknown))
4595 *out = &wrapper->IMFByteStream_iface;
4597 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4599 *out = &wrapper->IMFByteStreamCacheControl_iface;
4601 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4603 *out = &wrapper->IMFByteStreamBuffering_iface;
4605 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4607 *out = &wrapper->IMFMediaEventGenerator_iface;
4609 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4611 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4613 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4615 *out = &wrapper->IMFSampleOutputStream_iface;
4617 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4619 *out = &wrapper->IPropertyStore_iface;
4621 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4623 *out = &wrapper->IMFAttributes_iface;
4625 else
4627 WARN("Unsupported %s.\n", debugstr_guid(riid));
4628 *out = NULL;
4629 return E_NOINTERFACE;
4632 IUnknown_AddRef((IUnknown *)*out);
4633 return S_OK;
4636 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4638 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4639 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4641 TRACE("%p, refcount %d.\n", iface, refcount);
4643 return refcount;
4646 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4648 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4649 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4651 TRACE("%p, refcount %d.\n", iface, refcount);
4653 if (!refcount)
4655 if (wrapper->cache_control)
4656 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4657 if (wrapper->stream_buffering)
4658 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4659 if (wrapper->event_generator)
4660 IMFMediaEventGenerator_Release(wrapper->event_generator);
4661 if (wrapper->time_seek)
4662 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4663 if (wrapper->sample_output)
4664 IMFSampleOutputStream_Release(wrapper->sample_output);
4665 if (wrapper->propstore)
4666 IPropertyStore_Release(wrapper->propstore);
4667 if (wrapper->attributes)
4668 IMFAttributes_Release(wrapper->attributes);
4669 IMFByteStream_Release(wrapper->stream);
4670 heap_free(wrapper);
4673 return refcount;
4676 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4678 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4680 TRACE("%p, %p.\n", iface, capabilities);
4682 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4683 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4686 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4688 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4690 TRACE("%p, %p.\n", iface, length);
4692 if (wrapper->is_closed)
4693 return MF_E_INVALIDREQUEST;
4695 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4696 IMFByteStream_GetLength(wrapper->stream, length);
4699 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4701 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4703 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4705 if (wrapper->is_closed)
4706 return MF_E_INVALIDREQUEST;
4708 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4709 IMFByteStream_SetLength(wrapper->stream, length);
4712 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4714 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4716 TRACE("%p, %p.\n", iface, position);
4718 if (wrapper->is_closed)
4719 return MF_E_INVALIDREQUEST;
4721 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4722 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4725 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4727 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4729 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4731 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4732 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4735 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4737 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4739 TRACE("%p, %p.\n", iface, eos);
4741 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4742 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4745 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4747 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4749 TRACE("%p, %p, %u, %p.\n", iface, data, count, byte_read);
4751 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4752 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4755 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4756 IMFAsyncCallback *callback, IUnknown *state)
4758 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4760 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4762 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4763 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4766 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4768 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4770 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4772 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4773 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4776 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4778 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4780 TRACE("%p, %p, %u, %p.\n", iface, data, count, written);
4782 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4783 IMFByteStream_Write(wrapper->stream, data, count, written);
4786 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4787 IMFAsyncCallback *callback, IUnknown *state)
4789 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4791 TRACE("%p, %p, %u, %p, %p.\n", iface, data, size, callback, state);
4793 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4794 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4797 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4799 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4801 TRACE("%p, %p, %p.\n", iface, result, written);
4803 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4804 IMFByteStream_EndWrite(wrapper->stream, result, written);
4807 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4808 DWORD flags, QWORD *current)
4810 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4812 TRACE("%p, %u, %s, %#x, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4814 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4815 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
4818 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
4820 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4822 TRACE("%p\n", iface);
4824 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
4827 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
4829 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4831 TRACE("%p\n", iface);
4833 wrapper->is_closed = TRUE;
4835 return S_OK;
4838 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
4840 bytestream_wrapper_QueryInterface,
4841 bytestream_wrapper_AddRef,
4842 bytestream_wrapper_Release,
4843 bytestream_wrapper_GetCapabilities,
4844 bytestream_wrapper_GetLength,
4845 bytestream_wrapper_SetLength,
4846 bytestream_wrapper_GetCurrentPosition,
4847 bytestream_wrapper_SetCurrentPosition,
4848 bytestream_wrapper_IsEndOfStream,
4849 bytestream_wrapper_Read,
4850 bytestream_wrapper_BeginRead,
4851 bytestream_wrapper_EndRead,
4852 bytestream_wrapper_Write,
4853 bytestream_wrapper_BeginWrite,
4854 bytestream_wrapper_EndWrite,
4855 bytestream_wrapper_Seek,
4856 bytestream_wrapper_Flush,
4857 bytestream_wrapper_Close,
4860 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
4861 REFIID riid, void **obj)
4863 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4864 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4867 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
4869 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4870 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4873 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
4875 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4876 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4879 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
4881 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
4883 TRACE("%p.\n", iface);
4885 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
4888 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
4890 bytestream_wrapper_cache_control_QueryInterface,
4891 bytestream_wrapper_cache_control_AddRef,
4892 bytestream_wrapper_cache_control_Release,
4893 bytestream_wrapper_cache_control_StopBackgroundTransfer,
4896 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
4897 REFIID riid, void **obj)
4899 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4900 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4903 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
4905 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4906 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4909 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
4911 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4912 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4915 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
4916 MFBYTESTREAM_BUFFERING_PARAMS *params)
4918 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4920 TRACE("%p, %p.\n", iface, params);
4922 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
4925 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
4926 BOOL enable)
4928 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4930 TRACE("%p, %d.\n", iface, enable);
4932 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
4935 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
4937 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
4939 TRACE("%p.\n", iface);
4941 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
4944 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
4946 bytestream_wrapper_buffering_QueryInterface,
4947 bytestream_wrapper_buffering_AddRef,
4948 bytestream_wrapper_buffering_Release,
4949 bytestream_wrapper_buffering_SetBufferingParams,
4950 bytestream_wrapper_buffering_EnableBuffering,
4951 bytestream_wrapper_buffering_StopBuffering,
4954 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
4955 REFIID riid, void **obj)
4957 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4958 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
4961 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
4963 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4964 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
4967 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
4969 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4970 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
4973 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
4975 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4977 TRACE("%p, %p.\n", iface, result);
4979 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
4982 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
4984 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4986 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4988 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
4991 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
4992 QWORD *stop_time, QWORD *duration)
4994 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
4996 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
4998 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
5001 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
5003 bytestream_wrapper_timeseek_QueryInterface,
5004 bytestream_wrapper_timeseek_AddRef,
5005 bytestream_wrapper_timeseek_Release,
5006 bytestream_wrapper_timeseek_IsTimeSeekSupported,
5007 bytestream_wrapper_timeseek_TimeSeek,
5008 bytestream_wrapper_timeseek_GetTimeSeekResult,
5011 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
5013 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5014 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5017 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
5019 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5020 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5023 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
5025 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5026 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5029 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
5031 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5033 TRACE("%p, %#x, %p.\n", iface, flags, event);
5035 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
5038 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
5040 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5042 TRACE("%p, %p, %p.\n", iface, callback, state);
5044 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
5047 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5049 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5051 TRACE("%p, %p, %p.\n", iface, result, event);
5053 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
5056 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
5057 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
5059 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5061 TRACE("%p, %d, %s, %#x, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
5063 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
5066 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
5068 bytestream_wrapper_events_QueryInterface,
5069 bytestream_wrapper_events_AddRef,
5070 bytestream_wrapper_events_Release,
5071 bytestream_wrapper_events_GetEvent,
5072 bytestream_wrapper_events_BeginGetEvent,
5073 bytestream_wrapper_events_EndGetEvent,
5074 bytestream_wrapper_events_QueueEvent,
5077 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
5079 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5080 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5083 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
5085 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5086 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5089 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
5091 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5092 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5095 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
5096 IMFAsyncCallback *callback, IUnknown *state)
5098 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5100 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
5102 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
5105 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
5107 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5109 TRACE("%p, %p.\n", iface, result);
5111 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
5114 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
5116 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5118 TRACE("%p.\n", iface);
5120 return IMFSampleOutputStream_Close(wrapper->sample_output);
5123 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5125 bytestream_wrapper_sample_output_QueryInterface,
5126 bytestream_wrapper_sample_output_AddRef,
5127 bytestream_wrapper_sample_output_Release,
5128 bytestream_wrapper_sample_output_BeginWriteSample,
5129 bytestream_wrapper_sample_output_EndWriteSample,
5130 bytestream_wrapper_sample_output_Close,
5133 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5135 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5136 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5139 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5141 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5142 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5145 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5147 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5148 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5151 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5153 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5155 TRACE("%p, %p.\n", iface, count);
5157 return IPropertyStore_GetCount(wrapper->propstore, count);
5160 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5162 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5164 TRACE("%p, %u, %p.\n", iface, prop, key);
5166 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5169 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5171 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5173 TRACE("%p, %p, %p.\n", iface, key, value);
5175 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5178 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5179 const PROPVARIANT *value)
5181 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5183 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5185 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5188 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5190 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5192 TRACE("%p.\n", iface);
5194 return IPropertyStore_Commit(wrapper->propstore);
5197 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5199 bytestream_wrapper_propstore_QueryInterface,
5200 bytestream_wrapper_propstore_AddRef,
5201 bytestream_wrapper_propstore_Release,
5202 bytestream_wrapper_propstore_GetCount,
5203 bytestream_wrapper_propstore_GetAt,
5204 bytestream_wrapper_propstore_GetValue,
5205 bytestream_wrapper_propstore_SetValue,
5206 bytestream_wrapper_propstore_Commit,
5209 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5211 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5212 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5215 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5217 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5218 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5221 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5223 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5224 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5227 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5229 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5231 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5233 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5236 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5238 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5240 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5242 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5245 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5246 REFPROPVARIANT value, BOOL *result)
5248 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5250 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5252 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5255 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5256 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5258 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5260 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5262 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5265 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5267 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5269 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5271 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5274 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5276 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5278 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5280 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5283 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5285 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5287 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5289 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5292 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5294 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5296 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5298 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5301 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5303 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5305 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5307 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5310 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5311 UINT32 size, UINT32 *length)
5313 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5315 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5317 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5320 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5322 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5324 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5326 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5329 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5331 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5333 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5335 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5338 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5339 UINT32 bufsize, UINT32 *blobsize)
5341 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5343 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5345 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5348 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5350 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5352 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5354 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5357 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5359 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5361 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5363 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5366 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5368 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5370 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5372 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5375 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5377 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5379 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5381 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5384 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5386 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5388 TRACE("%p.\n", iface);
5390 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5393 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5395 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5397 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5399 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5402 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5404 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5406 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5408 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5411 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5413 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5415 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5417 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5420 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5422 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5424 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5426 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5429 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5431 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5433 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5435 return IMFAttributes_SetString(wrapper->attributes, key, value);
5438 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5440 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5442 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5444 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5447 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5449 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5451 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5453 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5456 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5458 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5460 TRACE("%p.\n", iface);
5462 return IMFAttributes_LockStore(wrapper->attributes);
5465 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5467 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5469 TRACE("%p.\n", iface);
5471 return IMFAttributes_UnlockStore(wrapper->attributes);
5474 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5476 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5478 TRACE("%p, %p.\n", iface, count);
5480 return IMFAttributes_GetCount(wrapper->attributes, count);
5483 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5485 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5487 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5489 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5492 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5494 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5496 TRACE("%p, %p.\n", iface, dest);
5498 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5501 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5503 bytestream_wrapper_attributes_QueryInterface,
5504 bytestream_wrapper_attributes_AddRef,
5505 bytestream_wrapper_attributes_Release,
5506 bytestream_wrapper_attributes_GetItem,
5507 bytestream_wrapper_attributes_GetItemType,
5508 bytestream_wrapper_attributes_CompareItem,
5509 bytestream_wrapper_attributes_Compare,
5510 bytestream_wrapper_attributes_GetUINT32,
5511 bytestream_wrapper_attributes_GetUINT64,
5512 bytestream_wrapper_attributes_GetDouble,
5513 bytestream_wrapper_attributes_GetGUID,
5514 bytestream_wrapper_attributes_GetStringLength,
5515 bytestream_wrapper_attributes_GetString,
5516 bytestream_wrapper_attributes_GetAllocatedString,
5517 bytestream_wrapper_attributes_GetBlobSize,
5518 bytestream_wrapper_attributes_GetBlob,
5519 bytestream_wrapper_attributes_GetAllocatedBlob,
5520 bytestream_wrapper_attributes_GetUnknown,
5521 bytestream_wrapper_attributes_SetItem,
5522 bytestream_wrapper_attributes_DeleteItem,
5523 bytestream_wrapper_attributes_DeleteAllItems,
5524 bytestream_wrapper_attributes_SetUINT32,
5525 bytestream_wrapper_attributes_SetUINT64,
5526 bytestream_wrapper_attributes_SetDouble,
5527 bytestream_wrapper_attributes_SetGUID,
5528 bytestream_wrapper_attributes_SetString,
5529 bytestream_wrapper_attributes_SetBlob,
5530 bytestream_wrapper_attributes_SetUnknown,
5531 bytestream_wrapper_attributes_LockStore,
5532 bytestream_wrapper_attributes_UnlockStore,
5533 bytestream_wrapper_attributes_GetCount,
5534 bytestream_wrapper_attributes_GetItemByIndex,
5535 bytestream_wrapper_attributes_CopyAllItems
5538 /***********************************************************************
5539 * MFCreateMFByteStreamWrapper (mfplat.@)
5541 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5543 struct bytestream_wrapper *object;
5545 TRACE("%p, %p.\n", stream, wrapper);
5547 object = heap_alloc_zero(sizeof(*object));
5548 if (!object)
5549 return E_OUTOFMEMORY;
5551 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5552 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5553 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5554 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5555 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5556 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5557 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5558 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5560 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5561 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5562 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5563 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5564 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5565 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5566 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5568 object->stream = stream;
5569 IMFByteStream_AddRef(object->stream);
5571 object->refcount = 1;
5573 *wrapper = &object->IMFByteStream_iface;
5575 return S_OK;
5578 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5580 if(IsEqualGUID(riid, &IID_IUnknown)) {
5581 TRACE("(IID_IUnknown %p)\n", ppv);
5582 *ppv = iface;
5583 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5584 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5585 *ppv = iface;
5586 }else {
5587 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5588 *ppv = NULL;
5589 return E_NOINTERFACE;
5592 IUnknown_AddRef((IUnknown*)*ppv);
5593 return S_OK;
5596 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5598 TRACE("\n");
5599 return 2;
5602 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5604 TRACE("\n");
5605 return 1;
5608 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5609 const WCHAR *selector, CLSID *clsid)
5611 FIXME("(%d %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5612 return E_NOTIMPL;
5615 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5616 DWORD index, WCHAR **selector, CLSID *clsid)
5618 FIXME("(%d %d %p %p)\n", plugin_type, index, selector, clsid);
5619 return E_NOTIMPL;
5622 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5623 const WCHAR *selector, const CLSID *clsid)
5625 FIXME("(%d %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5626 return E_NOTIMPL;
5629 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5631 FIXME("(%d %s)\n", plugin_type, debugstr_guid(clsid));
5632 return E_NOTIMPL;
5635 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5637 FIXME("(%d %d %p)\n", plugin_type, index, clsid);
5638 return E_NOTIMPL;
5641 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5643 FIXME("(%d %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5644 return E_NOTIMPL;
5647 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5648 MFPluginControl_QueryInterface,
5649 MFPluginControl_AddRef,
5650 MFPluginControl_Release,
5651 MFPluginControl_GetPreferredClsid,
5652 MFPluginControl_GetPreferredClsidByIndex,
5653 MFPluginControl_SetPreferredClsid,
5654 MFPluginControl_IsDisabled,
5655 MFPluginControl_GetDisabledByIndex,
5656 MFPluginControl_SetDisabled
5659 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5661 /***********************************************************************
5662 * MFGetPluginControl (mfplat.@)
5664 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5666 TRACE("(%p)\n", ret);
5668 *ret = &plugin_control;
5669 return S_OK;
5672 enum resolved_object_origin
5674 OBJECT_FROM_BYTESTREAM,
5675 OBJECT_FROM_URL,
5678 struct resolver_queued_result
5680 struct list entry;
5681 IUnknown *object;
5682 MF_OBJECT_TYPE obj_type;
5683 HRESULT hr;
5684 IRtwqAsyncResult *inner_result;
5685 enum resolved_object_origin origin;
5688 struct resolver_cancel_object
5690 IUnknown IUnknown_iface;
5691 LONG refcount;
5692 union
5694 IUnknown *handler;
5695 IMFByteStreamHandler *stream_handler;
5696 IMFSchemeHandler *scheme_handler;
5697 } u;
5698 IUnknown *cancel_cookie;
5699 enum resolved_object_origin origin;
5702 struct source_resolver
5704 IMFSourceResolver IMFSourceResolver_iface;
5705 LONG refcount;
5706 IRtwqAsyncCallback stream_callback;
5707 IRtwqAsyncCallback url_callback;
5708 CRITICAL_SECTION cs;
5709 struct list pending;
5712 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5714 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5717 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5719 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5722 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5724 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5727 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5728 IRtwqAsyncResult *result)
5730 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5731 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5732 struct resolver_queued_result *queued_result;
5733 union
5735 IUnknown *handler;
5736 IMFByteStreamHandler *stream_handler;
5737 IMFSchemeHandler *scheme_handler;
5738 } handler;
5740 if (!(queued_result = heap_alloc_zero(sizeof(*queued_result))))
5741 return E_OUTOFMEMORY;
5743 queued_result->origin = origin;
5745 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5747 switch (origin)
5749 case OBJECT_FROM_BYTESTREAM:
5750 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5751 &queued_result->obj_type, &queued_result->object);
5752 break;
5753 case OBJECT_FROM_URL:
5754 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5755 &queued_result->obj_type, &queued_result->object);
5756 break;
5757 default:
5758 queued_result->hr = E_FAIL;
5761 IUnknown_Release(handler.handler);
5763 if (data->hEvent)
5765 queued_result->inner_result = inner_result;
5766 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5769 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5770 EnterCriticalSection(&resolver->cs);
5771 list_add_tail(&resolver->pending, &queued_result->entry);
5772 LeaveCriticalSection(&resolver->cs);
5774 if (data->hEvent)
5775 SetEvent(data->hEvent);
5776 else
5778 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5779 IRtwqAsyncResult *caller_result;
5781 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5783 RtwqInvokeCallback(caller_result);
5784 IRtwqAsyncResult_Release(caller_result);
5788 return S_OK;
5791 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5793 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5796 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5798 if (IsEqualIID(riid, &IID_IUnknown))
5800 *obj = iface;
5801 IUnknown_AddRef(iface);
5802 return S_OK;
5805 *obj = NULL;
5806 return E_NOINTERFACE;
5809 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
5811 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5812 return InterlockedIncrement(&object->refcount);
5815 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
5817 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5818 ULONG refcount = InterlockedDecrement(&object->refcount);
5820 if (!refcount)
5822 if (object->cancel_cookie)
5823 IUnknown_Release(object->cancel_cookie);
5824 IUnknown_Release(object->u.handler);
5825 heap_free(object);
5828 return refcount;
5831 static const IUnknownVtbl resolver_cancel_object_vtbl =
5833 resolver_cancel_object_QueryInterface,
5834 resolver_cancel_object_AddRef,
5835 resolver_cancel_object_Release,
5838 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
5840 if (!iface)
5841 return NULL;
5843 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
5844 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
5847 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
5848 IUnknown *cancel_cookie, IUnknown **cancel_object)
5850 struct resolver_cancel_object *object;
5852 object = heap_alloc_zero(sizeof(*object));
5853 if (!object)
5854 return E_OUTOFMEMORY;
5856 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
5857 object->refcount = 1;
5858 object->u.handler = handler;
5859 IUnknown_AddRef(object->u.handler);
5860 object->cancel_cookie = cancel_cookie;
5861 IUnknown_AddRef(object->cancel_cookie);
5862 object->origin = origin;
5864 *cancel_object = &object->IUnknown_iface;
5866 return S_OK;
5869 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
5871 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
5872 IsEqualIID(riid, &IID_IUnknown))
5874 *obj = iface;
5875 IRtwqAsyncCallback_AddRef(iface);
5876 return S_OK;
5879 *obj = NULL;
5880 return E_NOINTERFACE;
5883 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
5885 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5886 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5889 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
5891 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5892 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5895 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
5897 return E_NOTIMPL;
5900 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5902 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
5904 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
5907 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
5909 source_resolver_callback_QueryInterface,
5910 source_resolver_callback_stream_AddRef,
5911 source_resolver_callback_stream_Release,
5912 source_resolver_callback_GetParameters,
5913 source_resolver_callback_stream_Invoke,
5916 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
5918 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5919 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
5922 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
5924 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5925 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
5928 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
5930 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
5932 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
5935 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
5937 source_resolver_callback_QueryInterface,
5938 source_resolver_callback_url_AddRef,
5939 source_resolver_callback_url_Release,
5940 source_resolver_callback_GetParameters,
5941 source_resolver_callback_url_Invoke,
5944 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
5946 unsigned int j = 0, name_length, type;
5947 HRESULT hr = E_FAIL;
5948 WCHAR clsidW[39];
5949 CLSID clsid;
5951 name_length = ARRAY_SIZE(clsidW);
5952 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
5954 if (type == REG_SZ)
5956 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
5958 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
5959 if (SUCCEEDED(hr))
5960 break;
5964 name_length = ARRAY_SIZE(clsidW);
5967 return hr;
5970 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
5971 IMFByteStreamHandler **handler)
5973 static const char streamhandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers";
5974 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
5975 IMFAttributes *attributes;
5976 const WCHAR *url_ext;
5977 WCHAR *mimeW = NULL;
5978 HRESULT hr = E_FAIL;
5979 unsigned int i, j;
5980 UINT32 length;
5982 *handler = NULL;
5984 /* MIME type */
5985 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
5987 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
5988 IMFAttributes_Release(attributes);
5991 /* Extension */
5992 url_ext = url ? wcsrchr(url, '.') : NULL;
5994 if (!url_ext && !mimeW)
5996 CoTaskMemFree(mimeW);
5997 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6000 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6002 struct local_handler *local_handler;
6004 EnterCriticalSection(&local_handlers_section);
6006 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
6008 if ((mimeW && !lstrcmpiW(mimeW, local_handler->u.bytestream.mime))
6009 || (url_ext && !lstrcmpiW(url_ext, local_handler->u.bytestream.extension)))
6011 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
6012 (void **)handler)))
6013 break;
6017 LeaveCriticalSection(&local_handlers_section);
6019 if (*handler)
6020 return hr;
6023 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
6025 const WCHAR *namesW[2] = { mimeW, url_ext };
6026 HKEY hkey, hkey_handler;
6028 if (RegOpenKeyA(hkey_roots[i], streamhandlerspath, &hkey))
6029 continue;
6031 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6033 if (!namesW[j])
6034 continue;
6036 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6038 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6039 RegCloseKey(hkey_handler);
6042 if (SUCCEEDED(hr))
6043 break;
6046 RegCloseKey(hkey);
6048 if (SUCCEEDED(hr))
6049 break;
6052 if (FAILED(hr))
6054 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6055 hr = CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6058 CoTaskMemFree(mimeW);
6059 return hr;
6062 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6064 static const char schemehandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers";
6065 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6066 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6067 unsigned int i;
6069 TRACE("%s, %#x, %p.\n", debugstr_w(scheme), flags, handler);
6071 *handler = NULL;
6073 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6075 struct local_handler *local_handler;
6077 EnterCriticalSection(&local_handlers_section);
6079 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6081 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6083 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6084 (void **)handler)))
6085 break;
6089 LeaveCriticalSection(&local_handlers_section);
6091 if (*handler)
6092 return hr;
6095 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6097 HKEY hkey, hkey_handler;
6099 hr = MF_E_UNSUPPORTED_SCHEME;
6101 if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey))
6102 continue;
6104 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6106 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6107 RegCloseKey(hkey_handler);
6110 RegCloseKey(hkey);
6112 if (SUCCEEDED(hr))
6113 break;
6116 return hr;
6119 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6121 static const WCHAR fileschemeW[] = L"file:";
6122 const WCHAR *ptr = url;
6123 unsigned int len;
6124 WCHAR *scheme;
6125 HRESULT hr;
6127 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6128 while (*ptr)
6130 WCHAR ch = towlower(*ptr);
6132 if (*ptr == '*' && ptr == url)
6134 ptr++;
6135 break;
6137 else if (!(*ptr >= '0' && *ptr <= '9') &&
6138 !(ch >= 'a' && ch <= 'z') &&
6139 *ptr != '+' && *ptr != '-' && *ptr != '.')
6141 break;
6144 ptr++;
6147 /* Schemes must end with a ':', if not found try "file:" */
6148 if (ptr == url || *ptr != ':')
6150 url = fileschemeW;
6151 ptr = fileschemeW + ARRAY_SIZE(fileschemeW) - 1;
6154 len = ptr - url;
6155 scheme = heap_alloc((len + 1) * sizeof(WCHAR));
6156 if (!scheme)
6157 return E_OUTOFMEMORY;
6159 memcpy(scheme, url, len * sizeof(WCHAR));
6160 scheme[len] = 0;
6162 hr = resolver_create_scheme_handler(scheme, flags, handler);
6163 if (FAILED(hr) && url != fileschemeW)
6164 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6166 heap_free(scheme);
6168 return hr;
6171 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6172 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6174 struct resolver_queued_result *queued_result = NULL, *iter;
6175 IUnknown *object;
6176 HRESULT hr;
6178 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6179 return hr;
6181 EnterCriticalSection(&resolver->cs);
6183 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6185 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6187 list_remove(&iter->entry);
6188 queued_result = iter;
6189 break;
6193 LeaveCriticalSection(&resolver->cs);
6195 IUnknown_Release(object);
6197 if (queued_result)
6199 *out = queued_result->object;
6200 *obj_type = queued_result->obj_type;
6201 hr = queued_result->hr;
6202 if (queued_result->inner_result)
6203 IRtwqAsyncResult_Release(queued_result->inner_result);
6204 heap_free(queued_result);
6206 else
6207 hr = E_UNEXPECTED;
6209 return hr;
6212 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6214 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6216 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6218 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6219 IsEqualIID(riid, &IID_IUnknown))
6221 *obj = &resolver->IMFSourceResolver_iface;
6223 else
6225 *obj = NULL;
6226 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6227 return E_NOINTERFACE;
6230 IUnknown_AddRef((IUnknown *)*obj);
6231 return S_OK;
6234 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6236 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6237 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6239 TRACE("%p, refcount %d.\n", iface, refcount);
6241 return refcount;
6244 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6246 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6247 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6248 struct resolver_queued_result *result, *result2;
6250 TRACE("%p, refcount %d.\n", iface, refcount);
6252 if (!refcount)
6254 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6256 if (result->object)
6257 IUnknown_Release(result->object);
6258 list_remove(&result->entry);
6259 heap_free(result);
6261 DeleteCriticalSection(&resolver->cs);
6262 heap_free(resolver);
6265 return refcount;
6268 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6269 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6271 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6272 IMFSchemeHandler *handler;
6273 IRtwqAsyncResult *result;
6274 RTWQASYNCRESULT *data;
6275 HRESULT hr;
6277 TRACE("%p, %s, %#x, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6279 if (!url || !obj_type || !object)
6280 return E_POINTER;
6282 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6283 return hr;
6285 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6286 IMFSchemeHandler_Release(handler);
6287 if (FAILED(hr))
6288 return hr;
6290 data = (RTWQASYNCRESULT *)result;
6291 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6293 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6294 (IUnknown *)result);
6295 if (FAILED(hr))
6297 IRtwqAsyncResult_Release(result);
6298 return hr;
6301 WaitForSingleObject(data->hEvent, INFINITE);
6303 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6304 IRtwqAsyncResult_Release(result);
6306 return hr;
6309 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6310 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6312 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6313 IMFByteStreamHandler *handler;
6314 IRtwqAsyncResult *result;
6315 RTWQASYNCRESULT *data;
6316 HRESULT hr;
6318 TRACE("%p, %p, %s, %#x, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6320 if (!stream || !obj_type || !object)
6321 return E_POINTER;
6323 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6324 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6326 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6327 IMFByteStreamHandler_Release(handler);
6328 if (FAILED(hr))
6329 return hr;
6331 data = (RTWQASYNCRESULT *)result;
6332 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6334 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6335 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6336 if (FAILED(hr))
6338 IRtwqAsyncResult_Release(result);
6339 return hr;
6342 WaitForSingleObject(data->hEvent, INFINITE);
6344 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6345 IRtwqAsyncResult_Release(result);
6347 return hr;
6350 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6351 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6353 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6354 IMFSchemeHandler *handler;
6355 IUnknown *inner_cookie = NULL;
6356 IRtwqAsyncResult *result;
6357 HRESULT hr;
6359 TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6361 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6362 return hr;
6364 if (cancel_cookie)
6365 *cancel_cookie = NULL;
6367 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6368 IMFSchemeHandler_Release(handler);
6369 if (FAILED(hr))
6370 return hr;
6372 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6373 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6375 if (SUCCEEDED(hr) && inner_cookie)
6376 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6378 IRtwqAsyncResult_Release(result);
6380 return hr;
6383 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6384 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6386 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6388 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6390 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6393 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6394 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6395 IUnknown *state)
6397 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6398 IMFByteStreamHandler *handler;
6399 IUnknown *inner_cookie = NULL;
6400 IRtwqAsyncResult *result;
6401 HRESULT hr;
6403 TRACE("%p, %p, %s, %#x, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6404 callback, state);
6406 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6407 return hr;
6409 if (cancel_cookie)
6410 *cancel_cookie = NULL;
6412 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6413 IMFByteStreamHandler_Release(handler);
6414 if (FAILED(hr))
6415 return hr;
6417 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6418 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6420 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6421 if (SUCCEEDED(hr) && inner_cookie)
6422 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6424 IRtwqAsyncResult_Release(result);
6426 return hr;
6429 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6430 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6432 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6434 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6436 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6439 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6441 struct resolver_cancel_object *object;
6442 HRESULT hr;
6444 TRACE("%p, %p.\n", iface, cancel_cookie);
6446 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6447 return E_UNEXPECTED;
6449 switch (object->origin)
6451 case OBJECT_FROM_BYTESTREAM:
6452 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6453 break;
6454 case OBJECT_FROM_URL:
6455 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6456 break;
6457 default:
6458 hr = E_UNEXPECTED;
6461 return hr;
6464 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6466 source_resolver_QueryInterface,
6467 source_resolver_AddRef,
6468 source_resolver_Release,
6469 source_resolver_CreateObjectFromURL,
6470 source_resolver_CreateObjectFromByteStream,
6471 source_resolver_BeginCreateObjectFromURL,
6472 source_resolver_EndCreateObjectFromURL,
6473 source_resolver_BeginCreateObjectFromByteStream,
6474 source_resolver_EndCreateObjectFromByteStream,
6475 source_resolver_CancelObjectCreation,
6478 /***********************************************************************
6479 * MFCreateSourceResolver (mfplat.@)
6481 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6483 struct source_resolver *object;
6485 TRACE("%p\n", resolver);
6487 if (!resolver)
6488 return E_POINTER;
6490 object = heap_alloc_zero(sizeof(*object));
6491 if (!object)
6492 return E_OUTOFMEMORY;
6494 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6495 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6496 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6497 object->refcount = 1;
6498 list_init(&object->pending);
6499 InitializeCriticalSection(&object->cs);
6501 *resolver = &object->IMFSourceResolver_iface;
6503 return S_OK;
6506 struct media_event
6508 struct attributes attributes;
6509 IMFMediaEvent IMFMediaEvent_iface;
6511 MediaEventType type;
6512 GUID extended_type;
6513 HRESULT status;
6514 PROPVARIANT value;
6517 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6519 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6522 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6524 struct media_event *event = impl_from_IMFMediaEvent(iface);
6526 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6528 if(IsEqualGUID(riid, &IID_IUnknown) ||
6529 IsEqualGUID(riid, &IID_IMFAttributes) ||
6530 IsEqualGUID(riid, &IID_IMFMediaEvent))
6532 *out = &event->IMFMediaEvent_iface;
6534 else
6536 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6537 *out = NULL;
6538 return E_NOINTERFACE;
6541 IUnknown_AddRef((IUnknown*)*out);
6542 return S_OK;
6545 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6547 struct media_event *event = impl_from_IMFMediaEvent(iface);
6548 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6550 TRACE("%p, refcount %u.\n", iface, refcount);
6552 return refcount;
6555 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6557 struct media_event *event = impl_from_IMFMediaEvent(iface);
6558 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6560 TRACE("%p, refcount %u.\n", iface, refcount);
6562 if (!refcount)
6564 clear_attributes_object(&event->attributes);
6565 PropVariantClear(&event->value);
6566 heap_free(event);
6569 return refcount;
6572 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6574 struct media_event *event = impl_from_IMFMediaEvent(iface);
6576 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6578 return attributes_GetItem(&event->attributes, key, value);
6581 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6583 struct media_event *event = impl_from_IMFMediaEvent(iface);
6585 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6587 return attributes_GetItemType(&event->attributes, key, type);
6590 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6592 struct media_event *event = impl_from_IMFMediaEvent(iface);
6594 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6596 return attributes_CompareItem(&event->attributes, key, value, result);
6599 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6600 BOOL *result)
6602 struct media_event *event = impl_from_IMFMediaEvent(iface);
6604 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6606 return attributes_Compare(&event->attributes, attrs, type, result);
6609 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6611 struct media_event *event = impl_from_IMFMediaEvent(iface);
6613 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6615 return attributes_GetUINT32(&event->attributes, key, value);
6618 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6620 struct media_event *event = impl_from_IMFMediaEvent(iface);
6622 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6624 return attributes_GetUINT64(&event->attributes, key, value);
6627 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6629 struct media_event *event = impl_from_IMFMediaEvent(iface);
6631 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6633 return attributes_GetDouble(&event->attributes, key, value);
6636 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6638 struct media_event *event = impl_from_IMFMediaEvent(iface);
6640 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6642 return attributes_GetGUID(&event->attributes, key, value);
6645 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6647 struct media_event *event = impl_from_IMFMediaEvent(iface);
6649 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6651 return attributes_GetStringLength(&event->attributes, key, length);
6654 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6655 UINT32 size, UINT32 *length)
6657 struct media_event *event = impl_from_IMFMediaEvent(iface);
6659 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6661 return attributes_GetString(&event->attributes, key, value, size, length);
6664 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6665 WCHAR **value, UINT32 *length)
6667 struct media_event *event = impl_from_IMFMediaEvent(iface);
6669 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6671 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6674 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6676 struct media_event *event = impl_from_IMFMediaEvent(iface);
6678 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
6680 return attributes_GetBlobSize(&event->attributes, key, size);
6683 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
6684 UINT32 bufsize, UINT32 *blobsize)
6686 struct media_event *event = impl_from_IMFMediaEvent(iface);
6688 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
6690 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
6693 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
6695 struct media_event *event = impl_from_IMFMediaEvent(iface);
6697 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
6699 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
6702 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
6704 struct media_event *event = impl_from_IMFMediaEvent(iface);
6706 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
6708 return attributes_GetUnknown(&event->attributes, key, riid, out);
6711 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
6713 struct media_event *event = impl_from_IMFMediaEvent(iface);
6715 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
6717 return attributes_SetItem(&event->attributes, key, value);
6720 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
6722 struct media_event *event = impl_from_IMFMediaEvent(iface);
6724 TRACE("%p, %s.\n", iface, debugstr_attr(key));
6726 return attributes_DeleteItem(&event->attributes, key);
6729 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
6731 struct media_event *event = impl_from_IMFMediaEvent(iface);
6733 TRACE("%p.\n", iface);
6735 return attributes_DeleteAllItems(&event->attributes);
6738 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
6740 struct media_event *event = impl_from_IMFMediaEvent(iface);
6742 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
6744 return attributes_SetUINT32(&event->attributes, key, value);
6747 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
6749 struct media_event *event = impl_from_IMFMediaEvent(iface);
6751 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
6753 return attributes_SetUINT64(&event->attributes, key, value);
6756 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
6758 struct media_event *event = impl_from_IMFMediaEvent(iface);
6760 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
6762 return attributes_SetDouble(&event->attributes, key, value);
6765 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
6767 struct media_event *event = impl_from_IMFMediaEvent(iface);
6769 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
6771 return attributes_SetGUID(&event->attributes, key, value);
6774 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
6776 struct media_event *event = impl_from_IMFMediaEvent(iface);
6778 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
6780 return attributes_SetString(&event->attributes, key, value);
6783 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
6785 struct media_event *event = impl_from_IMFMediaEvent(iface);
6787 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
6789 return attributes_SetBlob(&event->attributes, key, buf, size);
6792 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
6794 struct media_event *event = impl_from_IMFMediaEvent(iface);
6796 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
6798 return attributes_SetUnknown(&event->attributes, key, unknown);
6801 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
6803 struct media_event *event = impl_from_IMFMediaEvent(iface);
6805 TRACE("%p.\n", iface);
6807 return attributes_LockStore(&event->attributes);
6810 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
6812 struct media_event *event = impl_from_IMFMediaEvent(iface);
6814 TRACE("%p.\n", iface);
6816 return attributes_UnlockStore(&event->attributes);
6819 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
6821 struct media_event *event = impl_from_IMFMediaEvent(iface);
6823 TRACE("%p, %p.\n", iface, count);
6825 return attributes_GetCount(&event->attributes, count);
6828 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
6830 struct media_event *event = impl_from_IMFMediaEvent(iface);
6832 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
6834 return attributes_GetItemByIndex(&event->attributes, index, key, value);
6837 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
6839 struct media_event *event = impl_from_IMFMediaEvent(iface);
6841 TRACE("%p, %p.\n", iface, dest);
6843 return attributes_CopyAllItems(&event->attributes, dest);
6846 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
6848 struct media_event *event = impl_from_IMFMediaEvent(iface);
6850 TRACE("%p, %p.\n", iface, type);
6852 *type = event->type;
6854 return S_OK;
6857 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
6859 struct media_event *event = impl_from_IMFMediaEvent(iface);
6861 TRACE("%p, %p.\n", iface, extended_type);
6863 *extended_type = event->extended_type;
6865 return S_OK;
6868 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
6870 struct media_event *event = impl_from_IMFMediaEvent(iface);
6872 TRACE("%p, %p.\n", iface, status);
6874 *status = event->status;
6876 return S_OK;
6879 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
6881 struct media_event *event = impl_from_IMFMediaEvent(iface);
6883 TRACE("%p, %p.\n", iface, value);
6885 PropVariantCopy(value, &event->value);
6887 return S_OK;
6890 static const IMFMediaEventVtbl mfmediaevent_vtbl =
6892 mfmediaevent_QueryInterface,
6893 mfmediaevent_AddRef,
6894 mfmediaevent_Release,
6895 mfmediaevent_GetItem,
6896 mfmediaevent_GetItemType,
6897 mfmediaevent_CompareItem,
6898 mfmediaevent_Compare,
6899 mfmediaevent_GetUINT32,
6900 mfmediaevent_GetUINT64,
6901 mfmediaevent_GetDouble,
6902 mfmediaevent_GetGUID,
6903 mfmediaevent_GetStringLength,
6904 mfmediaevent_GetString,
6905 mfmediaevent_GetAllocatedString,
6906 mfmediaevent_GetBlobSize,
6907 mfmediaevent_GetBlob,
6908 mfmediaevent_GetAllocatedBlob,
6909 mfmediaevent_GetUnknown,
6910 mfmediaevent_SetItem,
6911 mfmediaevent_DeleteItem,
6912 mfmediaevent_DeleteAllItems,
6913 mfmediaevent_SetUINT32,
6914 mfmediaevent_SetUINT64,
6915 mfmediaevent_SetDouble,
6916 mfmediaevent_SetGUID,
6917 mfmediaevent_SetString,
6918 mfmediaevent_SetBlob,
6919 mfmediaevent_SetUnknown,
6920 mfmediaevent_LockStore,
6921 mfmediaevent_UnlockStore,
6922 mfmediaevent_GetCount,
6923 mfmediaevent_GetItemByIndex,
6924 mfmediaevent_CopyAllItems,
6925 mfmediaevent_GetType,
6926 mfmediaevent_GetExtendedType,
6927 mfmediaevent_GetStatus,
6928 mfmediaevent_GetValue,
6931 /***********************************************************************
6932 * MFCreateMediaEvent (mfplat.@)
6934 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
6935 IMFMediaEvent **event)
6937 struct media_event *object;
6938 HRESULT hr;
6940 TRACE("%s, %s, %#x, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
6941 debugstr_propvar(value), event);
6943 object = heap_alloc(sizeof(*object));
6944 if (!object)
6945 return E_OUTOFMEMORY;
6947 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
6949 heap_free(object);
6950 return hr;
6952 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
6954 object->type = type;
6955 object->extended_type = *extended_type;
6956 object->status = status;
6958 PropVariantInit(&object->value);
6959 if (value)
6960 PropVariantCopy(&object->value, value);
6962 *event = &object->IMFMediaEvent_iface;
6964 TRACE("Created event %p.\n", *event);
6966 return S_OK;
6969 struct event_queue
6971 IMFMediaEventQueue IMFMediaEventQueue_iface;
6972 LONG refcount;
6974 CRITICAL_SECTION cs;
6975 CONDITION_VARIABLE update_event;
6976 struct list events;
6977 BOOL is_shut_down;
6978 BOOL notified;
6979 IRtwqAsyncResult *subscriber;
6982 struct queued_event
6984 struct list entry;
6985 IMFMediaEvent *event;
6988 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
6990 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
6993 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
6995 struct list *head = list_head(&queue->events);
6996 struct queued_event *queued_event;
6997 IMFMediaEvent *event;
6999 if (!head)
7000 return NULL;
7002 queued_event = LIST_ENTRY(head, struct queued_event, entry);
7003 event = queued_event->event;
7004 list_remove(&queued_event->entry);
7005 heap_free(queued_event);
7006 return event;
7009 static void event_queue_cleanup(struct event_queue *queue)
7011 IMFMediaEvent *event;
7013 while ((event = queue_pop_event(queue)))
7014 IMFMediaEvent_Release(event);
7017 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7019 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7021 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7023 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7024 IsEqualIID(riid, &IID_IUnknown))
7026 *out = &queue->IMFMediaEventQueue_iface;
7027 IMFMediaEventQueue_AddRef(iface);
7028 return S_OK;
7031 WARN("Unsupported %s.\n", debugstr_guid(riid));
7032 *out = NULL;
7033 return E_NOINTERFACE;
7036 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7038 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7039 ULONG refcount = InterlockedIncrement(&queue->refcount);
7041 TRACE("%p, refcount %u.\n", iface, refcount);
7043 return refcount;
7046 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7048 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7049 ULONG refcount = InterlockedDecrement(&queue->refcount);
7051 TRACE("%p, refcount %u.\n", queue, refcount);
7053 if (!refcount)
7055 event_queue_cleanup(queue);
7056 DeleteCriticalSection(&queue->cs);
7057 heap_free(queue);
7060 return refcount;
7063 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7065 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7066 HRESULT hr = S_OK;
7068 TRACE("%p, %p.\n", iface, event);
7070 EnterCriticalSection(&queue->cs);
7072 if (queue->is_shut_down)
7073 hr = MF_E_SHUTDOWN;
7074 else if (queue->subscriber)
7075 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7076 else
7078 if (flags & MF_EVENT_FLAG_NO_WAIT)
7080 if (!(*event = queue_pop_event(queue)))
7081 hr = MF_E_NO_EVENTS_AVAILABLE;
7083 else
7085 while (list_empty(&queue->events) && !queue->is_shut_down)
7087 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7089 *event = queue_pop_event(queue);
7090 if (queue->is_shut_down)
7091 hr = MF_E_SHUTDOWN;
7095 LeaveCriticalSection(&queue->cs);
7097 return hr;
7100 static void queue_notify_subscriber(struct event_queue *queue)
7102 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7103 return;
7105 queue->notified = TRUE;
7106 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7109 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7111 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7112 MFASYNCRESULT *result_data = (MFASYNCRESULT *)queue->subscriber;
7113 HRESULT hr;
7115 TRACE("%p, %p, %p.\n", iface, callback, state);
7117 if (!callback)
7118 return E_INVALIDARG;
7120 EnterCriticalSection(&queue->cs);
7122 if (queue->is_shut_down)
7123 hr = MF_E_SHUTDOWN;
7124 else if (result_data)
7126 if (result_data->pCallback == callback)
7127 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7128 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7129 else
7130 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7132 else
7134 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7135 if (SUCCEEDED(hr))
7136 queue_notify_subscriber(queue);
7139 LeaveCriticalSection(&queue->cs);
7141 return hr;
7144 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7146 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7147 HRESULT hr = E_FAIL;
7149 TRACE("%p, %p, %p.\n", iface, result, event);
7151 EnterCriticalSection(&queue->cs);
7153 if (queue->is_shut_down)
7154 hr = MF_E_SHUTDOWN;
7155 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7157 *event = queue_pop_event(queue);
7158 if (queue->subscriber)
7159 IRtwqAsyncResult_Release(queue->subscriber);
7160 queue->subscriber = NULL;
7161 queue->notified = FALSE;
7162 hr = *event ? S_OK : E_FAIL;
7165 LeaveCriticalSection(&queue->cs);
7167 return hr;
7170 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7172 struct queued_event *queued_event;
7173 HRESULT hr = S_OK;
7175 queued_event = heap_alloc(sizeof(*queued_event));
7176 if (!queued_event)
7177 return E_OUTOFMEMORY;
7179 queued_event->event = event;
7181 EnterCriticalSection(&queue->cs);
7183 if (queue->is_shut_down)
7184 hr = MF_E_SHUTDOWN;
7185 else
7187 IMFMediaEvent_AddRef(queued_event->event);
7188 list_add_tail(&queue->events, &queued_event->entry);
7189 queue_notify_subscriber(queue);
7192 LeaveCriticalSection(&queue->cs);
7194 if (FAILED(hr))
7195 heap_free(queued_event);
7197 WakeAllConditionVariable(&queue->update_event);
7199 return hr;
7202 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7204 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7206 TRACE("%p, %p.\n", iface, event);
7208 return eventqueue_queue_event(queue, event);
7211 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7212 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7214 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7215 IMFMediaEvent *event;
7216 HRESULT hr;
7218 TRACE("%p, %s, %s, %#x, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7219 debugstr_propvar(value));
7221 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7222 return hr;
7224 hr = eventqueue_queue_event(queue, event);
7225 IMFMediaEvent_Release(event);
7226 return hr;
7229 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7230 REFGUID extended_type, HRESULT status, IUnknown *unk)
7232 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7233 IMFMediaEvent *event;
7234 PROPVARIANT value;
7235 HRESULT hr;
7237 TRACE("%p, %s, %s, %#x, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7239 value.vt = VT_UNKNOWN;
7240 value.punkVal = unk;
7242 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7243 return hr;
7245 hr = eventqueue_queue_event(queue, event);
7246 IMFMediaEvent_Release(event);
7247 return hr;
7250 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7252 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7254 TRACE("%p\n", queue);
7256 EnterCriticalSection(&queue->cs);
7258 if (!queue->is_shut_down)
7260 event_queue_cleanup(queue);
7261 queue->is_shut_down = TRUE;
7264 LeaveCriticalSection(&queue->cs);
7266 WakeAllConditionVariable(&queue->update_event);
7268 return S_OK;
7271 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7273 eventqueue_QueryInterface,
7274 eventqueue_AddRef,
7275 eventqueue_Release,
7276 eventqueue_GetEvent,
7277 eventqueue_BeginGetEvent,
7278 eventqueue_EndGetEvent,
7279 eventqueue_QueueEvent,
7280 eventqueue_QueueEventParamVar,
7281 eventqueue_QueueEventParamUnk,
7282 eventqueue_Shutdown
7285 /***********************************************************************
7286 * MFCreateEventQueue (mfplat.@)
7288 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7290 struct event_queue *object;
7292 TRACE("%p\n", queue);
7294 object = heap_alloc_zero(sizeof(*object));
7295 if (!object)
7296 return E_OUTOFMEMORY;
7298 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7299 object->refcount = 1;
7300 list_init(&object->events);
7301 InitializeCriticalSection(&object->cs);
7302 InitializeConditionVariable(&object->update_event);
7304 *queue = &object->IMFMediaEventQueue_iface;
7306 return S_OK;
7309 struct collection
7311 IMFCollection IMFCollection_iface;
7312 LONG refcount;
7313 IUnknown **elements;
7314 size_t capacity;
7315 size_t count;
7318 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7320 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7323 static void collection_clear(struct collection *collection)
7325 size_t i;
7327 for (i = 0; i < collection->count; ++i)
7329 if (collection->elements[i])
7330 IUnknown_Release(collection->elements[i]);
7333 heap_free(collection->elements);
7334 collection->elements = NULL;
7335 collection->count = 0;
7336 collection->capacity = 0;
7339 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7341 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7343 if (IsEqualIID(riid, &IID_IMFCollection) ||
7344 IsEqualIID(riid, &IID_IUnknown))
7346 *out = iface;
7347 IMFCollection_AddRef(iface);
7348 return S_OK;
7351 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7352 *out = NULL;
7353 return E_NOINTERFACE;
7356 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7358 struct collection *collection = impl_from_IMFCollection(iface);
7359 ULONG refcount = InterlockedIncrement(&collection->refcount);
7361 TRACE("%p, %d.\n", collection, refcount);
7363 return refcount;
7366 static ULONG WINAPI collection_Release(IMFCollection *iface)
7368 struct collection *collection = impl_from_IMFCollection(iface);
7369 ULONG refcount = InterlockedDecrement(&collection->refcount);
7371 TRACE("%p, %d.\n", collection, refcount);
7373 if (!refcount)
7375 collection_clear(collection);
7376 heap_free(collection->elements);
7377 heap_free(collection);
7380 return refcount;
7383 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7385 struct collection *collection = impl_from_IMFCollection(iface);
7387 TRACE("%p, %p.\n", iface, count);
7389 if (!count)
7390 return E_POINTER;
7392 *count = collection->count;
7394 return S_OK;
7397 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7399 struct collection *collection = impl_from_IMFCollection(iface);
7401 TRACE("%p, %u, %p.\n", iface, idx, element);
7403 if (!element)
7404 return E_POINTER;
7406 if (idx >= collection->count)
7407 return E_INVALIDARG;
7409 *element = collection->elements[idx];
7410 if (*element)
7411 IUnknown_AddRef(*element);
7413 return *element ? S_OK : E_UNEXPECTED;
7416 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7418 struct collection *collection = impl_from_IMFCollection(iface);
7420 TRACE("%p, %p.\n", iface, element);
7422 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7423 sizeof(*collection->elements)))
7424 return E_OUTOFMEMORY;
7426 collection->elements[collection->count++] = element;
7427 if (element)
7428 IUnknown_AddRef(element);
7430 return S_OK;
7433 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7435 struct collection *collection = impl_from_IMFCollection(iface);
7436 size_t count;
7438 TRACE("%p, %u, %p.\n", iface, idx, element);
7440 if (!element)
7441 return E_POINTER;
7443 if (idx >= collection->count)
7444 return E_INVALIDARG;
7446 *element = collection->elements[idx];
7448 count = collection->count - idx - 1;
7449 if (count)
7450 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7451 collection->count--;
7453 return S_OK;
7456 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7458 struct collection *collection = impl_from_IMFCollection(iface);
7459 size_t i;
7461 TRACE("%p, %u, %p.\n", iface, idx, element);
7463 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7464 sizeof(*collection->elements)))
7465 return E_OUTOFMEMORY;
7467 if (idx < collection->count)
7469 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7470 (collection->count - idx) * sizeof(*collection->elements));
7471 collection->count++;
7473 else
7475 for (i = collection->count; i < idx; ++i)
7476 collection->elements[i] = NULL;
7477 collection->count = idx + 1;
7480 collection->elements[idx] = element;
7481 if (collection->elements[idx])
7482 IUnknown_AddRef(collection->elements[idx]);
7484 return S_OK;
7487 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7489 struct collection *collection = impl_from_IMFCollection(iface);
7491 TRACE("%p.\n", iface);
7493 collection_clear(collection);
7495 return S_OK;
7498 static const IMFCollectionVtbl mfcollectionvtbl =
7500 collection_QueryInterface,
7501 collection_AddRef,
7502 collection_Release,
7503 collection_GetElementCount,
7504 collection_GetElement,
7505 collection_AddElement,
7506 collection_RemoveElement,
7507 collection_InsertElementAt,
7508 collection_RemoveAllElements,
7511 /***********************************************************************
7512 * MFCreateCollection (mfplat.@)
7514 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7516 struct collection *object;
7518 TRACE("%p\n", collection);
7520 if (!collection)
7521 return E_POINTER;
7523 object = heap_alloc_zero(sizeof(*object));
7524 if (!object)
7525 return E_OUTOFMEMORY;
7527 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7528 object->refcount = 1;
7530 *collection = &object->IMFCollection_iface;
7532 return S_OK;
7535 /***********************************************************************
7536 * MFHeapAlloc (mfplat.@)
7538 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7540 TRACE("%lu, %#x, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7541 return HeapAlloc(GetProcessHeap(), flags, size);
7544 /***********************************************************************
7545 * MFHeapFree (mfplat.@)
7547 void WINAPI MFHeapFree(void *p)
7549 TRACE("%p\n", p);
7550 HeapFree(GetProcessHeap(), 0, p);
7553 /***********************************************************************
7554 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7556 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7558 FIXME("(%p, %p): stub\n", stream, bytestream);
7560 return E_NOTIMPL;
7563 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7565 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7567 if (IsEqualIID(riid, &IID_IMFClock) ||
7568 IsEqualIID(riid, &IID_IUnknown))
7570 *obj = iface;
7571 IMFClock_AddRef(iface);
7572 return S_OK;
7575 WARN("Unsupported %s.\n", debugstr_guid(riid));
7576 *obj = NULL;
7577 return E_NOINTERFACE;
7580 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7582 struct system_clock *clock = impl_from_IMFClock(iface);
7583 ULONG refcount = InterlockedIncrement(&clock->refcount);
7585 TRACE("%p, refcount %u.\n", iface, refcount);
7587 return refcount;
7590 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7592 struct system_clock *clock = impl_from_IMFClock(iface);
7593 ULONG refcount = InterlockedDecrement(&clock->refcount);
7595 TRACE("%p, refcount %u.\n", iface, refcount);
7597 if (!refcount)
7598 heap_free(clock);
7600 return refcount;
7603 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7605 TRACE("%p, %p.\n", iface, flags);
7607 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7608 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7610 return S_OK;
7613 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7614 MFTIME *system_time)
7616 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7618 *clock_time = *system_time = MFGetSystemTime();
7620 return S_OK;
7623 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7625 TRACE("%p, %p.\n", iface, key);
7627 *key = 0;
7629 return S_OK;
7632 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7634 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7636 *state = MFCLOCK_STATE_RUNNING;
7638 return S_OK;
7641 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7643 TRACE("%p, %p.\n", iface, props);
7645 if (!props)
7646 return E_POINTER;
7648 memset(props, 0, sizeof(*props));
7649 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7650 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7651 props->dwClockJitter = 1;
7653 return S_OK;
7656 static const IMFClockVtbl system_clock_vtbl =
7658 system_clock_QueryInterface,
7659 system_clock_AddRef,
7660 system_clock_Release,
7661 system_clock_GetClockCharacteristics,
7662 system_clock_GetCorrelatedTime,
7663 system_clock_GetContinuityKey,
7664 system_clock_GetState,
7665 system_clock_GetProperties,
7668 static HRESULT create_system_clock(IMFClock **clock)
7670 struct system_clock *object;
7672 if (!(object = heap_alloc(sizeof(*object))))
7673 return E_OUTOFMEMORY;
7675 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7676 object->refcount = 1;
7678 *clock = &object->IMFClock_iface;
7680 return S_OK;
7683 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7685 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7687 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7689 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7690 IsEqualIID(riid, &IID_IUnknown))
7692 *obj = &source->IMFPresentationTimeSource_iface;
7694 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
7696 *obj = &source->IMFClockStateSink_iface;
7698 else
7700 WARN("Unsupported %s.\n", debugstr_guid(riid));
7701 *obj = NULL;
7702 return E_NOINTERFACE;
7705 IUnknown_AddRef((IUnknown *)*obj);
7706 return S_OK;
7709 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
7711 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7712 ULONG refcount = InterlockedIncrement(&source->refcount);
7714 TRACE("%p, refcount %u.\n", iface, refcount);
7716 return refcount;
7719 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
7721 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7722 ULONG refcount = InterlockedDecrement(&source->refcount);
7724 TRACE("%p, refcount %u.\n", iface, refcount);
7726 if (!refcount)
7728 if (source->clock)
7729 IMFClock_Release(source->clock);
7730 DeleteCriticalSection(&source->cs);
7731 heap_free(source);
7734 return refcount;
7737 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
7739 TRACE("%p, %p.\n", iface, flags);
7741 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7743 return S_OK;
7746 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
7747 LONGLONG *clock_time, MFTIME *system_time)
7749 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7750 HRESULT hr;
7752 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7754 EnterCriticalSection(&source->cs);
7755 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
7757 if (source->state == MFCLOCK_STATE_RUNNING)
7759 system_time_source_apply_rate(source, clock_time);
7760 *clock_time += source->start_offset;
7762 else
7763 *clock_time = source->start_offset;
7765 LeaveCriticalSection(&source->cs);
7767 return hr;
7770 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
7772 TRACE("%p, %p.\n", iface, key);
7774 *key = 0;
7776 return S_OK;
7779 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
7780 MFCLOCK_STATE *state)
7782 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7784 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7786 EnterCriticalSection(&source->cs);
7787 *state = source->state;
7788 LeaveCriticalSection(&source->cs);
7790 return S_OK;
7793 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
7795 TRACE("%p, %p.\n", iface, props);
7797 if (!props)
7798 return E_POINTER;
7800 memset(props, 0, sizeof(*props));
7801 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7802 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7803 props->dwClockJitter = 1;
7805 return S_OK;
7808 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
7810 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7812 TRACE("%p, %p.\n", iface, clock);
7814 *clock = source->clock;
7815 IMFClock_AddRef(*clock);
7817 return S_OK;
7820 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
7822 system_time_source_QueryInterface,
7823 system_time_source_AddRef,
7824 system_time_source_Release,
7825 system_time_source_GetClockCharacteristics,
7826 system_time_source_GetCorrelatedTime,
7827 system_time_source_GetContinuityKey,
7828 system_time_source_GetState,
7829 system_time_source_GetProperties,
7830 system_time_source_GetUnderlyingClock,
7833 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
7835 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7836 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
7839 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
7841 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7842 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
7845 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
7847 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7848 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
7851 enum clock_command
7853 CLOCK_CMD_START = 0,
7854 CLOCK_CMD_STOP,
7855 CLOCK_CMD_PAUSE,
7856 CLOCK_CMD_RESTART,
7857 CLOCK_CMD_MAX,
7860 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
7862 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
7863 { /* S S* P R */
7864 /* INVALID */ { 1, 0, 1, 0 },
7865 /* RUNNING */ { 1, 1, 1, 0 },
7866 /* STOPPED */ { 1, 1, 0, 0 },
7867 /* PAUSED */ { 1, 1, 0, 1 },
7869 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
7871 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
7872 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
7873 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
7874 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
7877 /* Special case that go against usual state change vs return value behavior. */
7878 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
7879 return S_OK;
7881 if (!state_change_is_allowed[source->state][command])
7882 return MF_E_INVALIDREQUEST;
7884 source->state = states[command];
7886 return S_OK;
7889 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
7890 LONGLONG start_offset)
7892 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7893 MFCLOCK_STATE state;
7894 HRESULT hr;
7896 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
7898 EnterCriticalSection(&source->cs);
7899 state = source->state;
7900 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
7902 system_time_source_apply_rate(source, &system_time);
7903 if (start_offset == PRESENTATION_CURRENT_POSITION)
7905 switch (state)
7907 case MFCLOCK_STATE_RUNNING:
7908 break;
7909 case MFCLOCK_STATE_PAUSED:
7910 source->start_offset -= system_time;
7911 break;
7912 default:
7913 source->start_offset = -system_time;
7914 break;
7918 else
7920 source->start_offset = -system_time + start_offset;
7923 LeaveCriticalSection(&source->cs);
7925 return hr;
7928 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
7930 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7931 HRESULT hr;
7933 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7935 EnterCriticalSection(&source->cs);
7936 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
7937 source->start_offset = 0;
7938 LeaveCriticalSection(&source->cs);
7940 return hr;
7943 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
7945 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7946 HRESULT hr;
7948 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7950 EnterCriticalSection(&source->cs);
7951 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
7953 system_time_source_apply_rate(source, &system_time);
7954 source->start_offset += system_time;
7956 LeaveCriticalSection(&source->cs);
7958 return hr;
7961 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
7963 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7964 HRESULT hr;
7966 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7968 EnterCriticalSection(&source->cs);
7969 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
7971 system_time_source_apply_rate(source, &system_time);
7972 source->start_offset -= system_time;
7974 LeaveCriticalSection(&source->cs);
7976 return hr;
7979 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
7981 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7982 double intpart;
7984 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
7986 if (rate == 0.0f)
7987 return MF_E_UNSUPPORTED_RATE;
7989 modf(rate, &intpart);
7991 EnterCriticalSection(&source->cs);
7992 source->rate = rate;
7993 source->i_rate = rate == intpart ? rate : 0;
7994 LeaveCriticalSection(&source->cs);
7996 return S_OK;
7999 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8001 system_time_source_sink_QueryInterface,
8002 system_time_source_sink_AddRef,
8003 system_time_source_sink_Release,
8004 system_time_source_sink_OnClockStart,
8005 system_time_source_sink_OnClockStop,
8006 system_time_source_sink_OnClockPause,
8007 system_time_source_sink_OnClockRestart,
8008 system_time_source_sink_OnClockSetRate,
8011 /***********************************************************************
8012 * MFCreateSystemTimeSource (mfplat.@)
8014 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8016 struct system_time_source *object;
8017 HRESULT hr;
8019 TRACE("%p.\n", time_source);
8021 object = heap_alloc_zero(sizeof(*object));
8022 if (!object)
8023 return E_OUTOFMEMORY;
8025 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8026 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8027 object->refcount = 1;
8028 object->rate = 1.0f;
8029 object->i_rate = 1;
8030 InitializeCriticalSection(&object->cs);
8032 if (FAILED(hr = create_system_clock(&object->clock)))
8034 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8035 return hr;
8038 *time_source = &object->IMFPresentationTimeSource_iface;
8040 return S_OK;
8043 struct async_create_file
8045 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8046 LONG refcount;
8047 MF_FILE_ACCESSMODE access_mode;
8048 MF_FILE_OPENMODE open_mode;
8049 MF_FILE_FLAGS flags;
8050 WCHAR *path;
8053 struct async_create_file_result
8055 struct list entry;
8056 IRtwqAsyncResult *result;
8057 IMFByteStream *stream;
8060 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8061 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8063 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8065 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8068 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8070 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8071 IsEqualIID(riid, &IID_IUnknown))
8073 *obj = iface;
8074 IRtwqAsyncCallback_AddRef(iface);
8075 return S_OK;
8078 *obj = NULL;
8079 return E_NOINTERFACE;
8082 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8084 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8085 ULONG refcount = InterlockedIncrement(&async->refcount);
8087 TRACE("%p, refcount %u.\n", iface, refcount);
8089 return refcount;
8092 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8094 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8095 ULONG refcount = InterlockedDecrement(&async->refcount);
8097 TRACE("%p, refcount %u.\n", iface, refcount);
8099 if (!refcount)
8101 heap_free(async->path);
8102 heap_free(async);
8105 return refcount;
8108 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8110 return E_NOTIMPL;
8113 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8115 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8116 IRtwqAsyncResult *caller;
8117 IMFByteStream *stream;
8118 HRESULT hr;
8120 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8122 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8123 if (SUCCEEDED(hr))
8125 struct async_create_file_result *result_item;
8127 result_item = heap_alloc(sizeof(*result_item));
8128 if (result_item)
8130 result_item->result = caller;
8131 IRtwqAsyncResult_AddRef(caller);
8132 result_item->stream = stream;
8133 IMFByteStream_AddRef(stream);
8135 EnterCriticalSection(&async_create_file_cs);
8136 list_add_tail(&async_create_file_results, &result_item->entry);
8137 LeaveCriticalSection(&async_create_file_cs);
8140 IMFByteStream_Release(stream);
8142 else
8143 IRtwqAsyncResult_SetStatus(caller, hr);
8145 RtwqInvokeCallback(caller);
8147 return S_OK;
8150 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8152 async_create_file_callback_QueryInterface,
8153 async_create_file_callback_AddRef,
8154 async_create_file_callback_Release,
8155 async_create_file_callback_GetParameters,
8156 async_create_file_callback_Invoke,
8159 /***********************************************************************
8160 * MFBeginCreateFile (mfplat.@)
8162 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8163 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8165 struct async_create_file *async = NULL;
8166 IRtwqAsyncResult *caller, *item = NULL;
8167 HRESULT hr;
8169 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8170 cancel_cookie);
8172 if (cancel_cookie)
8173 *cancel_cookie = NULL;
8175 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8176 return hr;
8178 async = heap_alloc(sizeof(*async));
8179 if (!async)
8181 hr = E_OUTOFMEMORY;
8182 goto failed;
8185 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8186 async->refcount = 1;
8187 async->access_mode = access_mode;
8188 async->open_mode = open_mode;
8189 async->flags = flags;
8190 if (FAILED(hr = heap_strdupW(path, &async->path)))
8191 goto failed;
8193 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8194 if (FAILED(hr))
8195 goto failed;
8197 if (cancel_cookie)
8199 *cancel_cookie = (IUnknown *)caller;
8200 IUnknown_AddRef(*cancel_cookie);
8203 hr = RtwqInvokeCallback(item);
8205 failed:
8206 if (async)
8207 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8208 if (item)
8209 IRtwqAsyncResult_Release(item);
8210 if (caller)
8211 IRtwqAsyncResult_Release(caller);
8213 return hr;
8216 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8218 struct async_create_file_result *item;
8219 HRESULT hr = MF_E_UNEXPECTED;
8220 IRtwqAsyncResult *result;
8222 *stream = NULL;
8224 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8225 return hr;
8227 EnterCriticalSection(&async_create_file_cs);
8229 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8231 if (result == item->result)
8233 *stream = item->stream;
8234 IRtwqAsyncResult_Release(item->result);
8235 list_remove(&item->entry);
8236 heap_free(item);
8237 break;
8241 LeaveCriticalSection(&async_create_file_cs);
8243 if (*stream)
8244 hr = IRtwqAsyncResult_GetStatus(result);
8246 IRtwqAsyncResult_Release(result);
8248 return hr;
8251 /***********************************************************************
8252 * MFEndCreateFile (mfplat.@)
8254 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8256 TRACE("%p, %p.\n", result, stream);
8258 return async_create_file_pull_result((IUnknown *)result, stream);
8261 /***********************************************************************
8262 * MFCancelCreateFile (mfplat.@)
8264 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8266 IMFByteStream *stream = NULL;
8267 HRESULT hr;
8269 TRACE("%p.\n", cancel_cookie);
8271 hr = async_create_file_pull_result(cancel_cookie, &stream);
8273 if (stream)
8274 IMFByteStream_Release(stream);
8276 return hr;
8279 /***********************************************************************
8280 * MFRegisterLocalSchemeHandler (mfplat.@)
8282 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8284 struct local_handler *handler;
8285 HRESULT hr;
8287 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8289 if (!scheme || !activate)
8290 return E_INVALIDARG;
8292 if (!(handler = heap_alloc(sizeof(*handler))))
8293 return E_OUTOFMEMORY;
8295 if (FAILED(hr = heap_strdupW(scheme, &handler->u.scheme)))
8297 heap_free(handler);
8298 return hr;
8300 handler->activate = activate;
8301 IMFActivate_AddRef(handler->activate);
8303 EnterCriticalSection(&local_handlers_section);
8304 list_add_head(&local_scheme_handlers, &handler->entry);
8305 LeaveCriticalSection(&local_handlers_section);
8307 return S_OK;
8310 /***********************************************************************
8311 * MFRegisterLocalByteStreamHandler (mfplat.@)
8313 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8315 struct local_handler *handler;
8316 HRESULT hr;
8318 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8320 if ((!extension && !mime) || !activate)
8321 return E_INVALIDARG;
8323 if (!(handler = heap_alloc_zero(sizeof(*handler))))
8324 return E_OUTOFMEMORY;
8326 hr = heap_strdupW(extension, &handler->u.bytestream.extension);
8327 if (SUCCEEDED(hr))
8328 hr = heap_strdupW(mime, &handler->u.bytestream.mime);
8330 if (FAILED(hr))
8331 goto failed;
8333 EnterCriticalSection(&local_handlers_section);
8334 list_add_head(&local_bytestream_handlers, &handler->entry);
8335 LeaveCriticalSection(&local_handlers_section);
8337 return hr;
8339 failed:
8340 heap_free(handler->u.bytestream.extension);
8341 heap_free(handler->u.bytestream.mime);
8342 heap_free(handler);
8344 return hr;
8347 struct property_store
8349 IPropertyStore IPropertyStore_iface;
8350 LONG refcount;
8351 CRITICAL_SECTION cs;
8352 size_t count, capacity;
8353 struct
8355 PROPERTYKEY key;
8356 PROPVARIANT value;
8357 } *values;
8360 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8362 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8365 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8367 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8369 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8371 *obj = iface;
8372 IPropertyStore_AddRef(iface);
8373 return S_OK;
8376 *obj = NULL;
8377 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8378 return E_NOINTERFACE;
8381 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8383 struct property_store *store = impl_from_IPropertyStore(iface);
8384 ULONG refcount = InterlockedIncrement(&store->refcount);
8386 TRACE("%p, refcount %d.\n", iface, refcount);
8388 return refcount;
8391 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8393 struct property_store *store = impl_from_IPropertyStore(iface);
8394 ULONG refcount = InterlockedDecrement(&store->refcount);
8396 TRACE("%p, refcount %d.\n", iface, refcount);
8398 if (!refcount)
8400 DeleteCriticalSection(&store->cs);
8401 heap_free(store->values);
8402 heap_free(store);
8405 return refcount;
8408 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8410 struct property_store *store = impl_from_IPropertyStore(iface);
8412 TRACE("%p, %p.\n", iface, count);
8414 if (!count)
8415 return E_INVALIDARG;
8417 EnterCriticalSection(&store->cs);
8418 *count = store->count;
8419 LeaveCriticalSection(&store->cs);
8420 return S_OK;
8423 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8425 struct property_store *store = impl_from_IPropertyStore(iface);
8427 TRACE("%p, %u, %p.\n", iface, index, key);
8429 EnterCriticalSection(&store->cs);
8431 if (index >= store->count)
8433 LeaveCriticalSection(&store->cs);
8434 return E_INVALIDARG;
8437 *key = store->values[index].key;
8439 LeaveCriticalSection(&store->cs);
8440 return S_OK;
8443 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8445 struct property_store *store = impl_from_IPropertyStore(iface);
8446 unsigned int i;
8448 TRACE("%p, %p, %p.\n", iface, key, value);
8450 if (!value)
8451 return E_INVALIDARG;
8453 if (!key)
8454 return S_FALSE;
8456 EnterCriticalSection(&store->cs);
8458 for (i = 0; i < store->count; ++i)
8460 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8462 PropVariantCopy(value, &store->values[i].value);
8463 LeaveCriticalSection(&store->cs);
8464 return S_OK;
8468 LeaveCriticalSection(&store->cs);
8469 return S_FALSE;
8472 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8474 struct property_store *store = impl_from_IPropertyStore(iface);
8475 unsigned int i;
8477 TRACE("%p, %p, %p.\n", iface, key, value);
8479 EnterCriticalSection(&store->cs);
8481 for (i = 0; i < store->count; ++i)
8483 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8485 PropVariantCopy(&store->values[i].value, value);
8486 LeaveCriticalSection(&store->cs);
8487 return S_OK;
8491 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8493 LeaveCriticalSection(&store->cs);
8494 return E_OUTOFMEMORY;
8497 store->values[store->count].key = *key;
8498 PropVariantCopy(&store->values[store->count].value, value);
8499 ++store->count;
8501 LeaveCriticalSection(&store->cs);
8502 return S_OK;
8505 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8507 TRACE("%p.\n", iface);
8509 return E_NOTIMPL;
8512 static const IPropertyStoreVtbl property_store_vtbl =
8514 property_store_QueryInterface,
8515 property_store_AddRef,
8516 property_store_Release,
8517 property_store_GetCount,
8518 property_store_GetAt,
8519 property_store_GetValue,
8520 property_store_SetValue,
8521 property_store_Commit,
8524 /***********************************************************************
8525 * CreatePropertyStore (mfplat.@)
8527 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8529 struct property_store *object;
8531 TRACE("%p.\n", store);
8533 if (!store)
8534 return E_INVALIDARG;
8536 if (!(object = heap_alloc_zero(sizeof(*object))))
8537 return E_OUTOFMEMORY;
8539 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8540 object->refcount = 1;
8541 InitializeCriticalSection(&object->cs);
8543 TRACE("Created store %p.\n", object);
8544 *store = &object->IPropertyStore_iface;
8546 return S_OK;
8549 enum dxgi_device_handle_flags
8551 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8552 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8553 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8556 struct dxgi_device_manager
8558 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8559 LONG refcount;
8560 UINT token;
8561 IDXGIDevice *device;
8563 unsigned int *handles;
8564 size_t count;
8565 size_t capacity;
8567 unsigned int locks;
8568 unsigned int locking_tid;
8570 CRITICAL_SECTION cs;
8571 CONDITION_VARIABLE lock;
8574 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8576 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8579 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8581 if (!hdevice || hdevice > ULongToHandle(manager->count))
8582 return E_HANDLE;
8583 *idx = (ULONG_PTR)hdevice - 1;
8584 return S_OK;
8587 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8589 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8591 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8592 IsEqualGUID(riid, &IID_IUnknown))
8594 *obj = iface;
8595 IMFDXGIDeviceManager_AddRef(iface);
8596 return S_OK;
8599 WARN("Unsupported %s.\n", debugstr_guid(riid));
8600 *obj = NULL;
8601 return E_NOINTERFACE;
8604 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8606 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8607 ULONG refcount = InterlockedIncrement(&manager->refcount);
8609 TRACE("%p, refcount %u.\n", iface, refcount);
8611 return refcount;
8614 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8616 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8617 ULONG refcount = InterlockedDecrement(&manager->refcount);
8619 TRACE("%p, refcount %u.\n", iface, refcount);
8621 if (!refcount)
8623 if (manager->device)
8624 IDXGIDevice_Release(manager->device);
8625 DeleteCriticalSection(&manager->cs);
8626 heap_free(manager->handles);
8627 heap_free(manager);
8630 return refcount;
8633 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8635 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8636 return;
8638 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8639 manager->locks++;
8642 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8644 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8645 return;
8647 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8648 if (!--manager->locks)
8649 manager->locking_tid = 0;
8652 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8654 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8655 HRESULT hr;
8656 size_t idx;
8658 TRACE("%p, %p.\n", iface, hdevice);
8660 EnterCriticalSection(&manager->cs);
8662 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8664 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8666 dxgi_device_manager_unlock_handle(manager, idx);
8667 manager->handles[idx] = 0;
8668 if (idx == manager->count - 1)
8669 manager->count--;
8671 else
8672 hr = E_HANDLE;
8675 LeaveCriticalSection(&manager->cs);
8677 WakeAllConditionVariable(&manager->lock);
8679 return hr;
8682 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8683 REFIID riid, void **service)
8685 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8686 HRESULT hr;
8687 size_t idx;
8689 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service);
8691 EnterCriticalSection(&manager->cs);
8693 if (!manager->device)
8694 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8695 else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8697 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8698 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8699 else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8700 hr = IDXGIDevice_QueryInterface(manager->device, riid, service);
8701 else
8702 hr = E_HANDLE;
8705 LeaveCriticalSection(&manager->cs);
8707 return hr;
8710 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8711 REFIID riid, void **obj, BOOL block)
8713 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8714 HRESULT hr;
8715 size_t idx;
8717 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
8719 EnterCriticalSection(&manager->cs);
8721 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8723 if (!manager->device)
8725 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8727 else if (manager->locking_tid == GetCurrentThreadId())
8729 if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8730 dxgi_device_manager_lock_handle(manager, idx);
8732 else if (manager->locking_tid && !block)
8734 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
8736 else
8738 while (manager->locking_tid)
8740 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
8743 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8745 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8746 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8747 else if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8749 manager->locking_tid = GetCurrentThreadId();
8750 dxgi_device_manager_lock_handle(manager, idx);
8756 LeaveCriticalSection(&manager->cs);
8758 return hr;
8761 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
8763 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8764 HRESULT hr = S_OK;
8765 size_t i;
8767 TRACE("%p, %p.\n", iface, hdevice);
8769 *hdevice = NULL;
8771 EnterCriticalSection(&manager->cs);
8773 if (!manager->device)
8774 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8775 else
8777 for (i = 0; i < manager->count; ++i)
8779 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8781 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
8782 *hdevice = ULongToHandle(i + 1);
8783 break;
8787 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
8788 sizeof(*manager->handles)))
8790 *hdevice = ULongToHandle(manager->count + 1);
8791 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
8793 else
8794 hr = E_OUTOFMEMORY;
8797 LeaveCriticalSection(&manager->cs);
8799 return hr;
8802 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
8804 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8805 IDXGIDevice *dxgi_device;
8806 size_t i;
8808 TRACE("%p, %p, %u.\n", iface, device, token);
8810 if (!device || token != manager->token)
8811 return E_INVALIDARG;
8813 if (FAILED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device)))
8814 return E_INVALIDARG;
8816 EnterCriticalSection(&manager->cs);
8818 if (manager->device)
8820 for (i = 0; i < manager->count; ++i)
8822 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
8823 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8825 manager->locking_tid = 0;
8826 manager->locks = 0;
8827 IDXGIDevice_Release(manager->device);
8829 manager->device = dxgi_device;
8831 LeaveCriticalSection(&manager->cs);
8833 WakeAllConditionVariable(&manager->lock);
8835 return S_OK;
8838 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8840 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8841 HRESULT hr;
8842 size_t idx;
8844 TRACE("%p, %p.\n", iface, hdevice);
8846 EnterCriticalSection(&manager->cs);
8848 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8850 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8851 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8852 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8853 hr = E_HANDLE;
8856 LeaveCriticalSection(&manager->cs);
8858 return hr;
8861 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8862 BOOL savestate)
8864 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8865 HRESULT hr = E_FAIL;
8866 size_t idx;
8868 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
8870 EnterCriticalSection(&manager->cs);
8872 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8874 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
8875 if (SUCCEEDED(hr))
8876 dxgi_device_manager_unlock_handle(manager, idx);
8879 LeaveCriticalSection(&manager->cs);
8881 WakeAllConditionVariable(&manager->lock);
8883 return hr;
8886 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
8888 dxgi_device_manager_QueryInterface,
8889 dxgi_device_manager_AddRef,
8890 dxgi_device_manager_Release,
8891 dxgi_device_manager_CloseDeviceHandle,
8892 dxgi_device_manager_GetVideoService,
8893 dxgi_device_manager_LockDevice,
8894 dxgi_device_manager_OpenDeviceHandle,
8895 dxgi_device_manager_ResetDevice,
8896 dxgi_device_manager_TestDevice,
8897 dxgi_device_manager_UnlockDevice,
8900 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8902 struct dxgi_device_manager *object;
8904 TRACE("%p, %p.\n", token, manager);
8906 if (!token || !manager)
8907 return E_POINTER;
8909 if (!(object = heap_alloc_zero(sizeof(*object))))
8910 return E_OUTOFMEMORY;
8912 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
8913 object->refcount = 1;
8914 object->token = GetTickCount();
8915 InitializeCriticalSection(&object->cs);
8916 InitializeConditionVariable(&object->lock);
8918 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
8920 *token = object->token;
8921 *manager = &object->IMFDXGIDeviceManager_iface;
8923 return S_OK;