makefiles: Install PE files in an architecture-specific directory.
[wine.git] / dlls / mfplat / main.c
blob5a35350f5c54565d46df5f15f7933db4d5d9ad39
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_clear_subscriber(struct event_queue *queue)
7011 if (queue->subscriber)
7012 IRtwqAsyncResult_Release(queue->subscriber);
7013 queue->subscriber = NULL;
7016 static void event_queue_cleanup(struct event_queue *queue)
7018 IMFMediaEvent *event;
7020 while ((event = queue_pop_event(queue)))
7021 IMFMediaEvent_Release(event);
7022 event_queue_clear_subscriber(queue);
7025 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7027 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7029 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7031 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7032 IsEqualIID(riid, &IID_IUnknown))
7034 *out = &queue->IMFMediaEventQueue_iface;
7035 IMFMediaEventQueue_AddRef(iface);
7036 return S_OK;
7039 WARN("Unsupported %s.\n", debugstr_guid(riid));
7040 *out = NULL;
7041 return E_NOINTERFACE;
7044 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7046 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7047 ULONG refcount = InterlockedIncrement(&queue->refcount);
7049 TRACE("%p, refcount %u.\n", iface, refcount);
7051 return refcount;
7054 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7056 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7057 ULONG refcount = InterlockedDecrement(&queue->refcount);
7059 TRACE("%p, refcount %u.\n", queue, refcount);
7061 if (!refcount)
7063 event_queue_cleanup(queue);
7064 DeleteCriticalSection(&queue->cs);
7065 heap_free(queue);
7068 return refcount;
7071 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7073 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7074 HRESULT hr = S_OK;
7076 TRACE("%p, %p.\n", iface, event);
7078 EnterCriticalSection(&queue->cs);
7080 if (queue->is_shut_down)
7081 hr = MF_E_SHUTDOWN;
7082 else if (queue->subscriber)
7083 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7084 else
7086 if (flags & MF_EVENT_FLAG_NO_WAIT)
7088 if (!(*event = queue_pop_event(queue)))
7089 hr = MF_E_NO_EVENTS_AVAILABLE;
7091 else
7093 while (list_empty(&queue->events) && !queue->is_shut_down)
7095 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7097 *event = queue_pop_event(queue);
7098 if (queue->is_shut_down)
7099 hr = MF_E_SHUTDOWN;
7103 LeaveCriticalSection(&queue->cs);
7105 return hr;
7108 static void queue_notify_subscriber(struct event_queue *queue)
7110 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7111 return;
7113 queue->notified = TRUE;
7114 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7117 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7119 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7120 RTWQASYNCRESULT *result_data;
7121 HRESULT hr;
7123 TRACE("%p, %p, %p.\n", iface, callback, state);
7125 if (!callback)
7126 return E_INVALIDARG;
7128 EnterCriticalSection(&queue->cs);
7130 if (queue->is_shut_down)
7131 hr = MF_E_SHUTDOWN;
7132 else if ((result_data = (RTWQASYNCRESULT *)queue->subscriber))
7134 if (result_data->pCallback == (IRtwqAsyncCallback *)callback)
7135 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7136 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7137 else
7138 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7140 else
7142 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7143 if (SUCCEEDED(hr))
7144 queue_notify_subscriber(queue);
7147 LeaveCriticalSection(&queue->cs);
7149 return hr;
7152 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7154 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7155 HRESULT hr = E_FAIL;
7157 TRACE("%p, %p, %p.\n", iface, result, event);
7159 EnterCriticalSection(&queue->cs);
7161 if (queue->is_shut_down)
7162 hr = MF_E_SHUTDOWN;
7163 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7165 *event = queue_pop_event(queue);
7166 event_queue_clear_subscriber(queue);
7167 queue->notified = FALSE;
7168 hr = *event ? S_OK : E_FAIL;
7171 LeaveCriticalSection(&queue->cs);
7173 return hr;
7176 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7178 struct queued_event *queued_event;
7179 HRESULT hr = S_OK;
7181 queued_event = heap_alloc(sizeof(*queued_event));
7182 if (!queued_event)
7183 return E_OUTOFMEMORY;
7185 queued_event->event = event;
7187 EnterCriticalSection(&queue->cs);
7189 if (queue->is_shut_down)
7190 hr = MF_E_SHUTDOWN;
7191 else
7193 IMFMediaEvent_AddRef(queued_event->event);
7194 list_add_tail(&queue->events, &queued_event->entry);
7195 queue_notify_subscriber(queue);
7198 LeaveCriticalSection(&queue->cs);
7200 if (FAILED(hr))
7201 heap_free(queued_event);
7203 WakeAllConditionVariable(&queue->update_event);
7205 return hr;
7208 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7210 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7212 TRACE("%p, %p.\n", iface, event);
7214 return eventqueue_queue_event(queue, event);
7217 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7218 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7220 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7221 IMFMediaEvent *event;
7222 HRESULT hr;
7224 TRACE("%p, %s, %s, %#x, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7225 debugstr_propvar(value));
7227 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7228 return hr;
7230 hr = eventqueue_queue_event(queue, event);
7231 IMFMediaEvent_Release(event);
7232 return hr;
7235 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7236 REFGUID extended_type, HRESULT status, IUnknown *unk)
7238 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7239 IMFMediaEvent *event;
7240 PROPVARIANT value;
7241 HRESULT hr;
7243 TRACE("%p, %s, %s, %#x, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7245 value.vt = VT_UNKNOWN;
7246 value.punkVal = unk;
7248 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7249 return hr;
7251 hr = eventqueue_queue_event(queue, event);
7252 IMFMediaEvent_Release(event);
7253 return hr;
7256 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7258 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7260 TRACE("%p\n", queue);
7262 EnterCriticalSection(&queue->cs);
7264 if (!queue->is_shut_down)
7266 event_queue_cleanup(queue);
7267 queue->is_shut_down = TRUE;
7270 LeaveCriticalSection(&queue->cs);
7272 WakeAllConditionVariable(&queue->update_event);
7274 return S_OK;
7277 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7279 eventqueue_QueryInterface,
7280 eventqueue_AddRef,
7281 eventqueue_Release,
7282 eventqueue_GetEvent,
7283 eventqueue_BeginGetEvent,
7284 eventqueue_EndGetEvent,
7285 eventqueue_QueueEvent,
7286 eventqueue_QueueEventParamVar,
7287 eventqueue_QueueEventParamUnk,
7288 eventqueue_Shutdown
7291 /***********************************************************************
7292 * MFCreateEventQueue (mfplat.@)
7294 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7296 struct event_queue *object;
7298 TRACE("%p\n", queue);
7300 object = heap_alloc_zero(sizeof(*object));
7301 if (!object)
7302 return E_OUTOFMEMORY;
7304 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7305 object->refcount = 1;
7306 list_init(&object->events);
7307 InitializeCriticalSection(&object->cs);
7308 InitializeConditionVariable(&object->update_event);
7310 *queue = &object->IMFMediaEventQueue_iface;
7312 return S_OK;
7315 struct collection
7317 IMFCollection IMFCollection_iface;
7318 LONG refcount;
7319 IUnknown **elements;
7320 size_t capacity;
7321 size_t count;
7324 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7326 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7329 static void collection_clear(struct collection *collection)
7331 size_t i;
7333 for (i = 0; i < collection->count; ++i)
7335 if (collection->elements[i])
7336 IUnknown_Release(collection->elements[i]);
7339 heap_free(collection->elements);
7340 collection->elements = NULL;
7341 collection->count = 0;
7342 collection->capacity = 0;
7345 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7347 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7349 if (IsEqualIID(riid, &IID_IMFCollection) ||
7350 IsEqualIID(riid, &IID_IUnknown))
7352 *out = iface;
7353 IMFCollection_AddRef(iface);
7354 return S_OK;
7357 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7358 *out = NULL;
7359 return E_NOINTERFACE;
7362 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7364 struct collection *collection = impl_from_IMFCollection(iface);
7365 ULONG refcount = InterlockedIncrement(&collection->refcount);
7367 TRACE("%p, %d.\n", collection, refcount);
7369 return refcount;
7372 static ULONG WINAPI collection_Release(IMFCollection *iface)
7374 struct collection *collection = impl_from_IMFCollection(iface);
7375 ULONG refcount = InterlockedDecrement(&collection->refcount);
7377 TRACE("%p, %d.\n", collection, refcount);
7379 if (!refcount)
7381 collection_clear(collection);
7382 heap_free(collection->elements);
7383 heap_free(collection);
7386 return refcount;
7389 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7391 struct collection *collection = impl_from_IMFCollection(iface);
7393 TRACE("%p, %p.\n", iface, count);
7395 if (!count)
7396 return E_POINTER;
7398 *count = collection->count;
7400 return S_OK;
7403 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7405 struct collection *collection = impl_from_IMFCollection(iface);
7407 TRACE("%p, %u, %p.\n", iface, idx, element);
7409 if (!element)
7410 return E_POINTER;
7412 if (idx >= collection->count)
7413 return E_INVALIDARG;
7415 *element = collection->elements[idx];
7416 if (*element)
7417 IUnknown_AddRef(*element);
7419 return *element ? S_OK : E_UNEXPECTED;
7422 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7424 struct collection *collection = impl_from_IMFCollection(iface);
7426 TRACE("%p, %p.\n", iface, element);
7428 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7429 sizeof(*collection->elements)))
7430 return E_OUTOFMEMORY;
7432 collection->elements[collection->count++] = element;
7433 if (element)
7434 IUnknown_AddRef(element);
7436 return S_OK;
7439 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7441 struct collection *collection = impl_from_IMFCollection(iface);
7442 size_t count;
7444 TRACE("%p, %u, %p.\n", iface, idx, element);
7446 if (!element)
7447 return E_POINTER;
7449 if (idx >= collection->count)
7450 return E_INVALIDARG;
7452 *element = collection->elements[idx];
7454 count = collection->count - idx - 1;
7455 if (count)
7456 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7457 collection->count--;
7459 return S_OK;
7462 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7464 struct collection *collection = impl_from_IMFCollection(iface);
7465 size_t i;
7467 TRACE("%p, %u, %p.\n", iface, idx, element);
7469 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7470 sizeof(*collection->elements)))
7471 return E_OUTOFMEMORY;
7473 if (idx < collection->count)
7475 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7476 (collection->count - idx) * sizeof(*collection->elements));
7477 collection->count++;
7479 else
7481 for (i = collection->count; i < idx; ++i)
7482 collection->elements[i] = NULL;
7483 collection->count = idx + 1;
7486 collection->elements[idx] = element;
7487 if (collection->elements[idx])
7488 IUnknown_AddRef(collection->elements[idx]);
7490 return S_OK;
7493 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7495 struct collection *collection = impl_from_IMFCollection(iface);
7497 TRACE("%p.\n", iface);
7499 collection_clear(collection);
7501 return S_OK;
7504 static const IMFCollectionVtbl mfcollectionvtbl =
7506 collection_QueryInterface,
7507 collection_AddRef,
7508 collection_Release,
7509 collection_GetElementCount,
7510 collection_GetElement,
7511 collection_AddElement,
7512 collection_RemoveElement,
7513 collection_InsertElementAt,
7514 collection_RemoveAllElements,
7517 /***********************************************************************
7518 * MFCreateCollection (mfplat.@)
7520 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7522 struct collection *object;
7524 TRACE("%p\n", collection);
7526 if (!collection)
7527 return E_POINTER;
7529 object = heap_alloc_zero(sizeof(*object));
7530 if (!object)
7531 return E_OUTOFMEMORY;
7533 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7534 object->refcount = 1;
7536 *collection = &object->IMFCollection_iface;
7538 return S_OK;
7541 /***********************************************************************
7542 * MFHeapAlloc (mfplat.@)
7544 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7546 TRACE("%lu, %#x, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7547 return HeapAlloc(GetProcessHeap(), flags, size);
7550 /***********************************************************************
7551 * MFHeapFree (mfplat.@)
7553 void WINAPI MFHeapFree(void *p)
7555 TRACE("%p\n", p);
7556 HeapFree(GetProcessHeap(), 0, p);
7559 /***********************************************************************
7560 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7562 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7564 FIXME("(%p, %p): stub\n", stream, bytestream);
7566 return E_NOTIMPL;
7569 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7571 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7573 if (IsEqualIID(riid, &IID_IMFClock) ||
7574 IsEqualIID(riid, &IID_IUnknown))
7576 *obj = iface;
7577 IMFClock_AddRef(iface);
7578 return S_OK;
7581 WARN("Unsupported %s.\n", debugstr_guid(riid));
7582 *obj = NULL;
7583 return E_NOINTERFACE;
7586 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7588 struct system_clock *clock = impl_from_IMFClock(iface);
7589 ULONG refcount = InterlockedIncrement(&clock->refcount);
7591 TRACE("%p, refcount %u.\n", iface, refcount);
7593 return refcount;
7596 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7598 struct system_clock *clock = impl_from_IMFClock(iface);
7599 ULONG refcount = InterlockedDecrement(&clock->refcount);
7601 TRACE("%p, refcount %u.\n", iface, refcount);
7603 if (!refcount)
7604 heap_free(clock);
7606 return refcount;
7609 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7611 TRACE("%p, %p.\n", iface, flags);
7613 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7614 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7616 return S_OK;
7619 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7620 MFTIME *system_time)
7622 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7624 *clock_time = *system_time = MFGetSystemTime();
7626 return S_OK;
7629 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7631 TRACE("%p, %p.\n", iface, key);
7633 *key = 0;
7635 return S_OK;
7638 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7640 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7642 *state = MFCLOCK_STATE_RUNNING;
7644 return S_OK;
7647 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7649 TRACE("%p, %p.\n", iface, props);
7651 if (!props)
7652 return E_POINTER;
7654 memset(props, 0, sizeof(*props));
7655 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7656 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7657 props->dwClockJitter = 1;
7659 return S_OK;
7662 static const IMFClockVtbl system_clock_vtbl =
7664 system_clock_QueryInterface,
7665 system_clock_AddRef,
7666 system_clock_Release,
7667 system_clock_GetClockCharacteristics,
7668 system_clock_GetCorrelatedTime,
7669 system_clock_GetContinuityKey,
7670 system_clock_GetState,
7671 system_clock_GetProperties,
7674 static HRESULT create_system_clock(IMFClock **clock)
7676 struct system_clock *object;
7678 if (!(object = heap_alloc(sizeof(*object))))
7679 return E_OUTOFMEMORY;
7681 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7682 object->refcount = 1;
7684 *clock = &object->IMFClock_iface;
7686 return S_OK;
7689 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7691 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7693 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7695 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7696 IsEqualIID(riid, &IID_IUnknown))
7698 *obj = &source->IMFPresentationTimeSource_iface;
7700 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
7702 *obj = &source->IMFClockStateSink_iface;
7704 else
7706 WARN("Unsupported %s.\n", debugstr_guid(riid));
7707 *obj = NULL;
7708 return E_NOINTERFACE;
7711 IUnknown_AddRef((IUnknown *)*obj);
7712 return S_OK;
7715 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
7717 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7718 ULONG refcount = InterlockedIncrement(&source->refcount);
7720 TRACE("%p, refcount %u.\n", iface, refcount);
7722 return refcount;
7725 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
7727 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7728 ULONG refcount = InterlockedDecrement(&source->refcount);
7730 TRACE("%p, refcount %u.\n", iface, refcount);
7732 if (!refcount)
7734 if (source->clock)
7735 IMFClock_Release(source->clock);
7736 DeleteCriticalSection(&source->cs);
7737 heap_free(source);
7740 return refcount;
7743 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
7745 TRACE("%p, %p.\n", iface, flags);
7747 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7749 return S_OK;
7752 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
7753 LONGLONG *clock_time, MFTIME *system_time)
7755 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7756 HRESULT hr;
7758 TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
7760 EnterCriticalSection(&source->cs);
7761 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
7763 if (source->state == MFCLOCK_STATE_RUNNING)
7765 system_time_source_apply_rate(source, clock_time);
7766 *clock_time += source->start_offset;
7768 else
7769 *clock_time = source->start_offset;
7771 LeaveCriticalSection(&source->cs);
7773 return hr;
7776 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
7778 TRACE("%p, %p.\n", iface, key);
7780 *key = 0;
7782 return S_OK;
7785 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
7786 MFCLOCK_STATE *state)
7788 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7790 TRACE("%p, %#x, %p.\n", iface, reserved, state);
7792 EnterCriticalSection(&source->cs);
7793 *state = source->state;
7794 LeaveCriticalSection(&source->cs);
7796 return S_OK;
7799 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
7801 TRACE("%p, %p.\n", iface, props);
7803 if (!props)
7804 return E_POINTER;
7806 memset(props, 0, sizeof(*props));
7807 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7808 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7809 props->dwClockJitter = 1;
7811 return S_OK;
7814 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
7816 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7818 TRACE("%p, %p.\n", iface, clock);
7820 *clock = source->clock;
7821 IMFClock_AddRef(*clock);
7823 return S_OK;
7826 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
7828 system_time_source_QueryInterface,
7829 system_time_source_AddRef,
7830 system_time_source_Release,
7831 system_time_source_GetClockCharacteristics,
7832 system_time_source_GetCorrelatedTime,
7833 system_time_source_GetContinuityKey,
7834 system_time_source_GetState,
7835 system_time_source_GetProperties,
7836 system_time_source_GetUnderlyingClock,
7839 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
7841 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7842 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
7845 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
7847 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7848 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
7851 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
7853 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7854 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
7857 enum clock_command
7859 CLOCK_CMD_START = 0,
7860 CLOCK_CMD_STOP,
7861 CLOCK_CMD_PAUSE,
7862 CLOCK_CMD_RESTART,
7863 CLOCK_CMD_MAX,
7866 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
7868 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
7869 { /* S S* P R */
7870 /* INVALID */ { 1, 0, 1, 0 },
7871 /* RUNNING */ { 1, 1, 1, 0 },
7872 /* STOPPED */ { 1, 1, 0, 0 },
7873 /* PAUSED */ { 1, 1, 0, 1 },
7875 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
7877 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
7878 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
7879 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
7880 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
7883 /* Special case that go against usual state change vs return value behavior. */
7884 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
7885 return S_OK;
7887 if (!state_change_is_allowed[source->state][command])
7888 return MF_E_INVALIDREQUEST;
7890 source->state = states[command];
7892 return S_OK;
7895 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
7896 LONGLONG start_offset)
7898 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7899 MFCLOCK_STATE state;
7900 HRESULT hr;
7902 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
7904 EnterCriticalSection(&source->cs);
7905 state = source->state;
7906 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
7908 system_time_source_apply_rate(source, &system_time);
7909 if (start_offset == PRESENTATION_CURRENT_POSITION)
7911 switch (state)
7913 case MFCLOCK_STATE_RUNNING:
7914 break;
7915 case MFCLOCK_STATE_PAUSED:
7916 source->start_offset -= system_time;
7917 break;
7918 default:
7919 source->start_offset = -system_time;
7920 break;
7924 else
7926 source->start_offset = -system_time + start_offset;
7929 LeaveCriticalSection(&source->cs);
7931 return hr;
7934 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
7936 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7937 HRESULT hr;
7939 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7941 EnterCriticalSection(&source->cs);
7942 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
7943 source->start_offset = 0;
7944 LeaveCriticalSection(&source->cs);
7946 return hr;
7949 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
7951 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7952 HRESULT hr;
7954 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7956 EnterCriticalSection(&source->cs);
7957 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
7959 system_time_source_apply_rate(source, &system_time);
7960 source->start_offset += system_time;
7962 LeaveCriticalSection(&source->cs);
7964 return hr;
7967 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
7969 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7970 HRESULT hr;
7972 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
7974 EnterCriticalSection(&source->cs);
7975 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
7977 system_time_source_apply_rate(source, &system_time);
7978 source->start_offset -= system_time;
7980 LeaveCriticalSection(&source->cs);
7982 return hr;
7985 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
7987 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
7988 double intpart;
7990 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
7992 if (rate == 0.0f)
7993 return MF_E_UNSUPPORTED_RATE;
7995 modf(rate, &intpart);
7997 EnterCriticalSection(&source->cs);
7998 source->rate = rate;
7999 source->i_rate = rate == intpart ? rate : 0;
8000 LeaveCriticalSection(&source->cs);
8002 return S_OK;
8005 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8007 system_time_source_sink_QueryInterface,
8008 system_time_source_sink_AddRef,
8009 system_time_source_sink_Release,
8010 system_time_source_sink_OnClockStart,
8011 system_time_source_sink_OnClockStop,
8012 system_time_source_sink_OnClockPause,
8013 system_time_source_sink_OnClockRestart,
8014 system_time_source_sink_OnClockSetRate,
8017 /***********************************************************************
8018 * MFCreateSystemTimeSource (mfplat.@)
8020 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8022 struct system_time_source *object;
8023 HRESULT hr;
8025 TRACE("%p.\n", time_source);
8027 object = heap_alloc_zero(sizeof(*object));
8028 if (!object)
8029 return E_OUTOFMEMORY;
8031 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8032 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8033 object->refcount = 1;
8034 object->rate = 1.0f;
8035 object->i_rate = 1;
8036 InitializeCriticalSection(&object->cs);
8038 if (FAILED(hr = create_system_clock(&object->clock)))
8040 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8041 return hr;
8044 *time_source = &object->IMFPresentationTimeSource_iface;
8046 return S_OK;
8049 struct async_create_file
8051 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8052 LONG refcount;
8053 MF_FILE_ACCESSMODE access_mode;
8054 MF_FILE_OPENMODE open_mode;
8055 MF_FILE_FLAGS flags;
8056 WCHAR *path;
8059 struct async_create_file_result
8061 struct list entry;
8062 IRtwqAsyncResult *result;
8063 IMFByteStream *stream;
8066 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8067 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8069 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8071 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8074 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8076 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8077 IsEqualIID(riid, &IID_IUnknown))
8079 *obj = iface;
8080 IRtwqAsyncCallback_AddRef(iface);
8081 return S_OK;
8084 *obj = NULL;
8085 return E_NOINTERFACE;
8088 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8090 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8091 ULONG refcount = InterlockedIncrement(&async->refcount);
8093 TRACE("%p, refcount %u.\n", iface, refcount);
8095 return refcount;
8098 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8100 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8101 ULONG refcount = InterlockedDecrement(&async->refcount);
8103 TRACE("%p, refcount %u.\n", iface, refcount);
8105 if (!refcount)
8107 heap_free(async->path);
8108 heap_free(async);
8111 return refcount;
8114 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8116 return E_NOTIMPL;
8119 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8121 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8122 IRtwqAsyncResult *caller;
8123 IMFByteStream *stream;
8124 HRESULT hr;
8126 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8128 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8129 if (SUCCEEDED(hr))
8131 struct async_create_file_result *result_item;
8133 result_item = heap_alloc(sizeof(*result_item));
8134 if (result_item)
8136 result_item->result = caller;
8137 IRtwqAsyncResult_AddRef(caller);
8138 result_item->stream = stream;
8139 IMFByteStream_AddRef(stream);
8141 EnterCriticalSection(&async_create_file_cs);
8142 list_add_tail(&async_create_file_results, &result_item->entry);
8143 LeaveCriticalSection(&async_create_file_cs);
8146 IMFByteStream_Release(stream);
8148 else
8149 IRtwqAsyncResult_SetStatus(caller, hr);
8151 RtwqInvokeCallback(caller);
8153 return S_OK;
8156 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8158 async_create_file_callback_QueryInterface,
8159 async_create_file_callback_AddRef,
8160 async_create_file_callback_Release,
8161 async_create_file_callback_GetParameters,
8162 async_create_file_callback_Invoke,
8165 /***********************************************************************
8166 * MFBeginCreateFile (mfplat.@)
8168 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8169 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8171 struct async_create_file *async = NULL;
8172 IRtwqAsyncResult *caller, *item = NULL;
8173 HRESULT hr;
8175 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8176 cancel_cookie);
8178 if (cancel_cookie)
8179 *cancel_cookie = NULL;
8181 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8182 return hr;
8184 async = heap_alloc(sizeof(*async));
8185 if (!async)
8187 hr = E_OUTOFMEMORY;
8188 goto failed;
8191 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8192 async->refcount = 1;
8193 async->access_mode = access_mode;
8194 async->open_mode = open_mode;
8195 async->flags = flags;
8196 if (FAILED(hr = heap_strdupW(path, &async->path)))
8197 goto failed;
8199 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8200 if (FAILED(hr))
8201 goto failed;
8203 if (cancel_cookie)
8205 *cancel_cookie = (IUnknown *)caller;
8206 IUnknown_AddRef(*cancel_cookie);
8209 hr = RtwqInvokeCallback(item);
8211 failed:
8212 if (async)
8213 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8214 if (item)
8215 IRtwqAsyncResult_Release(item);
8216 if (caller)
8217 IRtwqAsyncResult_Release(caller);
8219 return hr;
8222 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8224 struct async_create_file_result *item;
8225 HRESULT hr = MF_E_UNEXPECTED;
8226 IRtwqAsyncResult *result;
8228 *stream = NULL;
8230 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8231 return hr;
8233 EnterCriticalSection(&async_create_file_cs);
8235 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8237 if (result == item->result)
8239 *stream = item->stream;
8240 IRtwqAsyncResult_Release(item->result);
8241 list_remove(&item->entry);
8242 heap_free(item);
8243 break;
8247 LeaveCriticalSection(&async_create_file_cs);
8249 if (*stream)
8250 hr = IRtwqAsyncResult_GetStatus(result);
8252 IRtwqAsyncResult_Release(result);
8254 return hr;
8257 /***********************************************************************
8258 * MFEndCreateFile (mfplat.@)
8260 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8262 TRACE("%p, %p.\n", result, stream);
8264 return async_create_file_pull_result((IUnknown *)result, stream);
8267 /***********************************************************************
8268 * MFCancelCreateFile (mfplat.@)
8270 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8272 IMFByteStream *stream = NULL;
8273 HRESULT hr;
8275 TRACE("%p.\n", cancel_cookie);
8277 hr = async_create_file_pull_result(cancel_cookie, &stream);
8279 if (stream)
8280 IMFByteStream_Release(stream);
8282 return hr;
8285 /***********************************************************************
8286 * MFRegisterLocalSchemeHandler (mfplat.@)
8288 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8290 struct local_handler *handler;
8291 HRESULT hr;
8293 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8295 if (!scheme || !activate)
8296 return E_INVALIDARG;
8298 if (!(handler = heap_alloc(sizeof(*handler))))
8299 return E_OUTOFMEMORY;
8301 if (FAILED(hr = heap_strdupW(scheme, &handler->u.scheme)))
8303 heap_free(handler);
8304 return hr;
8306 handler->activate = activate;
8307 IMFActivate_AddRef(handler->activate);
8309 EnterCriticalSection(&local_handlers_section);
8310 list_add_head(&local_scheme_handlers, &handler->entry);
8311 LeaveCriticalSection(&local_handlers_section);
8313 return S_OK;
8316 /***********************************************************************
8317 * MFRegisterLocalByteStreamHandler (mfplat.@)
8319 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8321 struct local_handler *handler;
8322 HRESULT hr;
8324 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8326 if ((!extension && !mime) || !activate)
8327 return E_INVALIDARG;
8329 if (!(handler = heap_alloc_zero(sizeof(*handler))))
8330 return E_OUTOFMEMORY;
8332 hr = heap_strdupW(extension, &handler->u.bytestream.extension);
8333 if (SUCCEEDED(hr))
8334 hr = heap_strdupW(mime, &handler->u.bytestream.mime);
8336 if (FAILED(hr))
8337 goto failed;
8339 EnterCriticalSection(&local_handlers_section);
8340 list_add_head(&local_bytestream_handlers, &handler->entry);
8341 LeaveCriticalSection(&local_handlers_section);
8343 return hr;
8345 failed:
8346 heap_free(handler->u.bytestream.extension);
8347 heap_free(handler->u.bytestream.mime);
8348 heap_free(handler);
8350 return hr;
8353 struct property_store
8355 IPropertyStore IPropertyStore_iface;
8356 LONG refcount;
8357 CRITICAL_SECTION cs;
8358 size_t count, capacity;
8359 struct
8361 PROPERTYKEY key;
8362 PROPVARIANT value;
8363 } *values;
8366 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8368 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8371 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8373 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8375 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8377 *obj = iface;
8378 IPropertyStore_AddRef(iface);
8379 return S_OK;
8382 *obj = NULL;
8383 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8384 return E_NOINTERFACE;
8387 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8389 struct property_store *store = impl_from_IPropertyStore(iface);
8390 ULONG refcount = InterlockedIncrement(&store->refcount);
8392 TRACE("%p, refcount %d.\n", iface, refcount);
8394 return refcount;
8397 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8399 struct property_store *store = impl_from_IPropertyStore(iface);
8400 ULONG refcount = InterlockedDecrement(&store->refcount);
8402 TRACE("%p, refcount %d.\n", iface, refcount);
8404 if (!refcount)
8406 DeleteCriticalSection(&store->cs);
8407 heap_free(store->values);
8408 heap_free(store);
8411 return refcount;
8414 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8416 struct property_store *store = impl_from_IPropertyStore(iface);
8418 TRACE("%p, %p.\n", iface, count);
8420 if (!count)
8421 return E_INVALIDARG;
8423 EnterCriticalSection(&store->cs);
8424 *count = store->count;
8425 LeaveCriticalSection(&store->cs);
8426 return S_OK;
8429 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8431 struct property_store *store = impl_from_IPropertyStore(iface);
8433 TRACE("%p, %u, %p.\n", iface, index, key);
8435 EnterCriticalSection(&store->cs);
8437 if (index >= store->count)
8439 LeaveCriticalSection(&store->cs);
8440 return E_INVALIDARG;
8443 *key = store->values[index].key;
8445 LeaveCriticalSection(&store->cs);
8446 return S_OK;
8449 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8451 struct property_store *store = impl_from_IPropertyStore(iface);
8452 unsigned int i;
8454 TRACE("%p, %p, %p.\n", iface, key, value);
8456 if (!value)
8457 return E_INVALIDARG;
8459 if (!key)
8460 return S_FALSE;
8462 EnterCriticalSection(&store->cs);
8464 for (i = 0; i < store->count; ++i)
8466 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8468 PropVariantCopy(value, &store->values[i].value);
8469 LeaveCriticalSection(&store->cs);
8470 return S_OK;
8474 LeaveCriticalSection(&store->cs);
8475 return S_FALSE;
8478 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8480 struct property_store *store = impl_from_IPropertyStore(iface);
8481 unsigned int i;
8483 TRACE("%p, %p, %p.\n", iface, key, value);
8485 EnterCriticalSection(&store->cs);
8487 for (i = 0; i < store->count; ++i)
8489 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8491 PropVariantCopy(&store->values[i].value, value);
8492 LeaveCriticalSection(&store->cs);
8493 return S_OK;
8497 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8499 LeaveCriticalSection(&store->cs);
8500 return E_OUTOFMEMORY;
8503 store->values[store->count].key = *key;
8504 PropVariantCopy(&store->values[store->count].value, value);
8505 ++store->count;
8507 LeaveCriticalSection(&store->cs);
8508 return S_OK;
8511 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8513 TRACE("%p.\n", iface);
8515 return E_NOTIMPL;
8518 static const IPropertyStoreVtbl property_store_vtbl =
8520 property_store_QueryInterface,
8521 property_store_AddRef,
8522 property_store_Release,
8523 property_store_GetCount,
8524 property_store_GetAt,
8525 property_store_GetValue,
8526 property_store_SetValue,
8527 property_store_Commit,
8530 /***********************************************************************
8531 * CreatePropertyStore (mfplat.@)
8533 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8535 struct property_store *object;
8537 TRACE("%p.\n", store);
8539 if (!store)
8540 return E_INVALIDARG;
8542 if (!(object = heap_alloc_zero(sizeof(*object))))
8543 return E_OUTOFMEMORY;
8545 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8546 object->refcount = 1;
8547 InitializeCriticalSection(&object->cs);
8549 TRACE("Created store %p.\n", object);
8550 *store = &object->IPropertyStore_iface;
8552 return S_OK;
8555 enum dxgi_device_handle_flags
8557 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8558 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8559 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8562 struct dxgi_device_manager
8564 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8565 LONG refcount;
8566 UINT token;
8567 IDXGIDevice *device;
8569 unsigned int *handles;
8570 size_t count;
8571 size_t capacity;
8573 unsigned int locks;
8574 unsigned int locking_tid;
8576 CRITICAL_SECTION cs;
8577 CONDITION_VARIABLE lock;
8580 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8582 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8585 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8587 if (!hdevice || hdevice > ULongToHandle(manager->count))
8588 return E_HANDLE;
8589 *idx = (ULONG_PTR)hdevice - 1;
8590 return S_OK;
8593 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8595 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8597 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8598 IsEqualGUID(riid, &IID_IUnknown))
8600 *obj = iface;
8601 IMFDXGIDeviceManager_AddRef(iface);
8602 return S_OK;
8605 WARN("Unsupported %s.\n", debugstr_guid(riid));
8606 *obj = NULL;
8607 return E_NOINTERFACE;
8610 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8612 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8613 ULONG refcount = InterlockedIncrement(&manager->refcount);
8615 TRACE("%p, refcount %u.\n", iface, refcount);
8617 return refcount;
8620 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8622 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8623 ULONG refcount = InterlockedDecrement(&manager->refcount);
8625 TRACE("%p, refcount %u.\n", iface, refcount);
8627 if (!refcount)
8629 if (manager->device)
8630 IDXGIDevice_Release(manager->device);
8631 DeleteCriticalSection(&manager->cs);
8632 heap_free(manager->handles);
8633 heap_free(manager);
8636 return refcount;
8639 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8641 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8642 return;
8644 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8645 manager->locks++;
8648 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8650 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8651 return;
8653 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8654 if (!--manager->locks)
8655 manager->locking_tid = 0;
8658 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8660 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8661 HRESULT hr;
8662 size_t idx;
8664 TRACE("%p, %p.\n", iface, hdevice);
8666 EnterCriticalSection(&manager->cs);
8668 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8670 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8672 dxgi_device_manager_unlock_handle(manager, idx);
8673 manager->handles[idx] = 0;
8674 if (idx == manager->count - 1)
8675 manager->count--;
8677 else
8678 hr = E_HANDLE;
8681 LeaveCriticalSection(&manager->cs);
8683 WakeAllConditionVariable(&manager->lock);
8685 return hr;
8688 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8689 REFIID riid, void **service)
8691 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8692 HRESULT hr;
8693 size_t idx;
8695 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service);
8697 EnterCriticalSection(&manager->cs);
8699 if (!manager->device)
8700 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8701 else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8703 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8704 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8705 else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8706 hr = IDXGIDevice_QueryInterface(manager->device, riid, service);
8707 else
8708 hr = E_HANDLE;
8711 LeaveCriticalSection(&manager->cs);
8713 return hr;
8716 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8717 REFIID riid, void **obj, BOOL block)
8719 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8720 HRESULT hr;
8721 size_t idx;
8723 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
8725 EnterCriticalSection(&manager->cs);
8727 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8729 if (!manager->device)
8731 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8733 else if (manager->locking_tid == GetCurrentThreadId())
8735 if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8736 dxgi_device_manager_lock_handle(manager, idx);
8738 else if (manager->locking_tid && !block)
8740 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
8742 else
8744 while (manager->locking_tid)
8746 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
8749 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8751 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8752 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8753 else if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
8755 manager->locking_tid = GetCurrentThreadId();
8756 dxgi_device_manager_lock_handle(manager, idx);
8762 LeaveCriticalSection(&manager->cs);
8764 return hr;
8767 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
8769 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8770 HRESULT hr = S_OK;
8771 size_t i;
8773 TRACE("%p, %p.\n", iface, hdevice);
8775 *hdevice = NULL;
8777 EnterCriticalSection(&manager->cs);
8779 if (!manager->device)
8780 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8781 else
8783 for (i = 0; i < manager->count; ++i)
8785 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8787 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
8788 *hdevice = ULongToHandle(i + 1);
8789 break;
8793 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
8794 sizeof(*manager->handles)))
8796 *hdevice = ULongToHandle(manager->count + 1);
8797 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
8799 else
8800 hr = E_OUTOFMEMORY;
8803 LeaveCriticalSection(&manager->cs);
8805 return hr;
8808 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
8810 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8811 IDXGIDevice *dxgi_device;
8812 size_t i;
8814 TRACE("%p, %p, %u.\n", iface, device, token);
8816 if (!device || token != manager->token)
8817 return E_INVALIDARG;
8819 if (FAILED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device)))
8820 return E_INVALIDARG;
8822 EnterCriticalSection(&manager->cs);
8824 if (manager->device)
8826 for (i = 0; i < manager->count; ++i)
8828 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
8829 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8831 manager->locking_tid = 0;
8832 manager->locks = 0;
8833 IDXGIDevice_Release(manager->device);
8835 manager->device = dxgi_device;
8837 LeaveCriticalSection(&manager->cs);
8839 WakeAllConditionVariable(&manager->lock);
8841 return S_OK;
8844 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8846 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8847 HRESULT hr;
8848 size_t idx;
8850 TRACE("%p, %p.\n", iface, hdevice);
8852 EnterCriticalSection(&manager->cs);
8854 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8856 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
8857 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
8858 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
8859 hr = E_HANDLE;
8862 LeaveCriticalSection(&manager->cs);
8864 return hr;
8867 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8868 BOOL savestate)
8870 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8871 HRESULT hr = E_FAIL;
8872 size_t idx;
8874 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
8876 EnterCriticalSection(&manager->cs);
8878 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8880 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
8881 if (SUCCEEDED(hr))
8882 dxgi_device_manager_unlock_handle(manager, idx);
8885 LeaveCriticalSection(&manager->cs);
8887 WakeAllConditionVariable(&manager->lock);
8889 return hr;
8892 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
8894 dxgi_device_manager_QueryInterface,
8895 dxgi_device_manager_AddRef,
8896 dxgi_device_manager_Release,
8897 dxgi_device_manager_CloseDeviceHandle,
8898 dxgi_device_manager_GetVideoService,
8899 dxgi_device_manager_LockDevice,
8900 dxgi_device_manager_OpenDeviceHandle,
8901 dxgi_device_manager_ResetDevice,
8902 dxgi_device_manager_TestDevice,
8903 dxgi_device_manager_UnlockDevice,
8906 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
8908 struct dxgi_device_manager *object;
8910 TRACE("%p, %p.\n", token, manager);
8912 if (!token || !manager)
8913 return E_POINTER;
8915 if (!(object = heap_alloc_zero(sizeof(*object))))
8916 return E_OUTOFMEMORY;
8918 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
8919 object->refcount = 1;
8920 object->token = GetTickCount();
8921 InitializeCriticalSection(&object->cs);
8922 InitializeConditionVariable(&object->lock);
8924 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
8926 *token = object->token;
8927 *manager = &object->IMFDXGIDeviceManager_iface;
8929 return S_OK;