ddraw: Set dwMaxVertexCount to 2048.
[wine.git] / dlls / mfplat / main.c
blobaa987ff0496fc84a966903dda02941249b65d84f
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>
22 #include <limits.h>
24 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winreg.h"
30 #include "initguid.h"
31 #include "rtworkq.h"
32 #include "ole2.h"
33 #include "propsys.h"
34 #include "d3d11.h"
35 #include "uuids.h"
37 #include "wine/list.h"
39 #include "mfplat_private.h"
40 #include "mfreadwrite.h"
41 #include "mfmediaengine.h"
42 #include "propvarutil.h"
43 #include "strsafe.h"
44 #undef INITGUID
45 #include "evr.h"
46 /* mfd3d12 guids are not included in mfuuid */
47 #define INITGUID
48 #undef EXTERN_GUID
49 #define EXTERN_GUID DEFINE_GUID
50 #include "initguid.h"
51 #include "mfd3d12.h"
53 #include "bcrypt.h"
54 #include "pathcch.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
58 struct local_handler
60 struct list entry;
61 union
63 WCHAR *scheme;
64 struct
66 WCHAR *extension;
67 WCHAR *mime;
68 } bytestream;
69 } u;
70 IMFActivate *activate;
73 static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
75 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
76 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
78 struct mft_registration
80 struct list entry;
81 IClassFactory *factory;
82 CLSID clsid;
83 GUID category;
84 WCHAR *name;
85 DWORD flags;
86 MFT_REGISTER_TYPE_INFO *input_types;
87 UINT32 input_types_count;
88 MFT_REGISTER_TYPE_INFO *output_types;
89 UINT32 output_types_count;
90 BOOL local;
93 static const char *debugstr_reg_typeinfo(const MFT_REGISTER_TYPE_INFO *info)
95 return info ? wine_dbg_sprintf("%p{%s,%s}", info, debugstr_mf_guid(&info->guidMajorType),
96 debugstr_mf_guid(&info->guidSubtype)) : wine_dbg_sprintf("%p", info);
99 static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
101 static struct list local_mfts = LIST_INIT(local_mfts);
103 struct transform_activate
105 struct attributes attributes;
106 IMFActivate IMFActivate_iface;
107 IClassFactory *factory;
108 IMFTransform *transform;
111 struct system_clock
113 IMFClock IMFClock_iface;
114 LONG refcount;
117 struct system_time_source
119 IMFPresentationTimeSource IMFPresentationTimeSource_iface;
120 IMFClockStateSink IMFClockStateSink_iface;
121 LONG refcount;
122 MFCLOCK_STATE state;
123 IMFClock *clock;
124 LONGLONG start_offset;
125 LONGLONG system_time;
126 LONGLONG clock_time;
127 float rate;
128 int i_rate;
129 CRITICAL_SECTION cs;
132 static void system_time_source_update_clock_time(struct system_time_source *source, LONGLONG system_time)
134 LONGLONG diff = system_time - source->system_time;
135 if (source->i_rate) diff *= source->i_rate;
136 else if (source->rate != 1.0f) diff *= source->rate;
137 source->clock_time += diff;
138 source->system_time = system_time;
141 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
143 return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
146 static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
148 return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
151 static struct system_clock *impl_from_IMFClock(IMFClock *iface)
153 return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
156 static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface)
158 return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface);
161 static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out)
163 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
165 if (IsEqualIID(riid, &IID_IMFActivate) ||
166 IsEqualIID(riid, &IID_IMFAttributes) ||
167 IsEqualIID(riid, &IID_IUnknown))
169 *out = iface;
170 IMFActivate_AddRef(iface);
171 return S_OK;
174 WARN("Unsupported %s.\n", debugstr_guid(riid));
175 *out = NULL;
176 return E_NOINTERFACE;
179 static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface)
181 struct transform_activate *activate = impl_from_IMFActivate(iface);
182 ULONG refcount = InterlockedIncrement(&activate->attributes.ref);
184 TRACE("%p, refcount %lu.\n", iface, refcount);
186 return refcount;
189 static ULONG WINAPI transform_activate_Release(IMFActivate *iface)
191 struct transform_activate *activate = impl_from_IMFActivate(iface);
192 ULONG refcount = InterlockedDecrement(&activate->attributes.ref);
194 TRACE("%p, refcount %lu.\n", iface, refcount);
196 if (!refcount)
198 clear_attributes_object(&activate->attributes);
199 if (activate->factory)
200 IClassFactory_Release(activate->factory);
201 if (activate->transform)
202 IMFTransform_Release(activate->transform);
203 free(activate);
206 return refcount;
209 static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value)
211 struct transform_activate *activate = impl_from_IMFActivate(iface);
213 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
215 return attributes_GetItem(&activate->attributes, key, value);
218 static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
220 struct transform_activate *activate = impl_from_IMFActivate(iface);
222 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
224 return attributes_GetItemType(&activate->attributes, key, type);
227 static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value,
228 BOOL *result)
230 struct transform_activate *activate = impl_from_IMFActivate(iface);
232 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
234 return attributes_CompareItem(&activate->attributes, key, value, result);
237 static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs,
238 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
240 struct transform_activate *activate = impl_from_IMFActivate(iface);
242 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
244 return attributes_Compare(&activate->attributes, theirs, match_type, ret);
247 static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value)
249 struct transform_activate *activate = impl_from_IMFActivate(iface);
251 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
253 return attributes_GetUINT32(&activate->attributes, key, value);
256 static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value)
258 struct transform_activate *activate = impl_from_IMFActivate(iface);
260 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
262 return attributes_GetUINT64(&activate->attributes, key, value);
265 static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value)
267 struct transform_activate *activate = impl_from_IMFActivate(iface);
269 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
271 return attributes_GetDouble(&activate->attributes, key, value);
274 static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value)
276 struct transform_activate *activate = impl_from_IMFActivate(iface);
278 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
280 return attributes_GetGUID(&activate->attributes, key, value);
283 static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length)
285 struct transform_activate *activate = impl_from_IMFActivate(iface);
287 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
289 return attributes_GetStringLength(&activate->attributes, key, length);
292 static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value,
293 UINT32 size, UINT32 *length)
295 struct transform_activate *activate = impl_from_IMFActivate(iface);
297 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
299 return attributes_GetString(&activate->attributes, key, value, size, length);
302 static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value,
303 UINT32 *length)
305 struct transform_activate *activate = impl_from_IMFActivate(iface);
307 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
309 return attributes_GetAllocatedString(&activate->attributes, key, value, length);
312 static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size)
314 struct transform_activate *activate = impl_from_IMFActivate(iface);
316 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
318 return attributes_GetBlobSize(&activate->attributes, key, size);
321 static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize,
322 UINT32 *blobsize)
324 struct transform_activate *activate = impl_from_IMFActivate(iface);
326 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
328 return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize);
331 static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size)
333 struct transform_activate *activate = impl_from_IMFActivate(iface);
335 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
337 return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size);
340 static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out)
342 struct transform_activate *activate = impl_from_IMFActivate(iface);
344 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
346 return attributes_GetUnknown(&activate->attributes, key, riid, out);
349 static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value)
351 struct transform_activate *activate = impl_from_IMFActivate(iface);
353 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
355 return attributes_SetItem(&activate->attributes, key, value);
358 static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key)
360 struct transform_activate *activate = impl_from_IMFActivate(iface);
362 TRACE("%p, %s.\n", iface, debugstr_attr(key));
364 return attributes_DeleteItem(&activate->attributes, key);
367 static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface)
369 struct transform_activate *activate = impl_from_IMFActivate(iface);
371 TRACE("%p.\n", iface);
373 return attributes_DeleteAllItems(&activate->attributes);
376 static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value)
378 struct transform_activate *activate = impl_from_IMFActivate(iface);
380 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
382 return attributes_SetUINT32(&activate->attributes, key, value);
385 static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value)
387 struct transform_activate *activate = impl_from_IMFActivate(iface);
389 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
391 return attributes_SetUINT64(&activate->attributes, key, value);
394 static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value)
396 struct transform_activate *activate = impl_from_IMFActivate(iface);
398 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
400 return attributes_SetDouble(&activate->attributes, key, value);
403 static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value)
405 struct transform_activate *activate = impl_from_IMFActivate(iface);
407 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
409 return attributes_SetGUID(&activate->attributes, key, value);
412 static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value)
414 struct transform_activate *activate = impl_from_IMFActivate(iface);
416 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
418 return attributes_SetString(&activate->attributes, key, value);
421 static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size)
423 struct transform_activate *activate = impl_from_IMFActivate(iface);
425 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
427 return attributes_SetBlob(&activate->attributes, key, buf, size);
430 static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown)
432 struct transform_activate *activate = impl_from_IMFActivate(iface);
434 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
436 return attributes_SetUnknown(&activate->attributes, key, unknown);
439 static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface)
441 struct transform_activate *activate = impl_from_IMFActivate(iface);
443 TRACE("%p.\n", iface);
445 return attributes_LockStore(&activate->attributes);
448 static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface)
450 struct transform_activate *activate = impl_from_IMFActivate(iface);
452 TRACE("%p.\n", iface);
454 return attributes_UnlockStore(&activate->attributes);
457 static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count)
459 struct transform_activate *activate = impl_from_IMFActivate(iface);
461 TRACE("%p, %p.\n", iface, count);
463 return attributes_GetCount(&activate->attributes, count);
466 static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key,
467 PROPVARIANT *value)
469 struct transform_activate *activate = impl_from_IMFActivate(iface);
471 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
473 return attributes_GetItemByIndex(&activate->attributes, index, key, value);
476 static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest)
478 struct transform_activate *activate = impl_from_IMFActivate(iface);
480 TRACE("%p, %p.\n", iface, dest);
482 return attributes_CopyAllItems(&activate->attributes, dest);
485 static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj)
487 struct transform_activate *activate = impl_from_IMFActivate(iface);
488 CLSID clsid;
489 HRESULT hr;
491 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
493 EnterCriticalSection(&activate->attributes.cs);
495 if (!activate->transform)
497 if (activate->factory)
499 if (FAILED(hr = IClassFactory_CreateInstance(activate->factory, NULL, &IID_IMFTransform,
500 (void **)&activate->transform)))
502 hr = MF_E_INVALIDREQUEST;
505 else
507 if (SUCCEEDED(hr = attributes_GetGUID(&activate->attributes, &MFT_TRANSFORM_CLSID_Attribute, &clsid)))
509 if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
510 (void **)&activate->transform)))
512 hr = MF_E_INVALIDREQUEST;
518 if (activate->transform)
519 hr = IMFTransform_QueryInterface(activate->transform, riid, obj);
521 LeaveCriticalSection(&activate->attributes.cs);
523 return hr;
526 static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface)
528 struct transform_activate *activate = impl_from_IMFActivate(iface);
530 TRACE("%p.\n", iface);
532 EnterCriticalSection(&activate->attributes.cs);
534 if (activate->transform)
536 IMFTransform_Release(activate->transform);
537 activate->transform = NULL;
540 LeaveCriticalSection(&activate->attributes.cs);
542 return S_OK;
545 static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface)
547 TRACE("%p.\n", iface);
549 return E_NOTIMPL;
552 static const IMFActivateVtbl transform_activate_vtbl =
554 transform_activate_QueryInterface,
555 transform_activate_AddRef,
556 transform_activate_Release,
557 transform_activate_GetItem,
558 transform_activate_GetItemType,
559 transform_activate_CompareItem,
560 transform_activate_Compare,
561 transform_activate_GetUINT32,
562 transform_activate_GetUINT64,
563 transform_activate_GetDouble,
564 transform_activate_GetGUID,
565 transform_activate_GetStringLength,
566 transform_activate_GetString,
567 transform_activate_GetAllocatedString,
568 transform_activate_GetBlobSize,
569 transform_activate_GetBlob,
570 transform_activate_GetAllocatedBlob,
571 transform_activate_GetUnknown,
572 transform_activate_SetItem,
573 transform_activate_DeleteItem,
574 transform_activate_DeleteAllItems,
575 transform_activate_SetUINT32,
576 transform_activate_SetUINT64,
577 transform_activate_SetDouble,
578 transform_activate_SetGUID,
579 transform_activate_SetString,
580 transform_activate_SetBlob,
581 transform_activate_SetUnknown,
582 transform_activate_LockStore,
583 transform_activate_UnlockStore,
584 transform_activate_GetCount,
585 transform_activate_GetItemByIndex,
586 transform_activate_CopyAllItems,
587 transform_activate_ActivateObject,
588 transform_activate_ShutdownObject,
589 transform_activate_DetachObject,
592 static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate)
594 struct transform_activate *object;
595 HRESULT hr;
597 if (!(object = calloc(1, sizeof(*object))))
598 return E_OUTOFMEMORY;
600 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
602 free(object);
603 return hr;
606 object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl;
607 object->factory = factory;
608 if (object->factory)
609 IClassFactory_AddRef(object->factory);
611 *activate = &object->IMFActivate_iface;
613 return S_OK;
616 HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate)
618 TRACE("%p.\n", activate);
620 return create_transform_activate(NULL, activate);
623 static const WCHAR transform_keyW[] = L"MediaFoundation\\Transforms";
624 static const WCHAR categories_keyW[] = L"MediaFoundation\\Transforms\\Categories";
626 static const BYTE guid_conv_table[256] =
628 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
629 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
630 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
631 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
632 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
634 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
637 static WCHAR* guid_to_string(WCHAR *str, REFGUID guid)
639 swprintf(str, 39, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
640 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
641 guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
642 guid->Data4[6], guid->Data4[7]);
644 return str;
647 static inline BOOL is_valid_hex(WCHAR c)
649 if (!(((c >= '0') && (c <= '9')) ||
650 ((c >= 'a') && (c <= 'f')) ||
651 ((c >= 'A') && (c <= 'F'))))
652 return FALSE;
653 return TRUE;
656 static BOOL GUIDFromString(LPCWSTR s, GUID *id)
658 int i;
660 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
662 id->Data1 = 0;
663 for (i = 0; i < 8; i++)
665 if (!is_valid_hex(s[i])) return FALSE;
666 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
668 if (s[8]!='-') return FALSE;
670 id->Data2 = 0;
671 for (i = 9; i < 13; i++)
673 if (!is_valid_hex(s[i])) return FALSE;
674 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
676 if (s[13]!='-') return FALSE;
678 id->Data3 = 0;
679 for (i = 14; i < 18; i++)
681 if (!is_valid_hex(s[i])) return FALSE;
682 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
684 if (s[18]!='-') return FALSE;
686 for (i = 19; i < 36; i+=2)
688 if (i == 23)
690 if (s[i]!='-') return FALSE;
691 i++;
693 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
694 id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
697 if (!s[36]) return TRUE;
698 return FALSE;
701 static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags,
702 UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
703 const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
705 HRESULT hr = S_OK;
706 HKEY hclsid = 0;
707 WCHAR buffer[64];
708 WCHAR str[250];
709 UINT8 *blob;
710 UINT32 size;
711 DWORD ret;
713 guid_to_string(buffer, clsid);
714 swprintf(str, ARRAY_SIZE(str), L"%s\\%s", transform_keyW, buffer);
716 if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)))
717 hr = HRESULT_FROM_WIN32(ret);
719 if (SUCCEEDED(hr))
721 size = (lstrlenW(name) + 1) * sizeof(WCHAR);
722 if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)))
723 hr = HRESULT_FROM_WIN32(ret);
726 if (SUCCEEDED(hr) && cinput && input_types)
728 size = cinput * sizeof(MFT_REGISTER_TYPE_INFO);
729 if ((ret = RegSetValueExW(hclsid, L"InputTypes", 0, REG_BINARY, (BYTE *)input_types, size)))
730 hr = HRESULT_FROM_WIN32(ret);
733 if (SUCCEEDED(hr) && coutput && output_types)
735 size = coutput * sizeof(MFT_REGISTER_TYPE_INFO);
736 if ((ret = RegSetValueExW(hclsid, L"OutputTypes", 0, REG_BINARY, (BYTE *)output_types, size)))
737 hr = HRESULT_FROM_WIN32(ret);
740 if (SUCCEEDED(hr) && attributes)
742 if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size)))
744 if ((blob = malloc(size)))
746 if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size)))
748 if ((ret = RegSetValueExW(hclsid, L"Attributes", 0, REG_BINARY, blob, size)))
749 hr = HRESULT_FROM_WIN32(ret);
751 free(blob);
753 else
754 hr = E_OUTOFMEMORY;
758 if (SUCCEEDED(hr) && flags)
760 if ((ret = RegSetValueExW(hclsid, L"MFTFlags", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags))))
761 hr = HRESULT_FROM_WIN32(ret);
764 RegCloseKey(hclsid);
765 return hr;
768 static HRESULT register_category(CLSID *clsid, GUID *category)
770 HKEY htmp1;
771 WCHAR guid1[64], guid2[64];
772 WCHAR str[350];
774 guid_to_string(guid1, category);
775 guid_to_string(guid2, clsid);
777 swprintf(str, ARRAY_SIZE(str), L"%s\\%s\\%s", categories_keyW, guid1, guid2);
779 if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &htmp1))
780 return E_FAIL;
782 RegCloseKey(htmp1);
783 return S_OK;
786 /***********************************************************************
787 * MFTRegister (mfplat.@)
789 HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
790 MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
791 MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes)
793 HRESULT hr;
795 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category),
796 debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
798 hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes);
799 if(FAILED(hr))
800 ERR("Failed to write register transform\n");
802 if (SUCCEEDED(hr))
803 hr = register_category(&clsid, &category);
805 return hr;
808 static void release_mft_registration(struct mft_registration *mft)
810 if (mft->factory)
811 IClassFactory_Release(mft->factory);
812 free(mft->name);
813 free(mft->input_types);
814 free(mft->output_types);
815 free(mft);
818 static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
819 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
820 const MFT_REGISTER_TYPE_INFO *output_types)
822 struct mft_registration *mft, *cur, *unreg_mft = NULL;
823 HRESULT hr = S_OK;
825 if (!factory && !clsid)
827 WARN("Can't register without factory or CLSID.\n");
828 return E_FAIL;
831 if (!(mft = calloc(1, sizeof(*mft))))
832 return E_OUTOFMEMORY;
834 mft->factory = factory;
835 if (mft->factory)
836 IClassFactory_AddRef(mft->factory);
837 if (clsid)
838 mft->clsid = *clsid;
839 mft->category = *category;
840 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
841 flags |= MFT_ENUM_FLAG_SYNCMFT;
842 mft->flags = flags;
843 mft->local = TRUE;
844 if (name && !(mft->name = wcsdup(name)))
846 hr = E_OUTOFMEMORY;
847 goto failed;
850 if (input_count && input_types)
852 mft->input_types_count = input_count;
853 if (!(mft->input_types = calloc(mft->input_types_count, sizeof(*input_types))))
855 hr = E_OUTOFMEMORY;
856 goto failed;
858 memcpy(mft->input_types, input_types, mft->input_types_count * sizeof(*input_types));
861 if (output_count && output_types)
863 mft->output_types_count = output_count;
864 if (!(mft->output_types = calloc(mft->output_types_count, sizeof(*output_types))))
866 hr = E_OUTOFMEMORY;
867 goto failed;
869 memcpy(mft->output_types, output_types, mft->output_types_count * sizeof(*output_types));
872 EnterCriticalSection(&local_mfts_section);
874 LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct mft_registration, entry)
876 if (cur->factory == factory)
878 unreg_mft = cur;
879 list_remove(&cur->entry);
880 break;
883 list_add_tail(&local_mfts, &mft->entry);
885 LeaveCriticalSection(&local_mfts_section);
887 if (unreg_mft)
888 release_mft_registration(unreg_mft);
890 failed:
891 if (FAILED(hr))
892 release_mft_registration(mft);
894 return hr;
897 HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name, UINT32 flags,
898 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
899 const MFT_REGISTER_TYPE_INFO *output_types)
901 TRACE("%p, %s, %s, %#x, %u, %p, %u, %p.\n", factory, debugstr_guid(category), debugstr_w(name), flags, input_count,
902 input_types, output_count, output_types);
904 return mft_register_local(factory, NULL, category, name, flags, input_count, input_types, output_count, output_types);
907 HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
908 UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
909 const MFT_REGISTER_TYPE_INFO *output_types)
911 TRACE("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
912 input_count, input_types, output_count, output_types);
914 return mft_register_local(NULL, clsid, category, name, flags, input_count, input_types, output_count, output_types);
917 static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
919 struct mft_registration *cur, *cur2;
920 BOOL unregister_all = !factory && !clsid;
921 struct list unreg;
923 list_init(&unreg);
925 EnterCriticalSection(&local_mfts_section);
927 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct mft_registration, entry)
929 if (!unregister_all)
931 if ((factory && cur->factory == factory) || IsEqualCLSID(&cur->clsid, clsid))
933 list_remove(&cur->entry);
934 list_add_tail(&unreg, &cur->entry);
935 break;
938 else
940 list_remove(&cur->entry);
941 list_add_tail(&unreg, &cur->entry);
945 LeaveCriticalSection(&local_mfts_section);
947 if (!unregister_all && list_empty(&unreg))
948 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
950 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct mft_registration, entry)
952 list_remove(&cur->entry);
953 release_mft_registration(cur);
956 return S_OK;
959 HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid)
961 TRACE("%s.\n", debugstr_guid(&clsid));
963 return mft_unregister_local(NULL, &clsid);
966 HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
968 TRACE("%p.\n", factory);
970 return mft_unregister_local(factory, NULL);
973 MFTIME WINAPI MFGetSystemTime(void)
975 static LARGE_INTEGER frequency;
976 LARGE_INTEGER counter;
978 if (!frequency.QuadPart)
979 QueryPerformanceFrequency(&frequency);
980 QueryPerformanceCounter(&counter);
982 return counter.QuadPart * 10000000 / frequency.QuadPart;
985 static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *category, UINT32 flags,
986 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
987 const MFT_REGISTER_TYPE_INFO *output_type)
989 BOOL matching = TRUE;
990 DWORD model;
991 int i;
993 if (!IsEqualGUID(category, &mft->category))
994 return FALSE;
996 /* Default model is synchronous. */
997 model = mft->flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE);
998 if (!model)
999 model = MFT_ENUM_FLAG_SYNCMFT;
1000 if (!(model & flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1001 return FALSE;
1003 /* These flags should be explicitly enabled. */
1004 if (mft->flags & ~flags & (MFT_ENUM_FLAG_FIELDOFUSE | MFT_ENUM_FLAG_TRANSCODE_ONLY))
1005 return FALSE;
1007 if (flags & MFT_ENUM_FLAG_SORTANDFILTER && !mft->factory && plugin_control
1008 && IMFPluginControl_IsDisabled(plugin_control, MF_Plugin_Type_MFT, &mft->clsid) == S_OK)
1010 return FALSE;
1013 if (input_type)
1015 for (i = 0, matching = FALSE; input_type && i < mft->input_types_count; ++i)
1017 if (!memcmp(&mft->input_types[i], input_type, sizeof(*input_type)))
1019 matching = TRUE;
1020 break;
1025 if (output_type && matching)
1027 for (i = 0, matching = FALSE; i < mft->output_types_count; ++i)
1029 if (!memcmp(&mft->output_types[i], output_type, sizeof(*output_type)))
1031 matching = TRUE;
1032 break;
1037 return matching;
1040 static void mft_get_reg_type_info_internal(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type,
1041 UINT32 *count)
1043 HKEY htransform, hfilter;
1044 DWORD reg_type, size;
1046 *type = NULL;
1047 *count = 0;
1049 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1050 return;
1052 if (RegOpenKeyW(htransform, clsidW, &hfilter))
1054 RegCloseKey(htransform);
1055 return;
1058 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, NULL, &size))
1059 goto out;
1061 if (reg_type != REG_BINARY)
1062 goto out;
1064 if (!size || size % sizeof(**type))
1065 goto out;
1067 if (!(*type = malloc(size)))
1068 goto out;
1070 *count = size / sizeof(**type);
1072 if (RegQueryValueExW(hfilter, typeW, NULL, &reg_type, (BYTE *)*type, &size))
1074 free(*type);
1075 *type = NULL;
1076 *count = 0;
1079 out:
1080 RegCloseKey(hfilter);
1081 RegCloseKey(htransform);
1084 static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags)
1086 DWORD ret, reg_type, size;
1087 HKEY hroot, hmft;
1089 *flags = 0;
1091 if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot))
1092 return;
1094 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1095 RegCloseKey(hroot);
1096 if (ret)
1097 return;
1099 reg_type = 0;
1100 if (!RegQueryValueExW(hmft, nameW, NULL, &reg_type, NULL, &size) && reg_type == REG_DWORD)
1101 RegQueryValueExW(hmft, nameW, NULL, &reg_type, (BYTE *)flags, &size);
1103 RegCloseKey(hmft);
1106 static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, UINT32 flags,
1107 IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type,
1108 const MFT_REGISTER_TYPE_INFO *output_type)
1110 struct mft_registration mft, *cur;
1111 HKEY hcategory, hlist;
1112 WCHAR clsidW[64];
1113 DWORD ret, size;
1114 int index = 0;
1116 if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1117 return E_FAIL;
1119 guid_to_string(clsidW, category);
1120 ret = RegOpenKeyW(hcategory, clsidW, &hlist);
1121 RegCloseKey(hcategory);
1122 if (ret)
1123 return E_FAIL;
1125 size = ARRAY_SIZE(clsidW);
1126 while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL))
1128 memset(&mft, 0, sizeof(mft));
1129 mft.category = *category;
1130 if (!GUIDFromString(clsidW, &mft.clsid))
1131 goto next;
1133 mft_get_reg_flags(clsidW, L"MFTFlags", &mft.flags);
1135 if (output_type)
1136 mft_get_reg_type_info_internal(clsidW, L"OutputTypes", &mft.output_types, &mft.output_types_count);
1138 if (input_type)
1139 mft_get_reg_type_info_internal(clsidW, L"InputTypes", &mft.input_types, &mft.input_types_count);
1141 if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type))
1143 free(mft.input_types);
1144 free(mft.output_types);
1145 goto next;
1148 cur = malloc(sizeof(*cur));
1149 /* Reuse allocated type arrays. */
1150 *cur = mft;
1151 list_add_tail(mfts, &cur->entry);
1153 next:
1154 size = ARRAY_SIZE(clsidW);
1155 index++;
1158 return S_OK;
1161 static BOOL mft_is_preferred(IMFPluginControl *plugin_control, const CLSID *clsid)
1163 CLSID preferred;
1164 WCHAR *selector;
1165 int index = 0;
1167 while (SUCCEEDED(IMFPluginControl_GetPreferredClsidByIndex(plugin_control, MF_Plugin_Type_MFT, index++, &selector,
1168 &preferred)))
1170 CoTaskMemFree(selector);
1172 if (IsEqualGUID(&preferred, clsid))
1173 return TRUE;
1176 return FALSE;
1179 static HRESULT mft_enum(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1180 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1182 IMFPluginControl *plugin_control = NULL;
1183 struct list mfts, mfts_sorted, *result = &mfts;
1184 struct mft_registration *mft, *mft2;
1185 unsigned int obj_count;
1186 HRESULT hr;
1188 *count = 0;
1189 *activate = NULL;
1191 if (!flags)
1192 flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER;
1194 /* Synchronous processing is default. */
1195 if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE)))
1196 flags |= MFT_ENUM_FLAG_SYNCMFT;
1198 if (FAILED(hr = MFGetPluginControl(&plugin_control)))
1200 WARN("Failed to get plugin control instance, hr %#lx.\n", hr);
1201 return hr;
1204 list_init(&mfts);
1206 /* Collect from registry */
1207 mft_collect_machine_reg(&mfts, &category, flags, plugin_control, input_type, output_type);
1209 /* Collect locally registered ones. */
1210 if (flags & MFT_ENUM_FLAG_LOCALMFT)
1212 struct mft_registration *local;
1214 EnterCriticalSection(&local_mfts_section);
1216 LIST_FOR_EACH_ENTRY(local, &local_mfts, struct mft_registration, entry)
1218 if (mft_is_type_info_match(local, &category, flags, plugin_control, input_type, output_type))
1220 mft = calloc(1, sizeof(*mft));
1222 mft->clsid = local->clsid;
1223 mft->factory = local->factory;
1224 if (mft->factory)
1225 IClassFactory_AddRef(mft->factory);
1226 mft->flags = local->flags;
1227 mft->local = local->local;
1229 list_add_tail(&mfts, &mft->entry);
1233 LeaveCriticalSection(&local_mfts_section);
1236 list_init(&mfts_sorted);
1238 if (flags & MFT_ENUM_FLAG_SORTANDFILTER)
1240 /* Local registrations. */
1241 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1243 if (mft->local)
1245 list_remove(&mft->entry);
1246 list_add_tail(&mfts_sorted, &mft->entry);
1250 /* FIXME: Sort by merit value, for the ones that got it. Currently not handled. */
1252 /* Preferred transforms. */
1253 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1255 if (!mft->factory && mft_is_preferred(plugin_control, &mft->clsid))
1257 list_remove(&mft->entry);
1258 list_add_tail(&mfts_sorted, &mft->entry);
1262 /* Append the rest. */
1263 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1265 list_remove(&mft->entry);
1266 list_add_tail(&mfts_sorted, &mft->entry);
1269 result = &mfts_sorted;
1272 IMFPluginControl_Release(plugin_control);
1274 /* Create activation objects from CLSID/IClassFactory. */
1276 obj_count = list_count(result);
1278 if (obj_count)
1280 if (!(*activate = CoTaskMemAlloc(obj_count * sizeof(**activate))))
1281 hr = E_OUTOFMEMORY;
1283 obj_count = 0;
1285 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, result, struct mft_registration, entry)
1287 IMFActivate *mft_activate;
1289 if (*activate)
1291 if (SUCCEEDED(create_transform_activate(mft->factory, &mft_activate)))
1293 (*activate)[obj_count] = mft_activate;
1295 if (mft->local)
1297 IMFActivate_SetUINT32(mft_activate, &MFT_PROCESS_LOCAL_Attribute, 1);
1299 else
1301 if (mft->name)
1302 IMFActivate_SetString(mft_activate, &MFT_FRIENDLY_NAME_Attribute, mft->name);
1303 if (mft->input_types)
1304 IMFActivate_SetBlob(mft_activate, &MFT_INPUT_TYPES_Attributes, (const UINT8 *)mft->input_types,
1305 sizeof(*mft->input_types) * mft->input_types_count);
1306 if (mft->output_types)
1307 IMFActivate_SetBlob(mft_activate, &MFT_OUTPUT_TYPES_Attributes, (const UINT8 *)mft->output_types,
1308 sizeof(*mft->output_types) * mft->output_types_count);
1311 if (!mft->factory)
1312 IMFActivate_SetGUID(mft_activate, &MFT_TRANSFORM_CLSID_Attribute, &mft->clsid);
1314 IMFActivate_SetUINT32(mft_activate, &MF_TRANSFORM_FLAGS_Attribute, mft->flags);
1315 IMFActivate_SetGUID(mft_activate, &MF_TRANSFORM_CATEGORY_Attribute, &mft->category);
1317 obj_count++;
1321 list_remove(&mft->entry);
1322 release_mft_registration(mft);
1326 if (!obj_count)
1328 CoTaskMemFree(*activate);
1329 *activate = NULL;
1331 *count = obj_count;
1333 return hr;
1336 /***********************************************************************
1337 * MFTEnum (mfplat.@)
1339 HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
1340 MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count)
1342 struct mft_registration *mft, *mft2;
1343 unsigned int mft_count;
1344 struct list mfts;
1345 HRESULT hr;
1347 TRACE("%s, %#x, %s, %s, %p, %p, %p.\n", debugstr_mf_guid(&category), flags, debugstr_reg_typeinfo(input_type),
1348 debugstr_reg_typeinfo(output_type), attributes, clsids, count);
1350 if (!clsids || !count)
1351 return E_INVALIDARG;
1353 *count = 0;
1354 *clsids = NULL;
1356 list_init(&mfts);
1358 if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
1359 return hr;
1361 mft_count = list_count(&mfts);
1363 if (mft_count)
1365 if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
1366 hr = E_OUTOFMEMORY;
1368 mft_count = 0;
1369 LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
1371 if (*clsids)
1372 (*clsids)[mft_count++] = mft->clsid;
1373 list_remove(&mft->entry);
1374 release_mft_registration(mft);
1378 if (!mft_count)
1380 CoTaskMemFree(*clsids);
1381 *clsids = NULL;
1383 *count = mft_count;
1385 return hr;
1388 /***********************************************************************
1389 * MFTEnumEx (mfplat.@)
1391 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1392 const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count)
1394 TRACE("%s, %#x, %s, %s, %p, %p.\n", debugstr_mf_guid(&category), flags, debugstr_reg_typeinfo(input_type),
1395 debugstr_reg_typeinfo(output_type), activate, count);
1397 return mft_enum(category, flags, input_type, output_type, NULL, activate, count);
1400 /***********************************************************************
1401 * MFTEnum2 (mfplat.@)
1403 HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
1404 const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count)
1406 TRACE("%s, %#x, %s, %s, %p, %p, %p.\n", debugstr_mf_guid(&category), flags, debugstr_reg_typeinfo(input_type),
1407 debugstr_reg_typeinfo(output_type), attributes, activate, count);
1409 if (attributes)
1410 FIXME("Ignoring attributes.\n");
1412 return mft_enum(category, flags, input_type, output_type, attributes, activate, count);
1415 /***********************************************************************
1416 * MFTUnregister (mfplat.@)
1418 HRESULT WINAPI MFTUnregister(CLSID clsid)
1420 WCHAR buffer[64], category[MAX_PATH];
1421 HKEY htransform, hcategory, htmp;
1422 DWORD size = MAX_PATH;
1423 DWORD index = 0;
1425 TRACE("(%s)\n", debugstr_guid(&clsid));
1427 guid_to_string(buffer, &clsid);
1429 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
1431 RegDeleteKeyW(htransform, buffer);
1432 RegCloseKey(htransform);
1435 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
1437 while (RegEnumKeyExW(hcategory, index, category, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
1439 if (!RegOpenKeyW(hcategory, category, &htmp))
1441 RegDeleteKeyW(htmp, buffer);
1442 RegCloseKey(htmp);
1444 size = MAX_PATH;
1445 index++;
1447 RegCloseKey(hcategory);
1450 return S_OK;
1453 static HRESULT mft_get_name(HKEY hkey, WCHAR **name)
1455 DWORD size;
1457 if (!name)
1458 return S_OK;
1460 *name = NULL;
1462 if (!RegQueryValueExW(hkey, NULL, NULL, NULL, NULL, &size))
1464 if (!(*name = CoTaskMemAlloc(size)))
1465 return E_OUTOFMEMORY;
1467 RegQueryValueExW(hkey, NULL, NULL, NULL, (BYTE *)*name, &size);
1470 return S_OK;
1473 static HRESULT mft_get_reg_type_info(const WCHAR *clsid, const WCHAR *key, MFT_REGISTER_TYPE_INFO **ret_types,
1474 UINT32 *ret_count)
1476 MFT_REGISTER_TYPE_INFO *types = NULL;
1477 UINT32 count = 0;
1479 if (!ret_types)
1480 return S_OK;
1482 mft_get_reg_type_info_internal(clsid, key, &types, &count);
1483 if (count)
1485 if (!(*ret_types = CoTaskMemAlloc(count * sizeof(**ret_types))))
1487 free(types);
1488 return E_OUTOFMEMORY;
1491 memcpy(*ret_types, types, count * sizeof(**ret_types));
1492 *ret_count = count;
1495 free(types);
1497 return S_OK;
1500 static HRESULT mft_get_attributes(HKEY hkey, IMFAttributes **ret)
1502 IMFAttributes *attributes;
1503 UINT8 *blob;
1504 DWORD size;
1505 HRESULT hr;
1507 if (!ret)
1508 return S_OK;
1510 if (FAILED(hr = MFCreateAttributes(&attributes, 0)))
1511 return hr;
1513 if (!RegQueryValueExW(hkey, L"Attributes", NULL, NULL, NULL, &size) && size)
1515 if (!(blob = malloc(size)))
1517 IMFAttributes_Release(attributes);
1518 return E_OUTOFMEMORY;
1521 if (!RegQueryValueExW(hkey, L"Attributes", NULL, NULL, blob, &size))
1523 if (FAILED(hr = MFInitAttributesFromBlob(attributes, blob, size)))
1524 WARN("Failed to initialize attributes, hr %#lx.\n", hr);
1527 free(blob);
1530 if (SUCCEEDED(hr))
1532 *ret = attributes;
1533 IMFAttributes_AddRef(*ret);
1536 IMFAttributes_Release(attributes);
1538 return hr;
1541 /***********************************************************************
1542 * MFTGetInfo (mfplat.@)
1544 HRESULT WINAPI MFTGetInfo(CLSID clsid, WCHAR **name, MFT_REGISTER_TYPE_INFO **input_types,
1545 UINT32 *input_types_count, MFT_REGISTER_TYPE_INFO **output_types, UINT32 *output_types_count,
1546 IMFAttributes **attributes)
1548 HRESULT hr = S_OK;
1549 WCHAR clsidW[64];
1550 HKEY hroot, hmft;
1551 DWORD ret;
1553 TRACE("%s, %p, %p, %p, %p, %p, %p.\n", debugstr_guid(&clsid), name, input_types,
1554 input_types_count, output_types, output_types_count, attributes);
1556 guid_to_string(clsidW, &clsid);
1558 if ((ret = RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot)))
1559 return HRESULT_FROM_WIN32(ret);
1561 ret = RegOpenKeyW(hroot, clsidW, &hmft);
1562 RegCloseKey(hroot);
1563 if (ret)
1564 return HRESULT_FROM_WIN32(ret);
1566 if (input_types_count)
1567 *input_types_count = 0;
1569 if (output_types_count)
1570 *output_types_count = 0;
1572 hr = mft_get_name(hmft, name);
1574 if (SUCCEEDED(hr))
1575 hr = mft_get_reg_type_info(clsidW, L"InputTypes", input_types, input_types_count);
1577 if (SUCCEEDED(hr))
1578 hr = mft_get_reg_type_info(clsidW, L"OutputTypes", output_types, output_types_count);
1580 if (SUCCEEDED(hr))
1581 hr = mft_get_attributes(hmft, attributes);
1583 RegCloseKey(hmft);
1585 return hr;
1588 /***********************************************************************
1589 * MFStartup (mfplat.@)
1591 HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
1593 #define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
1594 #define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
1596 TRACE("%#lx, %#lx.\n", version, flags);
1598 if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
1599 return MF_E_BAD_STARTUP_VERSION;
1601 RtwqStartup();
1603 return S_OK;
1606 /***********************************************************************
1607 * MFShutdown (mfplat.@)
1609 HRESULT WINAPI MFShutdown(void)
1611 TRACE("\n");
1613 RtwqShutdown();
1615 return S_OK;
1618 /***********************************************************************
1619 * MFCopyImage (mfplat.@)
1621 HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines)
1623 TRACE("%p, %ld, %p, %ld, %lu, %lu.\n", dest, deststride, src, srcstride, width, lines);
1625 while (lines--)
1627 memcpy(dest, src, width);
1628 dest += deststride;
1629 src += srcstride;
1632 return S_OK;
1635 struct guid_def
1637 const GUID *guid;
1638 const char *name;
1641 static int __cdecl debug_compare_guid(const void *a, const void *b)
1643 const GUID *guid = a;
1644 const struct guid_def *guid_def = b;
1645 return memcmp(guid, guid_def->guid, sizeof(*guid));
1648 const char *debugstr_attr(const GUID *guid)
1650 static const struct guid_def guid_defs[] =
1652 #define X(g) { &(g), #g }
1653 #define MF_READER_WRITER_D3D_MANAGER MF_SOURCE_READER_D3D_MANAGER
1654 X(MF_READWRITE_MMCSS_CLASS),
1655 X(MF_TOPONODE_MARKIN_HERE),
1656 X(MF_MT_H264_SUPPORTED_SYNC_FRAME_TYPES),
1657 X(MF_TOPONODE_MARKOUT_HERE),
1658 X(EVRConfig_ForceBob),
1659 X(MF_TOPONODE_DECODER),
1660 X(EVRConfig_AllowDropToBob),
1661 X(MF_TOPOLOGY_PROJECTSTART),
1662 X(EVRConfig_ForceThrottle),
1663 X(MF_VIDEO_MAX_MB_PER_SEC),
1664 X(MF_TOPOLOGY_PROJECTSTOP),
1665 X(MF_SINK_WRITER_ENCODER_CONFIG),
1666 X(EVRConfig_AllowDropToThrottle),
1667 X(MF_TOPOLOGY_NO_MARKIN_MARKOUT),
1668 X(EVRConfig_ForceHalfInterlace),
1669 X(EVRConfig_AllowDropToHalfInterlace),
1670 X(EVRConfig_ForceScaling),
1671 X(MF_MT_H264_CAPABILITIES),
1672 X(EVRConfig_AllowScaling),
1673 X(MF_SOURCE_READER_ENABLE_TRANSCODE_ONLY_TRANSFORMS),
1674 X(MFT_PREFERRED_ENCODER_PROFILE),
1675 X(EVRConfig_ForceBatching),
1676 X(EVRConfig_AllowBatching),
1677 X(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED),
1678 X(MF_MT_VIDEO_PROFILE),
1679 X(MF_MT_DV_AAUX_CTRL_PACK_1),
1680 X(MF_MT_ALPHA_MODE),
1681 X(MF_MT_MPEG2_TIMECODE),
1682 X(MF_PMP_SERVER_CONTEXT),
1683 X(MF_TRANSCODE_TOPOLOGYMODE),
1684 X(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE),
1685 X(MF_MEDIA_ENGINE_TRACK_ID),
1686 X(MFTranscodeContainerType_MP3),
1687 X(MF_MT_CUSTOM_VIDEO_PRIMARIES),
1688 X(MF_MT_TIMESTAMP_CAN_BE_DTS),
1689 X(MFT_CODEC_MERIT_Attribute),
1690 X(MF_TOPOLOGY_PLAYBACK_MAX_DIMS),
1691 X(MF_XVP_DISABLE_FRC),
1692 X(MF_LOW_LATENCY),
1693 X(MF_TRANSCODE_ADJUST_PROFILE),
1694 X(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS),
1695 X(MF_MT_MPEG2_FLAGS),
1696 X(MF_MEDIA_ENGINE_AUDIO_CATEGORY),
1697 X(MF_MT_PIXEL_ASPECT_RATIO),
1698 X(MF_VIDEO_PROCESSOR_ALGORITHM),
1699 X(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK),
1700 X(MFT_CONNECTED_STREAM_ATTRIBUTE),
1701 X(MF_MT_REALTIME_CONTENT),
1702 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS),
1703 X(MF_MT_WRAPPED_TYPE),
1704 X(MF_MT_DRM_FLAGS),
1705 X(MF_MT_AVG_BITRATE),
1706 X(MF_MT_DECODER_USE_MAX_RESOLUTION),
1707 X(MF_MT_MAX_LUMINANCE_LEVEL),
1708 X(MFT_CONNECTED_TO_HW_STREAM),
1709 X(MF_SA_D3D_AWARE),
1710 X(MF_XVP_SAMPLE_LOCK_TIMEOUT),
1711 X(MF_MT_MAX_KEYFRAME_SPACING),
1712 X(MFT_TRANSFORM_CLSID_Attribute),
1713 X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
1714 X(MF_MT_AM_FORMAT_TYPE),
1715 X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
1716 X(MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE),
1717 X(MF_MT_H264_MAX_MB_PER_SEC),
1718 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS),
1719 X(MF_MT_AUDIO_BLOCK_ALIGNMENT),
1720 X(MF_PD_PMPHOST_CONTEXT),
1721 X(MF_PD_APP_CONTEXT),
1722 X(MF_PD_DURATION),
1723 X(MF_PD_TOTAL_FILE_SIZE),
1724 X(MF_PD_AUDIO_ENCODING_BITRATE),
1725 X(MF_PD_VIDEO_ENCODING_BITRATE),
1726 X(MFSampleExtension_TargetGlobalLuminance),
1727 X(MF_PD_MIME_TYPE),
1728 X(MF_MT_H264_SUPPORTED_SLICE_MODES),
1729 X(MF_PD_LAST_MODIFIED_TIME),
1730 X(VIDEO_ZOOM_RECT),
1731 X(MF_PD_PLAYBACK_ELEMENT_ID),
1732 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9),
1733 X(MF_MT_ALL_SAMPLES_INDEPENDENT),
1734 X(MF_SA_D3D12_CLEAR_VALUE),
1735 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER),
1736 X(MF_PD_PREFERRED_LANGUAGE),
1737 X(MF_PD_PLAYBACK_BOUNDARY_TIME),
1738 X(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID),
1739 X(MF_ACTIVATE_MFT_LOCKED),
1740 X(MFTranscodeContainerType_WAVE),
1741 X(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT),
1742 X(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING),
1743 X(MF_MT_FRAME_SIZE),
1744 X(MF_MT_H264_SIMULCAST_SUPPORT),
1745 X(MF_SINK_WRITER_ASYNC_CALLBACK),
1746 X(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH),
1747 X(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER),
1748 X(MF_TRANSCODE_CONTAINERTYPE),
1749 X(MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY),
1750 X(MF_MT_FRAME_RATE_RANGE_MAX),
1751 X(MF_MT_PALETTE),
1752 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID),
1753 X(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS),
1754 X(MF_SA_D3D11_USAGE),
1755 X(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK),
1756 X(MF_MT_GEOMETRIC_APERTURE),
1757 X(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
1758 X(MF_MT_DV_AAUX_SRC_PACK_1),
1759 X(MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL),
1760 X(MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE),
1761 X(MF_MEDIA_ENGINE_EXTENSION),
1762 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS),
1763 X(MF_MT_DEFAULT_STRIDE),
1764 X(MF_MT_ARBITRARY_FORMAT),
1765 X(MF_TRANSFORM_CATEGORY_Attribute),
1766 X(MF_MT_MPEG2_HDCP),
1767 X(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
1768 X(MF_MT_SPATIAL_AUDIO_MAX_DYNAMIC_OBJECTS),
1769 X(MF_MT_DECODER_MAX_DPB_COUNT),
1770 X(MFSampleExtension_ForwardedDecodeUnits),
1771 X(MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
1772 X(MF_MT_DV_AAUX_CTRL_PACK_0),
1773 X(MF_MT_YUV_MATRIX),
1774 X(MF_EVENT_SOURCE_TOPOLOGY_CANCELED),
1775 X(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
1776 X(MF_MT_MAX_FRAME_AVERAGE_LUMINANCE_LEVEL),
1777 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID),
1778 X(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME),
1779 X(MF_MT_VIDEO_ROTATION),
1780 X(MFTranscodeContainerType_MPEG4),
1781 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK),
1782 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11),
1783 X(MF_MT_USER_DATA),
1784 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID),
1785 X(MF_MT_MIN_MASTERING_LUMINANCE),
1786 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE),
1787 X(MF_SA_REQUIRED_SAMPLE_COUNT),
1788 X(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS),
1789 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID),
1790 X(MF_EVENT_STREAM_METADATA_SYSTEMID),
1791 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE),
1792 X(MF_MT_AUDIO_CHANNEL_MASK),
1793 X(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN),
1794 X(MF_READWRITE_DISABLE_CONVERTERS),
1795 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE),
1796 X(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS),
1797 X(MF_SA_D3D12_HEAP_FLAGS),
1798 X(MF_MT_MINIMUM_DISPLAY_APERTURE),
1799 X(MFSampleExtension_Token),
1800 X(MFTranscodeContainerType_3GP),
1801 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY),
1802 X(MF_D3D12_SYNCHRONIZATION_OBJECT),
1803 X(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
1804 X(MF_TRANSFORM_ASYNC_UNLOCK),
1805 X(MF_DISABLE_FRAME_CORRUPTION_INFO),
1806 X(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES),
1807 X(MFTranscodeContainerType_ASF),
1808 X(MF_MT_VIDEO_NO_FRAME_ORDERING),
1809 X(MF_MEDIA_ENGINE_PLAYBACK_VISUAL),
1810 X(MF_MT_VIDEO_CHROMA_SITING),
1811 X(MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY),
1812 X(MF_SA_BUFFERS_PER_SAMPLE),
1813 X(MFSampleExtension_3DVideo_SampleFormat),
1814 X(MF_MT_H264_RESOLUTION_SCALING),
1815 X(MF_MT_VIDEO_LEVEL),
1816 X(MF_SA_D3D12_HEAP_TYPE),
1817 X(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET),
1818 X(MF_MT_SAMPLE_SIZE),
1819 X(MF_MT_AAC_PAYLOAD_TYPE),
1820 X(MF_TOPOLOGY_PLAYBACK_FRAMERATE),
1821 X(MF_SOURCE_READER_D3D11_BIND_FLAGS),
1822 X(MF_TRANSCODE_ENCODINGPROFILE),
1823 X(MF_MT_AUDIO_FOLDDOWN_MATRIX),
1824 X(MF_MT_AUDIO_WMADRC_PEAKREF),
1825 X(MFTranscodeContainerType_ADTS),
1826 X(MF_MT_AUDIO_WMADRC_PEAKTARGET),
1827 X(MF_TRANSFORM_FLAGS_Attribute),
1828 X(MF_MT_H264_SUPPORTED_RATE_CONTROL_MODES),
1829 X(MF_PD_SAMI_STYLELIST),
1830 X(MF_MT_AUDIO_WMADRC_AVGREF),
1831 X(MF_MT_AUDIO_BITS_PER_SAMPLE),
1832 X(MF_SD_LANGUAGE),
1833 X(MF_MT_AUDIO_WMADRC_AVGTARGET),
1834 X(MF_SD_PROTECTED),
1835 X(MF_SESSION_TOPOLOADER),
1836 X(MF_SESSION_GLOBAL_TIME),
1837 X(MF_SESSION_QUALITY_MANAGER),
1838 X(MF_SESSION_CONTENT_PROTECTION_MANAGER),
1839 X(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
1840 X(MF_MT_D3D_RESOURCE_VERSION),
1841 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET),
1842 X(MF_MT_MPEG_START_TIME_CODE),
1843 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1844 X(MFT_REMUX_MARK_I_PICTURE_AS_CLEAN_POINT),
1845 X(MF_READWRITE_MMCSS_PRIORITY_AUDIO),
1846 X(MF_MT_H264_MAX_CODEC_CONFIG_DELAY),
1847 X(MF_MT_DV_AAUX_SRC_PACK_0),
1848 X(MF_BYTESTREAM_ORIGIN_NAME),
1849 X(MF_BYTESTREAM_CONTENT_TYPE),
1850 X(MF_MT_DEPTH_MEASUREMENT),
1851 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10),
1852 X(MF_MT_VIDEO_3D_NUM_VIEWS),
1853 X(MF_BYTESTREAM_DURATION),
1854 X(MF_SD_SAMI_LANGUAGE),
1855 X(MF_EVENT_OUTPUT_NODE),
1856 X(MF_BYTESTREAM_LAST_MODIFIED_TIME),
1857 X(MFT_ENUM_ADAPTER_LUID),
1858 X(MF_MT_FRAME_RATE_RANGE_MIN),
1859 X(MF_BYTESTREAM_IFO_FILE_URI),
1860 X(MF_EVENT_TOPOLOGY_STATUS),
1861 X(MF_BYTESTREAM_DLNA_PROFILE_ID),
1862 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE),
1863 X(MF_MT_MAJOR_TYPE),
1864 X(MF_SA_REQUIRED_SAMPLE_COUNT_PROGRESSIVE),
1865 X(MF_MT_IN_BAND_PARAMETER_SET),
1866 X(MF_EVENT_SOURCE_CHARACTERISTICS),
1867 X(MF_EVENT_SOURCE_CHARACTERISTICS_OLD),
1868 X(MF_SESSION_SERVER_CONTEXT),
1869 X(MF_MT_VIDEO_3D_FIRST_IS_LEFT),
1870 X(MFT_DECODER_FINAL_VIDEO_RESOLUTION_HINT),
1871 X(MF_PD_ADAPTIVE_STREAMING),
1872 X(MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE),
1873 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE),
1874 X(MF_MT_H264_SUPPORTED_USAGES),
1875 X(MFT_PREFERRED_OUTPUTTYPE_Attribute),
1876 X(MFSampleExtension_Timestamp),
1877 X(MF_TOPONODE_PRIMARYOUTPUT),
1878 X(MF_MT_SUBTYPE),
1879 X(MF_TRANSFORM_ASYNC),
1880 X(MF_TOPONODE_STREAMID),
1881 X(MF_MEDIA_ENGINE_PLAYBACK_HWND),
1882 X(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE),
1883 X(MF_MT_VIDEO_LIGHTING),
1884 X(MF_SD_MUTUALLY_EXCLUSIVE),
1885 X(MF_SD_STREAM_NAME),
1886 X(MF_MT_DV_VAUX_SRC_PACK),
1887 X(MF_TOPONODE_RATELESS),
1888 X(MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS),
1889 X(MF_TOPONODE_DISABLE_PREROLL),
1890 X(MF_SA_D3D11_ALLOW_DYNAMIC_YUV_TEXTURE),
1891 X(MF_MT_VIDEO_3D_FORMAT),
1892 X(MF_EVENT_STREAM_METADATA_KEYDATA),
1893 X(MF_READER_WRITER_D3D_MANAGER),
1894 X(MFTranscodeContainerType_FLAC),
1895 X(MFSampleExtension_3DVideo),
1896 X(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE),
1897 X(MF_MT_H264_USAGE),
1898 X(MF_MEDIA_ENGINE_EME_CALLBACK),
1899 X(MF_EVENT_SOURCE_FAKE_START),
1900 X(MF_EVENT_SOURCE_PROJECTSTART),
1901 X(MF_EVENT_SOURCE_ACTUAL_START),
1902 X(MF_MT_D3D12_TEXTURE_LAYOUT),
1903 X(MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER),
1904 X(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
1905 X(MFT_ENUM_HARDWARE_URL_Attribute),
1906 X(MF_SOURCE_READER_ASYNC_CALLBACK),
1907 X(MF_MT_D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE),
1908 X(MF_MT_OUTPUT_BUFFER_NUM),
1909 X(MF_SA_D3D11_BINDFLAGS),
1910 X(MFT_ENCODER_SUPPORTS_CONFIG_EVENT),
1911 X(MF_MT_AUDIO_FLAC_MAX_BLOCK_SIZE),
1912 X(MFT_FRIENDLY_NAME_Attribute),
1913 X(MFTranscodeContainerType_AVI),
1914 X(MF_MT_FIXED_SIZE_SAMPLES),
1915 X(MFT_SUPPORT_3DVIDEO),
1916 X(MFT_SUPPORT_3DVIDEO),
1917 X(MFT_INPUT_TYPES_Attributes),
1918 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS),
1919 X(MF_MT_H264_LAYOUT_PER_STREAM),
1920 X(MF_EVENT_SCRUBSAMPLE_TIME),
1921 X(MF_MT_SPATIAL_AUDIO_MAX_METADATA_ITEMS),
1922 X(MF_MT_MPEG2_ONE_FRAME_PER_PACKET),
1923 X(MF_MT_INTERLACE_MODE),
1924 X(MF_MEDIA_ENGINE_CALLBACK),
1925 X(MF_MT_VIDEO_RENDERER_EXTENSION_PROFILE),
1926 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE),
1927 X(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
1928 X(MF_XVP_CALLER_ALLOCATES_OUTPUT),
1929 X(MF_MT_H264_SVC_CAPABILITIES),
1930 X(MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY),
1931 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_LENGTH),
1932 X(MF_MT_SPATIAL_AUDIO_OBJECT_METADATA_FORMAT_ID),
1933 X(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK),
1934 X(MF_SA_D3D11_SHARED),
1935 X(MF_MT_PAN_SCAN_ENABLED),
1936 X(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),
1937 X(MFTranscodeContainerType_AC3),
1938 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID),
1939 X(MF_MT_DV_VAUX_CTRL_PACK),
1940 X(MFSampleExtension_ForwardedDecodeUnitType),
1941 X(MF_SA_D3D11_AWARE),
1942 X(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
1943 X(MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS),
1944 X(MF_MT_SPATIAL_AUDIO_MIN_METADATA_ITEM_OFFSET_SPACING),
1945 X(MF_TOPONODE_TRANSFORM_OBJECTID),
1946 X(MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE),
1947 X(MF_EVENT_MFT_INPUT_STREAM_ID),
1948 X(MF_MT_SOURCE_CONTENT_HINT),
1949 X(MFT_ENUM_HARDWARE_VENDOR_ID_Attribute),
1950 X(MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE),
1951 X(MF_READWRITE_MMCSS_PRIORITY),
1952 X(MF_TRANSCODE_DONOT_INSERT_ENCODER),
1953 X(MF_MT_VIDEO_3D),
1954 X(MF_EVENT_START_PRESENTATION_TIME),
1955 X(MF_EVENT_SESSIONCAPS),
1956 X(MF_EVENT_PRESENTATION_TIME_OFFSET),
1957 X(MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE),
1958 X(MF_EVENT_SESSIONCAPS_DELTA),
1959 X(MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT),
1960 X(MFTranscodeContainerType_AMR),
1961 X(MFSampleExtension_DecodeTimestamp),
1962 X(MF_MEDIA_ENGINE_COMPATIBILITY_MODE),
1963 X(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT),
1964 X(MF_MT_VIDEO_H264_NO_FMOASO),
1965 X(MF_MT_AVG_BIT_ERROR_RATE),
1966 X(MF_MT_VIDEO_PRIMARIES),
1967 X(MF_SINK_WRITER_DISABLE_THROTTLING),
1968 X(MF_MT_H264_RATE_CONTROL_MODES),
1969 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK),
1970 X(MF_READWRITE_D3D_OPTIONAL),
1971 X(MF_SA_D3D11_HW_PROTECTED),
1972 X(MF_MEDIA_ENGINE_DXGI_MANAGER),
1973 X(MF_READWRITE_MMCSS_CLASS_AUDIO),
1974 X(MF_MEDIA_ENGINE_COREWINDOW),
1975 X(MF_SOURCE_READER_DISABLE_CAMERA_PLUGINS),
1976 X(MF_MT_MPEG4_TRACK_TYPE),
1977 X(MF_ACTIVATE_VIDEO_WINDOW),
1978 X(MF_MT_PAN_SCAN_APERTURE),
1979 X(MF_TOPOLOGY_RESOLUTION_STATUS),
1980 X(MF_MT_ORIGINAL_4CC),
1981 X(MF_PD_AUDIO_ISVARIABLEBITRATE),
1982 X(MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS),
1983 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE),
1984 X(MF_MT_D3D12_CPU_READBACK),
1985 X(MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID),
1986 X(MF_MT_MPEG2_CONTENT_PACKET),
1987 X(MFT_PROCESS_LOCAL_Attribute),
1988 X(MFT_PROCESS_LOCAL_Attribute),
1989 X(MF_MT_PAD_CONTROL_FLAGS),
1990 X(MF_MT_VIDEO_NOMINAL_RANGE),
1991 X(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
1992 X(MF_MT_MPEG_SEQUENCE_HEADER),
1993 X(MF_MEDIA_ENGINE_OPM_HWND),
1994 X(MF_MT_AUDIO_SAMPLES_PER_SECOND),
1995 X(MF_MT_SPATIAL_AUDIO_DATA_PRESENT),
1996 X(MF_MT_FRAME_RATE),
1997 X(MF_TOPONODE_FLUSH),
1998 X(MF_MT_MPEG2_STANDARD),
1999 X(MF_TOPONODE_DRAIN),
2000 X(MF_MT_TRANSFER_FUNCTION),
2001 X(MF_TOPONODE_MEDIASTART),
2002 X(MF_TOPONODE_MEDIASTOP),
2003 X(MF_SOURCE_READER_MEDIASOURCE_CONFIG),
2004 X(MF_TOPONODE_SOURCE),
2005 X(MF_TOPONODE_PRESENTATION_DESCRIPTOR),
2006 X(MF_TOPONODE_D3DAWARE),
2007 X(MF_MT_COMPRESSED),
2008 X(MF_TOPONODE_STREAM_DESCRIPTOR),
2009 X(MF_TOPONODE_ERRORCODE),
2010 X(MF_TOPONODE_SEQUENCE_ELEMENTID),
2011 X(MF_TRANSCODE_SKIP_METADATA_TRANSFER),
2012 X(MF_EVENT_MFT_CONTEXT),
2013 X(MF_MT_FORWARD_CUSTOM_SEI),
2014 X(MFTranscodeContainerType_FMPEG4),
2015 X(MF_TOPONODE_CONNECT_METHOD),
2016 X(MFT_OUTPUT_TYPES_Attributes),
2017 X(MF_MT_IMAGE_LOSS_TOLERANT),
2018 X(MF_SESSION_REMOTE_SOURCE_MODE),
2019 X(MF_MT_DEPTH_VALUE_UNIT),
2020 X(MF_MT_AUDIO_NUM_CHANNELS),
2021 X(MF_MT_ARBITRARY_HEADER),
2022 X(MF_TOPOLOGY_DXVA_MODE),
2023 X(MF_TOPONODE_LOCKED),
2024 X(MF_TRANSCODE_QUALITYVSSPEED),
2025 X(MF_TOPONODE_WORKQUEUE_ID),
2026 X(MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR),
2027 X(MF_TOPONODE_WORKQUEUE_MMCSS_CLASS),
2028 X(MFTranscodeContainerType_MPEG2),
2029 X(MF_TOPONODE_DECRYPTOR),
2030 X(MF_EVENT_DO_THINNING),
2031 X(MF_TOPONODE_DISCARDABLE),
2032 X(MF_TOPOLOGY_HARDWARE_MODE),
2033 X(MF_SOURCE_READER_DISABLE_DXVA),
2034 X(MF_MT_FORWARD_CUSTOM_NALU),
2035 X(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10),
2036 X(MF_TOPONODE_ERROR_MAJORTYPE),
2037 X(MF_MT_SECURE),
2038 X(MFT_FIELDOFUSE_UNLOCK_Attribute),
2039 X(MF_TOPONODE_ERROR_SUBTYPE),
2040 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE),
2041 X(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE),
2042 X(MF_MT_VIDEO_3D_LEFT_IS_BASE),
2043 X(MF_TOPONODE_WORKQUEUE_MMCSS_TASKID),
2044 #undef MF_READER_WRITER_D3D_MANAGER
2045 #undef X
2047 struct guid_def *ret = NULL;
2049 if (guid)
2050 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2052 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2055 const char *debugstr_mf_guid(const GUID *guid)
2057 static const struct guid_def guid_defs[] =
2059 #define X(g) { &(g), #g }
2060 X(MFAudioFormat_ADTS),
2061 X(MFAudioFormat_PCM),
2062 X(MFAudioFormat_PCM_HDCP),
2063 X(MFAudioFormat_Float),
2064 X(MFAudioFormat_DTS),
2065 X(MFAudioFormat_DRM),
2066 X(MFAudioFormat_MSP1),
2067 X(MFAudioFormat_Vorbis),
2068 X(MFAudioFormat_AAC),
2069 X(MFVideoFormat_RGB24),
2070 X(MFVideoFormat_ARGB32),
2071 X(MFVideoFormat_RGB32),
2072 X(MFVideoFormat_RGB565),
2073 X(MFVideoFormat_RGB555),
2074 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID),
2075 X(MFT_CATEGORY_MULTIPLEXER),
2076 X(MFVideoFormat_A2R10G10B10),
2077 X(MFT_CATEGORY_VIDEO_EFFECT),
2078 X(MFMediaType_Script),
2079 X(MFMediaType_Image),
2080 X(MFMediaType_HTML),
2081 X(MFMediaType_Binary),
2082 X(MFVideoFormat_MPEG2),
2083 X(MFMediaType_FileTransfer),
2084 X(MFVideoFormat_RGB8),
2085 X(MFAudioFormat_Dolby_AC3),
2086 X(MFVideoFormat_L8),
2087 X(MFAudioFormat_LPCM),
2088 X(MFVideoFormat_420O),
2089 X(MFVideoFormat_AI44),
2090 X(MFVideoFormat_AV1),
2091 X(MFVideoFormat_AYUV),
2092 X(MFVideoFormat_H263),
2093 X(MFVideoFormat_H264),
2094 X(MFVideoFormat_H265),
2095 X(MFVideoFormat_HEVC),
2096 X(MFVideoFormat_HEVC_ES),
2097 X(MFT_CATEGORY_AUDIO_EFFECT),
2098 X(MFVideoFormat_I420),
2099 X(MFVideoFormat_IYUV),
2100 X(MFT_CATEGORY_VIDEO_DECODER),
2101 X(MFVideoFormat_M4S2),
2102 X(MFVideoFormat_MJPG),
2103 X(MFVideoFormat_MP43),
2104 X(MFVideoFormat_MP4S),
2105 X(MFVideoFormat_MP4V),
2106 X(MFVideoFormat_MPG1),
2107 X(MFVideoFormat_MSS1),
2108 X(MFVideoFormat_MSS2),
2109 X(MFVideoFormat_NV11),
2110 X(MFVideoFormat_NV12),
2111 X(MFVideoFormat_ORAW),
2112 X(MFAudioFormat_Opus),
2113 X(MFAudioFormat_MPEG),
2114 X(MFVideoFormat_D16),
2115 X(MFVideoFormat_P010),
2116 X(MFVideoFormat_P016),
2117 X(MFVideoFormat_P210),
2118 X(MFVideoFormat_P216),
2119 X(MFVideoFormat_L16),
2120 X(MFAudioFormat_MP3),
2121 X(MFVideoFormat_UYVY),
2122 X(MFVideoFormat_VP10),
2123 X(MFVideoFormat_VP80),
2124 X(MFVideoFormat_VP90),
2125 X(MFVideoFormat_WMV1),
2126 X(MFVideoFormat_WMV2),
2127 X(MFVideoFormat_WMV3),
2128 X(MFVideoFormat_WVC1),
2129 X(MFT_CATEGORY_OTHER),
2130 X(MFVideoFormat_Y210),
2131 X(MFVideoFormat_Y216),
2132 X(MFVideoFormat_Y410),
2133 X(MFVideoFormat_Y416),
2134 X(MFVideoFormat_Y41P),
2135 X(MFVideoFormat_Y41T),
2136 X(MFVideoFormat_Y42T),
2137 X(MFVideoFormat_YUY2),
2138 X(MFVideoFormat_YV12),
2139 X(MFVideoFormat_YVU9),
2140 X(MFVideoFormat_YVYU),
2141 X(MFAudioFormat_WMAudioV8),
2142 X(MFAudioFormat_ALAC),
2143 X(MFAudioFormat_AMR_NB),
2144 X(MFMediaType_Audio),
2145 X(MFAudioFormat_WMAudioV9),
2146 X(MFAudioFormat_AMR_WB),
2147 X(MFAudioFormat_WMAudio_Lossless),
2148 X(MFAudioFormat_AMR_WP),
2149 X(MFAudioFormat_WMASPDIF),
2150 X(MFVideoFormat_DV25),
2151 X(MFVideoFormat_DV50),
2152 X(MFVideoFormat_DVC),
2153 X(MFVideoFormat_DVH1),
2154 X(MFVideoFormat_DVHD),
2155 X(MFVideoFormat_DVSD),
2156 X(MFVideoFormat_DVSL),
2157 X(MFVideoFormat_A16B16G16R16F),
2158 X(MFVideoFormat_v210),
2159 X(MFVideoFormat_v216),
2160 X(MFVideoFormat_v410),
2161 X(MFMediaType_Video),
2162 X(MFAudioFormat_AAC_HDCP),
2163 X(MFT_CATEGORY_DEMULTIPLEXER),
2164 X(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID),
2165 X(MFT_CATEGORY_VIDEO_ENCODER),
2166 X(MFAudioFormat_Dolby_AC3_HDCP),
2167 X(MFMediaType_Subtitle),
2168 X(MFMediaType_Stream),
2169 X(MFAudioFormat_Dolby_AC3_SPDIF),
2170 X(MFAudioFormat_Float_SpatialObjects),
2171 X(MFMediaType_SAMI),
2172 X(MFAudioFormat_ADTS_HDCP),
2173 X(MFAudioFormat_FLAC),
2174 X(MFAudioFormat_Dolby_DDPlus),
2175 X(MFMediaType_MultiplexedFrames),
2176 X(MFT_CATEGORY_AUDIO_DECODER),
2177 X(MFAudioFormat_Base_HDCP),
2178 X(MFT_CATEGORY_AUDIO_ENCODER),
2179 X(MFVideoFormat_Base_HDCP),
2180 X(MFVideoFormat_H264_HDCP),
2181 X(MFVideoFormat_HEVC_HDCP),
2182 X(MFMediaType_Default),
2183 X(MFMediaType_Protected),
2184 X(MFVideoFormat_H264_ES),
2185 X(MFMediaType_Perception),
2186 X(MFT_CATEGORY_VIDEO_PROCESSOR),
2187 #undef X
2189 struct guid_def *ret = NULL;
2191 if (guid)
2192 ret = bsearch(guid, guid_defs, ARRAY_SIZE(guid_defs), sizeof(*guid_defs), debug_compare_guid);
2194 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbgstr_guid(guid);
2197 struct event_id
2199 DWORD id;
2200 const char *name;
2203 static int __cdecl debug_event_id(const void *a, const void *b)
2205 const DWORD *id = a;
2206 const struct event_id *event_id = b;
2207 return *id - event_id->id;
2210 static const char *debugstr_eventid(DWORD event)
2212 static const struct event_id
2214 DWORD id;
2215 const char *name;
2217 event_ids[] =
2219 #define X(e) { e, #e }
2220 X(MEUnknown),
2221 X(MEError),
2222 X(MEExtendedType),
2223 X(MENonFatalError),
2224 X(MESessionUnknown),
2225 X(MESessionTopologySet),
2226 X(MESessionTopologiesCleared),
2227 X(MESessionStarted),
2228 X(MESessionPaused),
2229 X(MESessionStopped),
2230 X(MESessionClosed),
2231 X(MESessionEnded),
2232 X(MESessionRateChanged),
2233 X(MESessionScrubSampleComplete),
2234 X(MESessionCapabilitiesChanged),
2235 X(MESessionTopologyStatus),
2236 X(MESessionNotifyPresentationTime),
2237 X(MENewPresentation),
2238 X(MELicenseAcquisitionStart),
2239 X(MELicenseAcquisitionCompleted),
2240 X(MEIndividualizationStart),
2241 X(MEIndividualizationCompleted),
2242 X(MEEnablerProgress),
2243 X(MEEnablerCompleted),
2244 X(MEPolicyError),
2245 X(MEPolicyReport),
2246 X(MEBufferingStarted),
2247 X(MEBufferingStopped),
2248 X(MEConnectStart),
2249 X(MEConnectEnd),
2250 X(MEReconnectStart),
2251 X(MEReconnectEnd),
2252 X(MERendererEvent),
2253 X(MESessionStreamSinkFormatChanged),
2254 X(MESourceUnknown),
2255 X(MESourceStarted),
2256 X(MEStreamStarted),
2257 X(MESourceSeeked),
2258 X(MEStreamSeeked),
2259 X(MENewStream),
2260 X(MEUpdatedStream),
2261 X(MESourceStopped),
2262 X(MEStreamStopped),
2263 X(MESourcePaused),
2264 X(MEStreamPaused),
2265 X(MEEndOfPresentation),
2266 X(MEEndOfStream),
2267 X(MEMediaSample),
2268 X(MEStreamTick),
2269 X(MEStreamThinMode),
2270 X(MEStreamFormatChanged),
2271 X(MESourceRateChanged),
2272 X(MEEndOfPresentationSegment),
2273 X(MESourceCharacteristicsChanged),
2274 X(MESourceRateChangeRequested),
2275 X(MESourceMetadataChanged),
2276 X(MESequencerSourceTopologyUpdated),
2277 X(MESinkUnknown),
2278 X(MEStreamSinkStarted),
2279 X(MEStreamSinkStopped),
2280 X(MEStreamSinkPaused),
2281 X(MEStreamSinkRateChanged),
2282 X(MEStreamSinkRequestSample),
2283 X(MEStreamSinkMarker),
2284 X(MEStreamSinkPrerolled),
2285 X(MEStreamSinkScrubSampleComplete),
2286 X(MEStreamSinkFormatChanged),
2287 X(MEStreamSinkDeviceChanged),
2288 X(MEQualityNotify),
2289 X(MESinkInvalidated),
2290 X(MEAudioSessionNameChanged),
2291 X(MEAudioSessionVolumeChanged),
2292 X(MEAudioSessionDeviceRemoved),
2293 X(MEAudioSessionServerShutdown),
2294 X(MEAudioSessionGroupingParamChanged),
2295 X(MEAudioSessionIconChanged),
2296 X(MEAudioSessionFormatChanged),
2297 X(MEAudioSessionDisconnected),
2298 X(MEAudioSessionExclusiveModeOverride),
2299 X(MECaptureAudioSessionVolumeChanged),
2300 X(MECaptureAudioSessionDeviceRemoved),
2301 X(MECaptureAudioSessionFormatChanged),
2302 X(MECaptureAudioSessionDisconnected),
2303 X(MECaptureAudioSessionExclusiveModeOverride),
2304 X(MECaptureAudioSessionServerShutdown),
2305 X(METrustUnknown),
2306 X(MEPolicyChanged),
2307 X(MEContentProtectionMessage),
2308 X(MEPolicySet),
2309 X(MEWMDRMLicenseBackupCompleted),
2310 X(MEWMDRMLicenseBackupProgress),
2311 X(MEWMDRMLicenseRestoreCompleted),
2312 X(MEWMDRMLicenseRestoreProgress),
2313 X(MEWMDRMLicenseAcquisitionCompleted),
2314 X(MEWMDRMIndividualizationCompleted),
2315 X(MEWMDRMIndividualizationProgress),
2316 X(MEWMDRMProximityCompleted),
2317 X(MEWMDRMLicenseStoreCleaned),
2318 X(MEWMDRMRevocationDownloadCompleted),
2319 X(METransformUnknown),
2320 X(METransformNeedInput),
2321 X(METransformHaveOutput),
2322 X(METransformDrainComplete),
2323 X(METransformMarker),
2324 X(METransformInputStreamStateChanged),
2325 X(MEByteStreamCharacteristicsChanged),
2326 X(MEVideoCaptureDeviceRemoved),
2327 X(MEVideoCaptureDevicePreempted),
2328 X(MEStreamSinkFormatInvalidated),
2329 X(MEEncodingParameters),
2330 X(MEContentProtectionMetadata),
2331 X(MEDeviceThermalStateChanged),
2332 #undef X
2335 struct event_id *ret = bsearch(&event, event_ids, ARRAY_SIZE(event_ids), sizeof(*event_ids), debug_event_id);
2336 return ret ? wine_dbg_sprintf("%s", ret->name) : wine_dbg_sprintf("%lu", event);
2339 static inline struct attributes *impl_from_IMFAttributes(IMFAttributes *iface)
2341 return CONTAINING_RECORD(iface, struct attributes, IMFAttributes_iface);
2344 static HRESULT WINAPI mfattributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
2346 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
2348 if (IsEqualIID(riid, &IID_IMFAttributes) ||
2349 IsEqualGUID(riid, &IID_IUnknown))
2351 *out = iface;
2352 IMFAttributes_AddRef(iface);
2353 return S_OK;
2356 WARN("Unsupported %s.\n", debugstr_guid(riid));
2357 *out = NULL;
2358 return E_NOINTERFACE;
2361 static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
2363 struct attributes *attributes = impl_from_IMFAttributes(iface);
2364 ULONG refcount = InterlockedIncrement(&attributes->ref);
2366 TRACE("%p, refcount %ld.\n", iface, refcount);
2368 return refcount;
2371 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
2373 struct attributes *attributes = impl_from_IMFAttributes(iface);
2374 ULONG refcount = InterlockedDecrement(&attributes->ref);
2376 TRACE("%p, refcount %ld.\n", iface, refcount);
2378 if (!refcount)
2380 clear_attributes_object(attributes);
2381 free(attributes);
2384 return refcount;
2387 static struct attribute *attributes_find_item(struct attributes *attributes, REFGUID key, size_t *index)
2389 size_t i;
2391 for (i = 0; i < attributes->count; ++i)
2393 if (IsEqualGUID(key, &attributes->attributes[i].key))
2395 if (index)
2396 *index = i;
2397 return &attributes->attributes[i];
2401 return NULL;
2404 static HRESULT attributes_get_item(struct attributes *attributes, const GUID *key, PROPVARIANT *value)
2406 struct attribute *attribute;
2407 HRESULT hr;
2409 EnterCriticalSection(&attributes->cs);
2411 attribute = attributes_find_item(attributes, key, NULL);
2412 if (attribute)
2414 if (attribute->value.vt == value->vt && !(value->vt == VT_UNKNOWN && !attribute->value.punkVal))
2415 hr = PropVariantCopy(value, &attribute->value);
2416 else
2417 hr = MF_E_INVALIDTYPE;
2419 else
2420 hr = MF_E_ATTRIBUTENOTFOUND;
2422 LeaveCriticalSection(&attributes->cs);
2424 return hr;
2427 HRESULT attributes_GetItem(struct attributes *attributes, REFGUID key, PROPVARIANT *value)
2429 struct attribute *attribute;
2430 HRESULT hr;
2432 EnterCriticalSection(&attributes->cs);
2434 if ((attribute = attributes_find_item(attributes, key, NULL)))
2435 hr = value ? PropVariantCopy(value, &attribute->value) : S_OK;
2436 else
2437 hr = MF_E_ATTRIBUTENOTFOUND;
2439 LeaveCriticalSection(&attributes->cs);
2441 return hr;
2444 HRESULT attributes_GetItemType(struct attributes *attributes, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2446 struct attribute *attribute;
2447 HRESULT hr = S_OK;
2449 EnterCriticalSection(&attributes->cs);
2451 if ((attribute = attributes_find_item(attributes, key, NULL)))
2453 *type = attribute->value.vt;
2455 else
2456 hr = MF_E_ATTRIBUTENOTFOUND;
2458 LeaveCriticalSection(&attributes->cs);
2460 return hr;
2463 HRESULT attributes_CompareItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value, BOOL *result)
2465 struct attribute *attribute;
2467 *result = FALSE;
2469 EnterCriticalSection(&attributes->cs);
2471 if ((attribute = attributes_find_item(attributes, key, NULL)))
2473 *result = attribute->value.vt == value->vt &&
2474 !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT);
2477 LeaveCriticalSection(&attributes->cs);
2479 return S_OK;
2482 HRESULT attributes_Compare(struct attributes *attributes, IMFAttributes *theirs,
2483 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
2485 IMFAttributes *smaller, *other;
2486 MF_ATTRIBUTE_TYPE type;
2487 HRESULT hr = S_OK;
2488 UINT32 count;
2489 BOOL result;
2490 size_t i;
2492 if (FAILED(hr = IMFAttributes_GetCount(theirs, &count)))
2493 return hr;
2495 EnterCriticalSection(&attributes->cs);
2497 result = TRUE;
2499 switch (match_type)
2501 case MF_ATTRIBUTES_MATCH_OUR_ITEMS:
2502 for (i = 0; i < attributes->count; ++i)
2504 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2505 &attributes->attributes[i].value, &result)))
2506 break;
2507 if (!result)
2508 break;
2510 break;
2511 case MF_ATTRIBUTES_MATCH_THEIR_ITEMS:
2512 hr = IMFAttributes_Compare(theirs, &attributes->IMFAttributes_iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2513 break;
2514 case MF_ATTRIBUTES_MATCH_ALL_ITEMS:
2515 if (count != attributes->count)
2517 result = FALSE;
2518 break;
2520 for (i = 0; i < count; ++i)
2522 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2523 &attributes->attributes[i].value, &result)))
2524 break;
2525 if (!result)
2526 break;
2528 break;
2529 case MF_ATTRIBUTES_MATCH_INTERSECTION:
2530 for (i = 0; i < attributes->count; ++i)
2532 if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type)))
2533 continue;
2535 if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key,
2536 &attributes->attributes[i].value, &result)))
2537 break;
2539 if (!result)
2540 break;
2542 break;
2543 case MF_ATTRIBUTES_MATCH_SMALLER:
2544 smaller = attributes->count > count ? theirs : &attributes->IMFAttributes_iface;
2545 other = attributes->count > count ? &attributes->IMFAttributes_iface : theirs;
2546 hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
2547 break;
2548 default:
2549 WARN("Unknown match type %d.\n", match_type);
2550 hr = E_INVALIDARG;
2553 LeaveCriticalSection(&attributes->cs);
2555 if (SUCCEEDED(hr))
2556 *ret = result;
2558 return hr;
2561 HRESULT attributes_GetUINT32(struct attributes *attributes, REFGUID key, UINT32 *value)
2563 PROPVARIANT attrval;
2564 HRESULT hr;
2566 PropVariantInit(&attrval);
2567 attrval.vt = VT_UI4;
2568 hr = attributes_get_item(attributes, key, &attrval);
2569 if (SUCCEEDED(hr))
2570 *value = attrval.ulVal;
2572 return hr;
2575 HRESULT attributes_GetUINT64(struct attributes *attributes, REFGUID key, UINT64 *value)
2577 PROPVARIANT attrval;
2578 HRESULT hr;
2580 PropVariantInit(&attrval);
2581 attrval.vt = VT_UI8;
2582 hr = attributes_get_item(attributes, key, &attrval);
2583 if (SUCCEEDED(hr))
2584 *value = attrval.uhVal.QuadPart;
2586 return hr;
2589 HRESULT attributes_GetDouble(struct attributes *attributes, REFGUID key, double *value)
2591 PROPVARIANT attrval;
2592 HRESULT hr;
2594 PropVariantInit(&attrval);
2595 attrval.vt = VT_R8;
2596 hr = attributes_get_item(attributes, key, &attrval);
2597 if (SUCCEEDED(hr))
2598 *value = attrval.dblVal;
2600 return hr;
2603 HRESULT attributes_GetGUID(struct attributes *attributes, REFGUID key, GUID *value)
2605 struct attribute *attribute;
2606 HRESULT hr = S_OK;
2608 EnterCriticalSection(&attributes->cs);
2610 attribute = attributes_find_item(attributes, key, NULL);
2611 if (attribute)
2613 if (attribute->value.vt == MF_ATTRIBUTE_GUID)
2614 *value = *attribute->value.puuid;
2615 else
2616 hr = MF_E_INVALIDTYPE;
2618 else
2619 hr = MF_E_ATTRIBUTENOTFOUND;
2621 LeaveCriticalSection(&attributes->cs);
2623 return hr;
2626 HRESULT attributes_GetStringLength(struct attributes *attributes, REFGUID key, UINT32 *length)
2628 struct attribute *attribute;
2629 HRESULT hr = S_OK;
2631 EnterCriticalSection(&attributes->cs);
2633 attribute = attributes_find_item(attributes, key, NULL);
2634 if (attribute)
2636 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2637 *length = lstrlenW(attribute->value.pwszVal);
2638 else
2639 hr = MF_E_INVALIDTYPE;
2641 else
2642 hr = MF_E_ATTRIBUTENOTFOUND;
2644 LeaveCriticalSection(&attributes->cs);
2646 return hr;
2649 HRESULT attributes_GetString(struct attributes *attributes, REFGUID key, WCHAR *value,
2650 UINT32 size, UINT32 *length)
2652 struct attribute *attribute;
2653 HRESULT hr = S_OK;
2655 EnterCriticalSection(&attributes->cs);
2657 attribute = attributes_find_item(attributes, key, NULL);
2658 if (attribute)
2660 if (attribute->value.vt == MF_ATTRIBUTE_STRING)
2662 int len = lstrlenW(attribute->value.pwszVal);
2664 if (length)
2665 *length = len;
2667 if (size <= len)
2668 hr = STRSAFE_E_INSUFFICIENT_BUFFER;
2669 else
2670 memcpy(value, attribute->value.pwszVal, (len + 1) * sizeof(WCHAR));
2672 else
2673 hr = MF_E_INVALIDTYPE;
2675 else
2676 hr = MF_E_ATTRIBUTENOTFOUND;
2678 LeaveCriticalSection(&attributes->cs);
2680 return hr;
2683 HRESULT attributes_GetAllocatedString(struct attributes *attributes, REFGUID key, WCHAR **value, UINT32 *length)
2685 PROPVARIANT attrval;
2686 HRESULT hr;
2688 PropVariantInit(&attrval);
2689 attrval.vt = VT_LPWSTR;
2690 hr = attributes_get_item(attributes, key, &attrval);
2691 if (SUCCEEDED(hr))
2693 *value = attrval.pwszVal;
2694 if (length)
2695 *length = lstrlenW(*value);
2698 return hr;
2701 HRESULT attributes_GetBlobSize(struct attributes *attributes, REFGUID key, UINT32 *size)
2703 struct attribute *attribute;
2704 HRESULT hr = S_OK;
2706 EnterCriticalSection(&attributes->cs);
2708 attribute = attributes_find_item(attributes, key, NULL);
2709 if (attribute)
2711 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2712 *size = attribute->value.caub.cElems;
2713 else
2714 hr = MF_E_INVALIDTYPE;
2716 else
2717 hr = MF_E_ATTRIBUTENOTFOUND;
2719 LeaveCriticalSection(&attributes->cs);
2721 return hr;
2724 HRESULT attributes_GetBlob(struct attributes *attributes, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
2726 struct attribute *attribute;
2727 HRESULT hr;
2729 EnterCriticalSection(&attributes->cs);
2731 attribute = attributes_find_item(attributes, key, NULL);
2732 if (attribute)
2734 if (attribute->value.vt == MF_ATTRIBUTE_BLOB)
2736 UINT32 size = attribute->value.caub.cElems;
2738 if (bufsize >= size)
2739 hr = PropVariantToBuffer(&attribute->value, buf, size);
2740 else
2741 hr = E_NOT_SUFFICIENT_BUFFER;
2743 if (blobsize)
2744 *blobsize = size;
2746 else
2747 hr = MF_E_INVALIDTYPE;
2749 else
2750 hr = MF_E_ATTRIBUTENOTFOUND;
2752 LeaveCriticalSection(&attributes->cs);
2754 return hr;
2757 HRESULT attributes_GetAllocatedBlob(struct attributes *attributes, REFGUID key, UINT8 **buf, UINT32 *size)
2759 PROPVARIANT attrval;
2760 HRESULT hr;
2762 attrval.vt = VT_VECTOR | VT_UI1;
2763 hr = attributes_get_item(attributes, key, &attrval);
2764 if (SUCCEEDED(hr))
2766 *buf = attrval.caub.pElems;
2767 if (size)
2768 *size = attrval.caub.cElems;
2771 return hr;
2774 HRESULT attributes_GetUnknown(struct attributes *attributes, REFGUID key, REFIID riid, void **out)
2776 PROPVARIANT attrval;
2777 HRESULT hr;
2779 PropVariantInit(&attrval);
2780 attrval.vt = VT_UNKNOWN;
2781 hr = attributes_get_item(attributes, key, &attrval);
2782 if (SUCCEEDED(hr))
2783 hr = IUnknown_QueryInterface(attrval.punkVal, riid, out);
2784 PropVariantClear(&attrval);
2785 return hr;
2788 static HRESULT attributes_set_item(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2790 struct attribute *attribute;
2792 EnterCriticalSection(&attributes->cs);
2794 attribute = attributes_find_item(attributes, key, NULL);
2795 if (!attribute)
2797 if (!mf_array_reserve((void **)&attributes->attributes, &attributes->capacity, attributes->count + 1,
2798 sizeof(*attributes->attributes)))
2800 LeaveCriticalSection(&attributes->cs);
2801 return E_OUTOFMEMORY;
2803 attributes->attributes[attributes->count].key = *key;
2804 attribute = &attributes->attributes[attributes->count++];
2806 else
2807 PropVariantClear(&attribute->value);
2809 PropVariantCopy(&attribute->value, value);
2811 LeaveCriticalSection(&attributes->cs);
2813 return S_OK;
2816 HRESULT attributes_SetItem(struct attributes *attributes, REFGUID key, REFPROPVARIANT value)
2818 PROPVARIANT empty;
2820 switch (value->vt)
2822 case MF_ATTRIBUTE_UINT32:
2823 case MF_ATTRIBUTE_UINT64:
2824 case MF_ATTRIBUTE_DOUBLE:
2825 case MF_ATTRIBUTE_GUID:
2826 case MF_ATTRIBUTE_STRING:
2827 case MF_ATTRIBUTE_BLOB:
2828 case MF_ATTRIBUTE_IUNKNOWN:
2829 return attributes_set_item(attributes, key, value);
2830 default:
2831 PropVariantInit(&empty);
2832 attributes_set_item(attributes, key, &empty);
2833 return MF_E_INVALIDTYPE;
2837 HRESULT attributes_DeleteItem(struct attributes *attributes, REFGUID key)
2839 struct attribute *attribute;
2840 size_t index = 0;
2842 EnterCriticalSection(&attributes->cs);
2844 if ((attribute = attributes_find_item(attributes, key, &index)))
2846 size_t count;
2848 PropVariantClear(&attribute->value);
2850 attributes->count--;
2851 count = attributes->count - index;
2852 if (count)
2853 memmove(&attributes->attributes[index], &attributes->attributes[index + 1], count * sizeof(*attributes->attributes));
2856 LeaveCriticalSection(&attributes->cs);
2858 return S_OK;
2861 HRESULT attributes_DeleteAllItems(struct attributes *attributes)
2863 EnterCriticalSection(&attributes->cs);
2865 while (attributes->count)
2867 PropVariantClear(&attributes->attributes[--attributes->count].value);
2869 free(attributes->attributes);
2870 attributes->attributes = NULL;
2871 attributes->capacity = 0;
2873 LeaveCriticalSection(&attributes->cs);
2875 return S_OK;
2878 HRESULT attributes_SetUINT32(struct attributes *attributes, REFGUID key, UINT32 value)
2880 PROPVARIANT attrval;
2882 attrval.vt = VT_UI4;
2883 attrval.ulVal = value;
2884 return attributes_set_item(attributes, key, &attrval);
2887 HRESULT attributes_SetUINT64(struct attributes *attributes, REFGUID key, UINT64 value)
2889 PROPVARIANT attrval;
2891 attrval.vt = VT_UI8;
2892 attrval.uhVal.QuadPart = value;
2893 return attributes_set_item(attributes, key, &attrval);
2896 HRESULT attributes_SetDouble(struct attributes *attributes, REFGUID key, double value)
2898 PROPVARIANT attrval;
2900 attrval.vt = VT_R8;
2901 attrval.dblVal = value;
2902 return attributes_set_item(attributes, key, &attrval);
2905 HRESULT attributes_SetGUID(struct attributes *attributes, REFGUID key, REFGUID value)
2907 PROPVARIANT attrval;
2909 attrval.vt = VT_CLSID;
2910 attrval.puuid = (CLSID *)value;
2911 return attributes_set_item(attributes, key, &attrval);
2914 HRESULT attributes_SetString(struct attributes *attributes, REFGUID key, const WCHAR *value)
2916 PROPVARIANT attrval;
2918 attrval.vt = VT_LPWSTR;
2919 attrval.pwszVal = (WCHAR *)value;
2920 return attributes_set_item(attributes, key, &attrval);
2923 HRESULT attributes_SetBlob(struct attributes *attributes, REFGUID key, const UINT8 *buf, UINT32 size)
2925 PROPVARIANT attrval;
2927 attrval.vt = VT_VECTOR | VT_UI1;
2928 attrval.caub.cElems = size;
2929 attrval.caub.pElems = (UINT8 *)buf;
2930 return attributes_set_item(attributes, key, &attrval);
2933 HRESULT attributes_SetUnknown(struct attributes *attributes, REFGUID key, IUnknown *unknown)
2935 PROPVARIANT attrval;
2937 attrval.vt = VT_UNKNOWN;
2938 attrval.punkVal = unknown;
2939 return attributes_set_item(attributes, key, &attrval);
2942 HRESULT attributes_LockStore(struct attributes *attributes)
2944 EnterCriticalSection(&attributes->cs);
2946 return S_OK;
2949 HRESULT attributes_UnlockStore(struct attributes *attributes)
2951 LeaveCriticalSection(&attributes->cs);
2953 return S_OK;
2956 HRESULT attributes_GetCount(struct attributes *attributes, UINT32 *count)
2958 EnterCriticalSection(&attributes->cs);
2959 *count = attributes->count;
2960 LeaveCriticalSection(&attributes->cs);
2962 return S_OK;
2965 HRESULT attributes_GetItemByIndex(struct attributes *attributes, UINT32 index, GUID *key, PROPVARIANT *value)
2967 HRESULT hr = S_OK;
2969 EnterCriticalSection(&attributes->cs);
2971 if (index < attributes->count)
2973 *key = attributes->attributes[index].key;
2974 if (value)
2975 PropVariantCopy(value, &attributes->attributes[index].value);
2977 else
2978 hr = E_INVALIDARG;
2980 LeaveCriticalSection(&attributes->cs);
2982 return hr;
2985 HRESULT attributes_CopyAllItems(struct attributes *attributes, IMFAttributes *dest)
2987 HRESULT hr = S_OK;
2988 size_t i;
2990 EnterCriticalSection(&attributes->cs);
2992 IMFAttributes_LockStore(dest);
2994 IMFAttributes_DeleteAllItems(dest);
2996 for (i = 0; i < attributes->count; ++i)
2998 hr = IMFAttributes_SetItem(dest, &attributes->attributes[i].key, &attributes->attributes[i].value);
2999 if (FAILED(hr))
3000 break;
3003 IMFAttributes_UnlockStore(dest);
3005 LeaveCriticalSection(&attributes->cs);
3007 return hr;
3010 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
3012 struct attributes *attributes = impl_from_IMFAttributes(iface);
3014 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3016 return attributes_GetItem(attributes, key, value);
3019 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
3021 struct attributes *attributes = impl_from_IMFAttributes(iface);
3023 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
3025 return attributes_GetItemType(attributes, key, type);
3028 static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
3030 struct attributes *attributes = impl_from_IMFAttributes(iface);
3032 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
3034 return attributes_CompareItem(attributes, key, value, result);
3037 static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
3038 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
3040 struct attributes *attributes = impl_from_IMFAttributes(iface);
3042 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
3044 return attributes_Compare(attributes, theirs, match_type, ret);
3047 static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
3049 struct attributes *attributes = impl_from_IMFAttributes(iface);
3051 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3053 return attributes_GetUINT32(attributes, key, value);
3056 static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
3058 struct attributes *attributes = impl_from_IMFAttributes(iface);
3060 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3062 return attributes_GetUINT64(attributes, key, value);
3065 static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
3067 struct attributes *attributes = impl_from_IMFAttributes(iface);
3069 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3071 return attributes_GetDouble(attributes, key, value);
3074 static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
3076 struct attributes *attributes = impl_from_IMFAttributes(iface);
3078 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
3080 return attributes_GetGUID(attributes, key, value);
3083 static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
3085 struct attributes *attributes = impl_from_IMFAttributes(iface);
3087 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
3089 return attributes_GetStringLength(attributes, key, length);
3092 static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
3093 UINT32 size, UINT32 *length)
3095 struct attributes *attributes = impl_from_IMFAttributes(iface);
3097 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
3099 return attributes_GetString(attributes, key, value, size, length);
3102 static HRESULT WINAPI mfattributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
3104 struct attributes *attributes = impl_from_IMFAttributes(iface);
3106 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
3108 return attributes_GetAllocatedString(attributes, key, value, length);
3111 static HRESULT WINAPI mfattributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
3113 struct attributes *attributes = impl_from_IMFAttributes(iface);
3115 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
3117 return attributes_GetBlobSize(attributes, key, size);
3120 static HRESULT WINAPI mfattributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
3121 UINT32 bufsize, UINT32 *blobsize)
3123 struct attributes *attributes = impl_from_IMFAttributes(iface);
3125 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
3127 return attributes_GetBlob(attributes, key, buf, bufsize, blobsize);
3130 static HRESULT WINAPI mfattributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
3132 struct attributes *attributes = impl_from_IMFAttributes(iface);
3134 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
3136 return attributes_GetAllocatedBlob(attributes, key, buf, size);
3139 static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
3141 struct attributes *attributes = impl_from_IMFAttributes(iface);
3143 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
3145 return attributes_GetUnknown(attributes, key, riid, out);
3148 static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
3150 struct attributes *attributes = impl_from_IMFAttributes(iface);
3152 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
3154 return attributes_SetItem(attributes, key, value);
3157 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
3159 struct attributes *attributes = impl_from_IMFAttributes(iface);
3161 TRACE("%p, %s.\n", iface, debugstr_attr(key));
3163 return attributes_DeleteItem(attributes, key);
3166 static HRESULT WINAPI mfattributes_DeleteAllItems(IMFAttributes *iface)
3168 struct attributes *attributes = impl_from_IMFAttributes(iface);
3170 TRACE("%p.\n", iface);
3172 return attributes_DeleteAllItems(attributes);
3175 static HRESULT WINAPI mfattributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
3177 struct attributes *attributes = impl_from_IMFAttributes(iface);
3179 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
3181 return attributes_SetUINT32(attributes, key, value);
3184 static HRESULT WINAPI mfattributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
3186 struct attributes *attributes = impl_from_IMFAttributes(iface);
3188 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
3190 return attributes_SetUINT64(attributes, key, value);
3193 static HRESULT WINAPI mfattributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
3195 struct attributes *attributes = impl_from_IMFAttributes(iface);
3197 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
3199 return attributes_SetDouble(attributes, key, value);
3202 static HRESULT WINAPI mfattributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
3204 struct attributes *attributes = impl_from_IMFAttributes(iface);
3206 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
3208 return attributes_SetGUID(attributes, key, value);
3211 static HRESULT WINAPI mfattributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
3213 struct attributes *attributes = impl_from_IMFAttributes(iface);
3215 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
3217 return attributes_SetString(attributes, key, value);
3220 static HRESULT WINAPI mfattributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
3222 struct attributes *attributes = impl_from_IMFAttributes(iface);
3224 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
3226 return attributes_SetBlob(attributes, key, buf, size);
3229 static HRESULT WINAPI mfattributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
3231 struct attributes *attributes = impl_from_IMFAttributes(iface);
3233 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
3235 return attributes_SetUnknown(attributes, key, unknown);
3238 static HRESULT WINAPI mfattributes_LockStore(IMFAttributes *iface)
3240 struct attributes *attributes = impl_from_IMFAttributes(iface);
3242 TRACE("%p.\n", iface);
3244 return attributes_LockStore(attributes);
3247 static HRESULT WINAPI mfattributes_UnlockStore(IMFAttributes *iface)
3249 struct attributes *attributes = impl_from_IMFAttributes(iface);
3251 TRACE("%p.\n", iface);
3253 return attributes_UnlockStore(attributes);
3256 static HRESULT WINAPI mfattributes_GetCount(IMFAttributes *iface, UINT32 *count)
3258 struct attributes *attributes = impl_from_IMFAttributes(iface);
3260 TRACE("%p, %p.\n", iface, count);
3262 return attributes_GetCount(attributes, count);
3265 static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
3267 struct attributes *attributes = impl_from_IMFAttributes(iface);
3269 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
3271 return attributes_GetItemByIndex(attributes, index, key, value);
3274 static HRESULT WINAPI mfattributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
3276 struct attributes *attributes = impl_from_IMFAttributes(iface);
3278 TRACE("%p, %p.\n", iface, dest);
3280 return attributes_CopyAllItems(attributes, dest);
3283 static const IMFAttributesVtbl mfattributes_vtbl =
3285 mfattributes_QueryInterface,
3286 mfattributes_AddRef,
3287 mfattributes_Release,
3288 mfattributes_GetItem,
3289 mfattributes_GetItemType,
3290 mfattributes_CompareItem,
3291 mfattributes_Compare,
3292 mfattributes_GetUINT32,
3293 mfattributes_GetUINT64,
3294 mfattributes_GetDouble,
3295 mfattributes_GetGUID,
3296 mfattributes_GetStringLength,
3297 mfattributes_GetString,
3298 mfattributes_GetAllocatedString,
3299 mfattributes_GetBlobSize,
3300 mfattributes_GetBlob,
3301 mfattributes_GetAllocatedBlob,
3302 mfattributes_GetUnknown,
3303 mfattributes_SetItem,
3304 mfattributes_DeleteItem,
3305 mfattributes_DeleteAllItems,
3306 mfattributes_SetUINT32,
3307 mfattributes_SetUINT64,
3308 mfattributes_SetDouble,
3309 mfattributes_SetGUID,
3310 mfattributes_SetString,
3311 mfattributes_SetBlob,
3312 mfattributes_SetUnknown,
3313 mfattributes_LockStore,
3314 mfattributes_UnlockStore,
3315 mfattributes_GetCount,
3316 mfattributes_GetItemByIndex,
3317 mfattributes_CopyAllItems
3320 HRESULT init_attributes_object(struct attributes *object, UINT32 size)
3322 object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
3323 object->ref = 1;
3324 InitializeCriticalSection(&object->cs);
3326 object->attributes = NULL;
3327 object->count = 0;
3328 object->capacity = 0;
3329 if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
3330 sizeof(*object->attributes)))
3332 DeleteCriticalSection(&object->cs);
3333 return E_OUTOFMEMORY;
3336 return S_OK;
3339 void clear_attributes_object(struct attributes *object)
3341 size_t i;
3343 for (i = 0; i < object->count; i++)
3344 PropVariantClear(&object->attributes[i].value);
3345 free(object->attributes);
3347 DeleteCriticalSection(&object->cs);
3350 /***********************************************************************
3351 * MFCreateAttributes (mfplat.@)
3353 HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
3355 struct attributes *object;
3356 HRESULT hr;
3358 TRACE("%p, %d\n", attributes, size);
3360 if (!(object = calloc(1, sizeof(*object))))
3361 return E_OUTOFMEMORY;
3363 if (FAILED(hr = init_attributes_object(object, size)))
3365 free(object);
3366 return hr;
3368 *attributes = &object->IMFAttributes_iface;
3370 return S_OK;
3373 #define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
3375 struct attributes_store_header
3377 DWORD magic;
3378 UINT32 count;
3381 struct attributes_store_item
3383 GUID key;
3384 QWORD type;
3385 union
3387 double f;
3388 UINT32 i32;
3389 UINT64 i64;
3390 struct
3392 DWORD size;
3393 DWORD offset;
3394 } subheader;
3395 } u;
3398 /***********************************************************************
3399 * MFGetAttributesAsBlobSize (mfplat.@)
3401 HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
3403 unsigned int i, count, length;
3404 HRESULT hr;
3405 GUID key;
3407 TRACE("%p, %p.\n", attributes, size);
3409 IMFAttributes_LockStore(attributes);
3411 hr = IMFAttributes_GetCount(attributes, &count);
3413 *size = sizeof(struct attributes_store_header);
3415 for (i = 0; i < count; ++i)
3417 MF_ATTRIBUTE_TYPE type;
3419 hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
3420 if (FAILED(hr))
3421 break;
3423 *size += sizeof(struct attributes_store_item);
3425 IMFAttributes_GetItemType(attributes, &key, &type);
3427 switch (type)
3429 case MF_ATTRIBUTE_GUID:
3430 *size += sizeof(GUID);
3431 break;
3432 case MF_ATTRIBUTE_STRING:
3433 IMFAttributes_GetStringLength(attributes, &key, &length);
3434 *size += (length + 1) * sizeof(WCHAR);
3435 break;
3436 case MF_ATTRIBUTE_BLOB:
3437 IMFAttributes_GetBlobSize(attributes, &key, &length);
3438 *size += length;
3439 break;
3440 case MF_ATTRIBUTE_UINT32:
3441 case MF_ATTRIBUTE_UINT64:
3442 case MF_ATTRIBUTE_DOUBLE:
3443 case MF_ATTRIBUTE_IUNKNOWN:
3444 default:
3449 IMFAttributes_UnlockStore(attributes);
3451 return hr;
3454 struct attr_serialize_context
3456 UINT8 *buffer;
3457 UINT8 *ptr;
3458 UINT32 size;
3461 static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
3463 memcpy(context->ptr, value, size);
3464 context->ptr += size;
3467 static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
3468 const void *value)
3470 switch (item->type)
3472 case MF_ATTRIBUTE_UINT32:
3473 case MF_ATTRIBUTE_UINT64:
3474 case MF_ATTRIBUTE_DOUBLE:
3475 attributes_serialize_write(context, item, sizeof(*item));
3476 break;
3477 case MF_ATTRIBUTE_GUID:
3478 case MF_ATTRIBUTE_STRING:
3479 case MF_ATTRIBUTE_BLOB:
3480 item->u.subheader.offset = context->size - item->u.subheader.size;
3481 attributes_serialize_write(context, item, sizeof(*item));
3482 memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
3483 context->size -= item->u.subheader.size;
3484 break;
3485 default:
3486 return FALSE;
3489 return TRUE;
3492 /***********************************************************************
3493 * MFGetAttributesAsBlob (mfplat.@)
3495 HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
3497 struct attributes_store_header header;
3498 struct attr_serialize_context context;
3499 unsigned int required_size, i;
3500 PROPVARIANT value;
3501 UINT32 count;
3502 HRESULT hr;
3504 TRACE("%p, %p, %u.\n", attributes, buffer, size);
3506 if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
3507 return hr;
3509 if (required_size > size)
3510 return MF_E_BUFFERTOOSMALL;
3512 context.buffer = buffer;
3513 context.ptr = buffer;
3514 context.size = required_size;
3516 IMFAttributes_LockStore(attributes);
3518 header.magic = ATTRIBUTES_STORE_MAGIC;
3519 header.count = 0; /* Will be updated later */
3520 IMFAttributes_GetCount(attributes, &count);
3522 attributes_serialize_write(&context, &header, sizeof(header));
3524 for (i = 0; i < count; ++i)
3526 struct attributes_store_item item;
3527 const void *data = NULL;
3529 hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
3530 if (FAILED(hr))
3531 break;
3533 item.type = value.vt;
3535 switch (value.vt)
3537 case MF_ATTRIBUTE_UINT32:
3538 case MF_ATTRIBUTE_UINT64:
3539 item.u.i64 = value.uhVal.QuadPart;
3540 break;
3541 case MF_ATTRIBUTE_DOUBLE:
3542 item.u.f = value.dblVal;
3543 break;
3544 case MF_ATTRIBUTE_GUID:
3545 item.u.subheader.size = sizeof(*value.puuid);
3546 data = value.puuid;
3547 break;
3548 case MF_ATTRIBUTE_STRING:
3549 item.u.subheader.size = (lstrlenW(value.pwszVal) + 1) * sizeof(WCHAR);
3550 data = value.pwszVal;
3551 break;
3552 case MF_ATTRIBUTE_BLOB:
3553 item.u.subheader.size = value.caub.cElems;
3554 data = value.caub.pElems;
3555 break;
3556 case MF_ATTRIBUTE_IUNKNOWN:
3557 break;
3558 default:
3559 WARN("Unknown attribute type %#x.\n", value.vt);
3562 if (attributes_serialize_write_item(&context, &item, data))
3563 header.count++;
3565 PropVariantClear(&value);
3568 memcpy(context.buffer, &header, sizeof(header));
3570 IMFAttributes_UnlockStore(attributes);
3572 return S_OK;
3575 static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
3577 if (context->size < (context->ptr - context->buffer) + size)
3578 return E_INVALIDARG;
3580 memcpy(value, context->ptr, size);
3581 context->ptr += size;
3583 return S_OK;
3586 /***********************************************************************
3587 * MFInitAttributesFromBlob (mfplat.@)
3589 HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
3591 struct attr_serialize_context context;
3592 struct attributes_store_header header;
3593 struct attributes_store_item item;
3594 IMFAttributes *attributes;
3595 unsigned int i;
3596 HRESULT hr;
3598 TRACE("%p, %p, %u.\n", dest, buffer, size);
3600 context.buffer = (UINT8 *)buffer;
3601 context.ptr = (UINT8 *)buffer;
3602 context.size = size;
3604 /* Validate buffer structure. */
3605 if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
3606 return hr;
3608 if (header.magic != ATTRIBUTES_STORE_MAGIC)
3609 return E_UNEXPECTED;
3611 if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
3612 return hr;
3614 for (i = 0; i < header.count; ++i)
3616 if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
3617 break;
3619 hr = E_UNEXPECTED;
3621 switch (item.type)
3623 case MF_ATTRIBUTE_UINT32:
3624 hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
3625 break;
3626 case MF_ATTRIBUTE_UINT64:
3627 hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
3628 break;
3629 case MF_ATTRIBUTE_DOUBLE:
3630 hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
3631 break;
3632 case MF_ATTRIBUTE_GUID:
3633 if (item.u.subheader.size == sizeof(GUID) &&
3634 item.u.subheader.offset + item.u.subheader.size <= context.size)
3636 hr = IMFAttributes_SetGUID(attributes, &item.key,
3637 (const GUID *)(context.buffer + item.u.subheader.offset));
3639 break;
3640 case MF_ATTRIBUTE_STRING:
3641 if (item.u.subheader.size >= sizeof(WCHAR) &&
3642 item.u.subheader.offset + item.u.subheader.size <= context.size)
3644 hr = IMFAttributes_SetString(attributes, &item.key,
3645 (const WCHAR *)(context.buffer + item.u.subheader.offset));
3647 break;
3648 case MF_ATTRIBUTE_BLOB:
3649 if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
3651 hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
3652 item.u.subheader.size);
3654 break;
3655 default:
3659 if (FAILED(hr))
3660 break;
3663 if (SUCCEEDED(hr))
3665 IMFAttributes_DeleteAllItems(dest);
3666 hr = IMFAttributes_CopyAllItems(attributes, dest);
3669 IMFAttributes_Release(attributes);
3671 return hr;
3674 struct bytestream
3676 struct attributes attributes;
3677 IMFByteStream IMFByteStream_iface;
3678 IMFGetService IMFGetService_iface;
3679 IRtwqAsyncCallback read_callback;
3680 IRtwqAsyncCallback write_callback;
3681 IStream *stream;
3682 HANDLE hfile;
3683 QWORD position;
3684 DWORD capabilities;
3685 struct list pending;
3686 CRITICAL_SECTION cs;
3689 static inline struct bytestream *impl_from_IMFByteStream(IMFByteStream *iface)
3691 return CONTAINING_RECORD(iface, struct bytestream, IMFByteStream_iface);
3694 static struct bytestream *impl_bytestream_from_IMFGetService(IMFGetService *iface)
3696 return CONTAINING_RECORD(iface, struct bytestream, IMFGetService_iface);
3699 static struct bytestream *impl_from_read_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3701 return CONTAINING_RECORD(iface, struct bytestream, read_callback);
3704 static struct bytestream *impl_from_write_callback_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
3706 return CONTAINING_RECORD(iface, struct bytestream, write_callback);
3709 enum async_stream_op_type
3711 ASYNC_STREAM_OP_READ,
3712 ASYNC_STREAM_OP_WRITE,
3715 struct async_stream_op
3717 IUnknown IUnknown_iface;
3718 LONG refcount;
3719 union
3721 const BYTE *src;
3722 BYTE *dest;
3723 } u;
3724 QWORD position;
3725 ULONG requested_length;
3726 ULONG actual_length;
3727 IMFAsyncResult *caller;
3728 struct list entry;
3729 enum async_stream_op_type type;
3732 static struct async_stream_op *impl_async_stream_op_from_IUnknown(IUnknown *iface)
3734 return CONTAINING_RECORD(iface, struct async_stream_op, IUnknown_iface);
3737 static HRESULT WINAPI async_stream_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
3739 if (IsEqualIID(riid, &IID_IUnknown))
3741 *obj = iface;
3742 IUnknown_AddRef(iface);
3743 return S_OK;
3746 WARN("Unsupported %s.\n", debugstr_guid(riid));
3747 *obj = NULL;
3748 return E_NOINTERFACE;
3751 static ULONG WINAPI async_stream_op_AddRef(IUnknown *iface)
3753 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3754 ULONG refcount = InterlockedIncrement(&op->refcount);
3756 TRACE("%p, refcount %ld.\n", iface, refcount);
3758 return refcount;
3761 static ULONG WINAPI async_stream_op_Release(IUnknown *iface)
3763 struct async_stream_op *op = impl_async_stream_op_from_IUnknown(iface);
3764 ULONG refcount = InterlockedDecrement(&op->refcount);
3766 TRACE("%p, refcount %ld.\n", iface, refcount);
3768 if (!refcount)
3770 if (op->caller)
3771 IMFAsyncResult_Release(op->caller);
3772 free(op);
3775 return refcount;
3778 static const IUnknownVtbl async_stream_op_vtbl =
3780 async_stream_op_QueryInterface,
3781 async_stream_op_AddRef,
3782 async_stream_op_Release,
3785 static HRESULT bytestream_create_io_request(struct bytestream *stream, enum async_stream_op_type type,
3786 const BYTE *data, ULONG size, IMFAsyncCallback *callback, IUnknown *state)
3788 struct async_stream_op *op;
3789 IRtwqAsyncResult *request;
3790 HRESULT hr;
3792 op = malloc(sizeof(*op));
3793 if (!op)
3794 return E_OUTOFMEMORY;
3796 op->IUnknown_iface.lpVtbl = &async_stream_op_vtbl;
3797 op->refcount = 1;
3798 op->u.src = data;
3799 op->position = stream->position;
3800 op->requested_length = size;
3801 op->type = type;
3802 if (FAILED(hr = RtwqCreateAsyncResult((IUnknown *)&stream->IMFByteStream_iface, (IRtwqAsyncCallback *)callback, state,
3803 (IRtwqAsyncResult **)&op->caller)))
3805 goto failed;
3808 if (FAILED(hr = RtwqCreateAsyncResult(&op->IUnknown_iface, type == ASYNC_STREAM_OP_READ ? &stream->read_callback :
3809 &stream->write_callback, NULL, &request)))
3810 goto failed;
3812 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_IO, 0, request);
3813 IRtwqAsyncResult_Release(request);
3815 failed:
3816 IUnknown_Release(&op->IUnknown_iface);
3817 return hr;
3820 static HRESULT bytestream_complete_io_request(struct bytestream *stream, enum async_stream_op_type type,
3821 IMFAsyncResult *result, ULONG *actual_length)
3823 struct async_stream_op *op = NULL, *cur;
3824 HRESULT hr;
3826 EnterCriticalSection(&stream->cs);
3827 LIST_FOR_EACH_ENTRY(cur, &stream->pending, struct async_stream_op, entry)
3829 if (cur->caller == result && cur->type == type)
3831 op = cur;
3832 list_remove(&cur->entry);
3833 break;
3836 LeaveCriticalSection(&stream->cs);
3838 if (!op)
3839 return E_INVALIDARG;
3841 if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result)))
3842 *actual_length = op->actual_length;
3844 IUnknown_Release(&op->IUnknown_iface);
3846 return hr;
3849 static HRESULT WINAPI bytestream_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
3851 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
3852 IsEqualIID(riid, &IID_IUnknown))
3854 *obj = iface;
3855 IRtwqAsyncCallback_AddRef(iface);
3856 return S_OK;
3859 WARN("Unsupported %s.\n", debugstr_guid(riid));
3860 *obj = NULL;
3861 return E_NOINTERFACE;
3864 static ULONG WINAPI bytestream_read_callback_AddRef(IRtwqAsyncCallback *iface)
3866 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3867 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3870 static ULONG WINAPI bytestream_read_callback_Release(IRtwqAsyncCallback *iface)
3872 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
3873 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3876 static HRESULT WINAPI bytestream_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
3878 return E_NOTIMPL;
3881 static ULONG WINAPI bytestream_write_callback_AddRef(IRtwqAsyncCallback *iface)
3883 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3884 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
3887 static ULONG WINAPI bytestream_write_callback_Release(IRtwqAsyncCallback *iface)
3889 struct bytestream *stream = impl_from_write_callback_IRtwqAsyncCallback(iface);
3890 return IMFByteStream_Release(&stream->IMFByteStream_iface);
3893 static HRESULT WINAPI bytestream_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
3895 struct bytestream *stream = impl_from_IMFByteStream(iface);
3897 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
3899 if (IsEqualIID(riid, &IID_IMFByteStream) ||
3900 IsEqualIID(riid, &IID_IUnknown))
3902 *out = &stream->IMFByteStream_iface;
3904 else if (IsEqualIID(riid, &IID_IMFAttributes))
3906 *out = &stream->attributes.IMFAttributes_iface;
3908 else if (stream->IMFGetService_iface.lpVtbl && IsEqualIID(riid, &IID_IMFGetService))
3910 *out = &stream->IMFGetService_iface;
3912 else
3914 WARN("Unsupported %s.\n", debugstr_guid(riid));
3915 *out = NULL;
3916 return E_NOINTERFACE;
3919 IUnknown_AddRef((IUnknown*)*out);
3920 return S_OK;
3923 static ULONG WINAPI bytestream_AddRef(IMFByteStream *iface)
3925 struct bytestream *stream = impl_from_IMFByteStream(iface);
3926 ULONG refcount = InterlockedIncrement(&stream->attributes.ref);
3928 TRACE("%p, refcount %ld.\n", iface, refcount);
3930 return refcount;
3933 static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
3935 struct bytestream *stream = impl_from_IMFByteStream(iface);
3936 ULONG refcount = InterlockedDecrement(&stream->attributes.ref);
3937 struct async_stream_op *cur, *cur2;
3939 TRACE("%p, refcount %ld.\n", iface, refcount);
3941 if (!refcount)
3943 clear_attributes_object(&stream->attributes);
3944 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &stream->pending, struct async_stream_op, entry)
3946 list_remove(&cur->entry);
3947 IUnknown_Release(&cur->IUnknown_iface);
3949 DeleteCriticalSection(&stream->cs);
3950 if (stream->stream)
3951 IStream_Release(stream->stream);
3952 if (stream->hfile)
3953 CloseHandle(stream->hfile);
3954 free(stream);
3957 return refcount;
3960 static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3962 struct bytestream *stream = impl_from_IMFByteStream(iface);
3963 STATSTG stat;
3964 HRESULT hr;
3966 TRACE("%p, %p.\n", iface, capabilities);
3968 if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
3969 return hr;
3971 *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
3972 if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
3973 *capabilities |= MFBYTESTREAM_IS_WRITABLE;
3975 return S_OK;
3978 static HRESULT WINAPI bytestream_file_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
3980 struct bytestream *stream = impl_from_IMFByteStream(iface);
3982 TRACE("%p, %p.\n", iface, capabilities);
3984 *capabilities = stream->capabilities;
3986 return S_OK;
3989 static HRESULT WINAPI bytestream_file_SetLength(IMFByteStream *iface, QWORD length)
3991 FIXME("%p, %s\n", iface, wine_dbgstr_longlong(length));
3993 return E_NOTIMPL;
3996 static HRESULT WINAPI bytestream_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
3998 struct bytestream *stream = impl_from_IMFByteStream(iface);
4000 TRACE("%p, %p.\n", iface, position);
4002 if (!position)
4003 return E_INVALIDARG;
4005 *position = stream->position;
4007 return S_OK;
4010 static HRESULT WINAPI bytestream_file_GetLength(IMFByteStream *iface, QWORD *length)
4012 struct bytestream *stream = impl_from_IMFByteStream(iface);
4013 LARGE_INTEGER li;
4015 TRACE("%p, %p.\n", iface, length);
4017 if (!length)
4018 return E_INVALIDARG;
4020 if (GetFileSizeEx(stream->hfile, &li))
4021 *length = li.QuadPart;
4022 else
4023 return HRESULT_FROM_WIN32(GetLastError());
4025 return S_OK;
4028 static HRESULT WINAPI bytestream_file_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4030 struct bytestream *stream = impl_from_IMFByteStream(iface);
4031 LARGE_INTEGER position, length;
4032 HRESULT hr = S_OK;
4034 TRACE("%p, %p.\n", iface, ret);
4036 EnterCriticalSection(&stream->cs);
4038 position.QuadPart = 0;
4039 if (SetFilePointerEx(stream->hfile, position, &length, FILE_END))
4040 *ret = stream->position >= length.QuadPart;
4041 else
4042 hr = HRESULT_FROM_WIN32(GetLastError());
4044 LeaveCriticalSection(&stream->cs);
4046 return hr;
4049 static HRESULT WINAPI bytestream_file_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4051 struct bytestream *stream = impl_from_IMFByteStream(iface);
4052 LARGE_INTEGER position;
4053 HRESULT hr = S_OK;
4054 BOOL ret;
4056 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, read_len);
4058 EnterCriticalSection(&stream->cs);
4060 position.QuadPart = stream->position;
4061 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
4063 if ((ret = ReadFile(stream->hfile, buffer, size, read_len, NULL)))
4064 stream->position += *read_len;
4067 if (!ret)
4068 hr = HRESULT_FROM_WIN32(GetLastError());
4070 LeaveCriticalSection(&stream->cs);
4072 return hr;
4075 static HRESULT WINAPI bytestream_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size, IMFAsyncCallback *callback,
4076 IUnknown *state)
4078 struct bytestream *stream = impl_from_IMFByteStream(iface);
4080 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4082 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_READ, data, size, callback, state);
4085 static HRESULT WINAPI bytestream_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4087 struct bytestream *stream = impl_from_IMFByteStream(iface);
4089 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4091 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_READ, result, byte_read);
4094 static HRESULT WINAPI bytestream_file_Write(IMFByteStream *iface, const BYTE *data, ULONG size, ULONG *written)
4096 struct bytestream *stream = impl_from_IMFByteStream(iface);
4097 LARGE_INTEGER position;
4098 HRESULT hr = S_OK;
4099 BOOL ret;
4101 TRACE("%p, %p, %lu, %p\n", iface, data, size, written);
4103 EnterCriticalSection(&stream->cs);
4105 position.QuadPart = stream->position;
4106 if ((ret = SetFilePointerEx(stream->hfile, position, NULL, FILE_BEGIN)))
4108 if ((ret = WriteFile(stream->hfile, data, size, written, NULL)))
4109 stream->position += *written;
4112 if (!ret)
4113 hr = HRESULT_FROM_WIN32(GetLastError());
4115 LeaveCriticalSection(&stream->cs);
4117 return hr;
4120 static HRESULT WINAPI bytestream_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4121 IMFAsyncCallback *callback, IUnknown *state)
4123 struct bytestream *stream = impl_from_IMFByteStream(iface);
4125 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4127 return bytestream_create_io_request(stream, ASYNC_STREAM_OP_WRITE, data, size, callback, state);
4130 static HRESULT WINAPI bytestream_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4132 struct bytestream *stream = impl_from_IMFByteStream(iface);
4134 TRACE("%p, %p, %p.\n", iface, result, written);
4136 return bytestream_complete_io_request(stream, ASYNC_STREAM_OP_WRITE, result, written);
4139 static HRESULT WINAPI bytestream_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset,
4140 DWORD flags, QWORD *current)
4142 struct bytestream *stream = impl_from_IMFByteStream(iface);
4143 HRESULT hr = S_OK;
4145 TRACE("%p, %u, %s, %#lx, %p.\n", iface, origin, wine_dbgstr_longlong(offset), flags, current);
4147 EnterCriticalSection(&stream->cs);
4149 switch (origin)
4151 case msoBegin:
4152 stream->position = offset;
4153 break;
4154 case msoCurrent:
4155 stream->position += offset;
4156 break;
4157 default:
4158 WARN("Unknown origin mode %d.\n", origin);
4159 hr = E_INVALIDARG;
4162 *current = stream->position;
4164 LeaveCriticalSection(&stream->cs);
4166 return hr;
4169 static HRESULT WINAPI bytestream_file_Flush(IMFByteStream *iface)
4171 FIXME("%p\n", iface);
4173 return E_NOTIMPL;
4176 static HRESULT WINAPI bytestream_file_Close(IMFByteStream *iface)
4178 FIXME("%p\n", iface);
4180 return E_NOTIMPL;
4183 static HRESULT WINAPI bytestream_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4185 struct bytestream *stream = impl_from_IMFByteStream(iface);
4187 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4189 EnterCriticalSection(&stream->cs);
4190 stream->position = position;
4191 LeaveCriticalSection(&stream->cs);
4193 return S_OK;
4196 static const IMFByteStreamVtbl bytestream_file_vtbl =
4198 bytestream_QueryInterface,
4199 bytestream_AddRef,
4200 bytestream_Release,
4201 bytestream_file_GetCapabilities,
4202 bytestream_file_GetLength,
4203 bytestream_file_SetLength,
4204 bytestream_GetCurrentPosition,
4205 bytestream_SetCurrentPosition,
4206 bytestream_file_IsEndOfStream,
4207 bytestream_file_Read,
4208 bytestream_BeginRead,
4209 bytestream_EndRead,
4210 bytestream_file_Write,
4211 bytestream_BeginWrite,
4212 bytestream_EndWrite,
4213 bytestream_Seek,
4214 bytestream_file_Flush,
4215 bytestream_file_Close
4218 static HRESULT WINAPI bytestream_stream_GetLength(IMFByteStream *iface, QWORD *length)
4220 struct bytestream *stream = impl_from_IMFByteStream(iface);
4221 STATSTG statstg;
4222 HRESULT hr;
4224 TRACE("%p, %p.\n", iface, length);
4226 if (FAILED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4227 return hr;
4229 *length = statstg.cbSize.QuadPart;
4231 return S_OK;
4234 static HRESULT WINAPI bytestream_stream_SetLength(IMFByteStream *iface, QWORD length)
4236 struct bytestream *stream = impl_from_IMFByteStream(iface);
4237 ULARGE_INTEGER size;
4238 HRESULT hr;
4240 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4242 EnterCriticalSection(&stream->cs);
4244 size.QuadPart = length;
4245 hr = IStream_SetSize(stream->stream, size);
4247 LeaveCriticalSection(&stream->cs);
4249 return hr;
4252 static HRESULT WINAPI bytestream_stream_IsEndOfStream(IMFByteStream *iface, BOOL *ret)
4254 struct bytestream *stream = impl_from_IMFByteStream(iface);
4255 STATSTG statstg;
4256 HRESULT hr;
4258 TRACE("%p, %p.\n", iface, ret);
4260 EnterCriticalSection(&stream->cs);
4262 if (SUCCEEDED(hr = IStream_Stat(stream->stream, &statstg, STATFLAG_NONAME)))
4263 *ret = stream->position >= statstg.cbSize.QuadPart;
4265 LeaveCriticalSection(&stream->cs);
4267 return hr;
4270 static HRESULT WINAPI bytestream_stream_Read(IMFByteStream *iface, BYTE *buffer, ULONG size, ULONG *read_len)
4272 struct bytestream *stream = impl_from_IMFByteStream(iface);
4273 LARGE_INTEGER position;
4274 HRESULT hr;
4276 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, read_len);
4278 EnterCriticalSection(&stream->cs);
4280 position.QuadPart = stream->position;
4281 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4283 if (SUCCEEDED(hr = IStream_Read(stream->stream, buffer, size, read_len)))
4284 stream->position += *read_len;
4287 LeaveCriticalSection(&stream->cs);
4289 return hr;
4292 static HRESULT WINAPI bytestream_stream_Write(IMFByteStream *iface, const BYTE *buffer, ULONG size, ULONG *written)
4294 struct bytestream *stream = impl_from_IMFByteStream(iface);
4295 LARGE_INTEGER position;
4296 HRESULT hr;
4298 TRACE("%p, %p, %lu, %p.\n", iface, buffer, size, written);
4300 EnterCriticalSection(&stream->cs);
4302 position.QuadPart = stream->position;
4303 if (SUCCEEDED(hr = IStream_Seek(stream->stream, position, STREAM_SEEK_SET, NULL)))
4305 if (SUCCEEDED(hr = IStream_Write(stream->stream, buffer, size, written)))
4306 stream->position += *written;
4309 LeaveCriticalSection(&stream->cs);
4311 return hr;
4314 static HRESULT WINAPI bytestream_stream_Flush(IMFByteStream *iface)
4316 struct bytestream *stream = impl_from_IMFByteStream(iface);
4318 TRACE("%p.\n", iface);
4320 return IStream_Commit(stream->stream, STGC_DEFAULT);
4323 static HRESULT WINAPI bytestream_stream_Close(IMFByteStream *iface)
4325 TRACE("%p.\n", iface);
4327 return S_OK;
4330 static const IMFByteStreamVtbl bytestream_stream_vtbl =
4332 bytestream_QueryInterface,
4333 bytestream_AddRef,
4334 bytestream_Release,
4335 bytestream_stream_GetCapabilities,
4336 bytestream_stream_GetLength,
4337 bytestream_stream_SetLength,
4338 bytestream_GetCurrentPosition,
4339 bytestream_SetCurrentPosition,
4340 bytestream_stream_IsEndOfStream,
4341 bytestream_stream_Read,
4342 bytestream_BeginRead,
4343 bytestream_EndRead,
4344 bytestream_stream_Write,
4345 bytestream_BeginWrite,
4346 bytestream_EndWrite,
4347 bytestream_Seek,
4348 bytestream_stream_Flush,
4349 bytestream_stream_Close,
4352 static inline struct bytestream *impl_from_IMFByteStream_IMFAttributes(IMFAttributes *iface)
4354 return CONTAINING_RECORD(iface, struct bytestream, attributes.IMFAttributes_iface);
4357 static HRESULT WINAPI bytestream_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
4359 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4360 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, out);
4363 static ULONG WINAPI bytestream_attributes_AddRef(IMFAttributes *iface)
4365 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4366 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4369 static ULONG WINAPI bytestream_attributes_Release(IMFAttributes *iface)
4371 struct bytestream *stream = impl_from_IMFByteStream_IMFAttributes(iface);
4372 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4375 static const IMFAttributesVtbl bytestream_attributes_vtbl =
4377 bytestream_attributes_QueryInterface,
4378 bytestream_attributes_AddRef,
4379 bytestream_attributes_Release,
4380 mfattributes_GetItem,
4381 mfattributes_GetItemType,
4382 mfattributes_CompareItem,
4383 mfattributes_Compare,
4384 mfattributes_GetUINT32,
4385 mfattributes_GetUINT64,
4386 mfattributes_GetDouble,
4387 mfattributes_GetGUID,
4388 mfattributes_GetStringLength,
4389 mfattributes_GetString,
4390 mfattributes_GetAllocatedString,
4391 mfattributes_GetBlobSize,
4392 mfattributes_GetBlob,
4393 mfattributes_GetAllocatedBlob,
4394 mfattributes_GetUnknown,
4395 mfattributes_SetItem,
4396 mfattributes_DeleteItem,
4397 mfattributes_DeleteAllItems,
4398 mfattributes_SetUINT32,
4399 mfattributes_SetUINT64,
4400 mfattributes_SetDouble,
4401 mfattributes_SetGUID,
4402 mfattributes_SetString,
4403 mfattributes_SetBlob,
4404 mfattributes_SetUnknown,
4405 mfattributes_LockStore,
4406 mfattributes_UnlockStore,
4407 mfattributes_GetCount,
4408 mfattributes_GetItemByIndex,
4409 mfattributes_CopyAllItems
4412 static HRESULT WINAPI bytestream_read_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4414 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4415 struct async_stream_op *op;
4416 IUnknown *object;
4417 HRESULT hr;
4419 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4420 return hr;
4422 op = impl_async_stream_op_from_IUnknown(object);
4424 EnterCriticalSection(&stream->cs);
4426 hr = IMFByteStream_Read(&stream->IMFByteStream_iface, op->u.dest, op->requested_length, &op->actual_length);
4427 if(FAILED(hr)) TRACE("Read failed: %#lx\n", hr);
4428 IMFAsyncResult_SetStatus(op->caller, hr);
4429 list_add_tail(&stream->pending, &op->entry);
4431 LeaveCriticalSection(&stream->cs);
4433 MFInvokeCallback(op->caller);
4435 return S_OK;
4438 static HRESULT WINAPI bytestream_write_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
4440 struct bytestream *stream = impl_from_read_callback_IRtwqAsyncCallback(iface);
4441 struct async_stream_op *op;
4442 IUnknown *object;
4443 HRESULT hr;
4445 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
4446 return hr;
4448 op = impl_async_stream_op_from_IUnknown(object);
4450 EnterCriticalSection(&stream->cs);
4452 hr = IMFByteStream_Write(&stream->IMFByteStream_iface, op->u.src, op->requested_length, &op->actual_length);
4453 if(FAILED(hr)) TRACE("Write failed: %#lx\n", hr);
4454 IMFAsyncResult_SetStatus(op->caller, hr);
4455 list_add_tail(&stream->pending, &op->entry);
4457 LeaveCriticalSection(&stream->cs);
4459 MFInvokeCallback(op->caller);
4461 return S_OK;
4464 static const IRtwqAsyncCallbackVtbl bytestream_read_callback_vtbl =
4466 bytestream_callback_QueryInterface,
4467 bytestream_read_callback_AddRef,
4468 bytestream_read_callback_Release,
4469 bytestream_callback_GetParameters,
4470 bytestream_read_callback_Invoke,
4473 static const IRtwqAsyncCallbackVtbl bytestream_write_callback_vtbl =
4475 bytestream_callback_QueryInterface,
4476 bytestream_write_callback_AddRef,
4477 bytestream_write_callback_Release,
4478 bytestream_callback_GetParameters,
4479 bytestream_write_callback_Invoke,
4482 /***********************************************************************
4483 * MFCreateMFByteStreamOnStream (mfplat.@)
4485 HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream)
4487 struct bytestream *object;
4488 LARGE_INTEGER position;
4489 STATSTG stat;
4490 HRESULT hr;
4492 TRACE("%p, %p.\n", stream, bytestream);
4494 if (!(object = calloc(1, sizeof(*object))))
4495 return E_OUTOFMEMORY;
4497 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
4499 free(object);
4500 return hr;
4503 object->IMFByteStream_iface.lpVtbl = &bytestream_stream_vtbl;
4504 object->attributes.IMFAttributes_iface.lpVtbl = &bytestream_attributes_vtbl;
4505 object->read_callback.lpVtbl = &bytestream_read_callback_vtbl;
4506 object->write_callback.lpVtbl = &bytestream_write_callback_vtbl;
4507 InitializeCriticalSection(&object->cs);
4508 list_init(&object->pending);
4510 object->stream = stream;
4511 IStream_AddRef(object->stream);
4512 position.QuadPart = 0;
4513 IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
4515 if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
4517 if (stat.pwcsName)
4519 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
4520 stat.pwcsName);
4521 CoTaskMemFree(stat.pwcsName);
4525 *bytestream = &object->IMFByteStream_iface;
4527 return S_OK;
4530 static HRESULT WINAPI bytestream_file_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
4532 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4533 return IMFByteStream_QueryInterface(&stream->IMFByteStream_iface, riid, obj);
4536 static ULONG WINAPI bytestream_file_getservice_AddRef(IMFGetService *iface)
4538 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4539 return IMFByteStream_AddRef(&stream->IMFByteStream_iface);
4542 static ULONG WINAPI bytestream_file_getservice_Release(IMFGetService *iface)
4544 struct bytestream *stream = impl_bytestream_from_IMFGetService(iface);
4545 return IMFByteStream_Release(&stream->IMFByteStream_iface);
4548 static HRESULT WINAPI bytestream_file_getservice_GetService(IMFGetService *iface, REFGUID service,
4549 REFIID riid, void **obj)
4551 FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
4553 return E_NOTIMPL;
4556 static const IMFGetServiceVtbl bytestream_file_getservice_vtbl =
4558 bytestream_file_getservice_QueryInterface,
4559 bytestream_file_getservice_AddRef,
4560 bytestream_file_getservice_Release,
4561 bytestream_file_getservice_GetService,
4564 static HRESULT create_file_bytestream(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4565 const WCHAR *path, BOOL is_tempfile, IMFByteStream **bytestream)
4567 DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK;
4568 DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0;
4569 DWORD filesharemode = FILE_SHARE_READ | FILE_SHARE_DELETE;
4570 struct bytestream *object;
4571 FILETIME writetime;
4572 HANDLE file;
4573 HRESULT hr;
4575 switch (accessmode)
4577 case MF_ACCESSMODE_READ:
4578 fileaccessmode = GENERIC_READ;
4579 capabilities |= MFBYTESTREAM_IS_READABLE;
4580 break;
4581 case MF_ACCESSMODE_WRITE:
4582 fileaccessmode = GENERIC_WRITE;
4583 capabilities |= MFBYTESTREAM_IS_WRITABLE;
4584 break;
4585 case MF_ACCESSMODE_READWRITE:
4586 fileaccessmode = GENERIC_READ | GENERIC_WRITE;
4587 capabilities |= (MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE);
4588 break;
4591 switch (openmode)
4593 case MF_OPENMODE_FAIL_IF_NOT_EXIST:
4594 filecreation_disposition = OPEN_EXISTING;
4595 break;
4596 case MF_OPENMODE_FAIL_IF_EXIST:
4597 filecreation_disposition = CREATE_NEW;
4598 break;
4599 case MF_OPENMODE_RESET_IF_EXIST:
4600 filecreation_disposition = TRUNCATE_EXISTING;
4601 break;
4602 case MF_OPENMODE_APPEND_IF_EXIST:
4603 filecreation_disposition = OPEN_ALWAYS;
4604 fileaccessmode |= FILE_APPEND_DATA;
4605 break;
4606 case MF_OPENMODE_DELETE_IF_EXIST:
4607 filecreation_disposition = CREATE_ALWAYS;
4608 break;
4611 if (flags & MF_FILEFLAGS_NOBUFFERING)
4612 fileattributes |= FILE_FLAG_NO_BUFFERING;
4613 if (is_tempfile)
4614 fileattributes |= FILE_FLAG_DELETE_ON_CLOSE;
4616 /* Open HANDLE to file */
4617 file = CreateFileW(path, fileaccessmode, filesharemode, NULL, filecreation_disposition, fileattributes, 0);
4618 if (file == INVALID_HANDLE_VALUE)
4619 return HRESULT_FROM_WIN32(GetLastError());
4621 if (!(object = calloc(1, sizeof(*object))))
4623 CloseHandle(file);
4624 return E_OUTOFMEMORY;
4627 if (FAILED(hr = init_attributes_object(&object->attributes, 2)))
4629 CloseHandle(file);
4630 free(object);
4631 return hr;
4633 object->IMFByteStream_iface.lpVtbl = &bytestream_file_vtbl;
4634 object->attributes.IMFAttributes_iface.lpVtbl = &bytestream_attributes_vtbl;
4635 object->IMFGetService_iface.lpVtbl = &bytestream_file_getservice_vtbl;
4636 object->read_callback.lpVtbl = &bytestream_read_callback_vtbl;
4637 object->write_callback.lpVtbl = &bytestream_write_callback_vtbl;
4638 InitializeCriticalSection(&object->cs);
4639 list_init(&object->pending);
4640 object->capabilities = capabilities;
4641 object->hfile = file;
4643 if (!is_tempfile && GetFileTime(file, NULL, NULL, &writetime))
4645 IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME,
4646 (const UINT8 *)&writetime, sizeof(writetime));
4649 IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, path);
4651 *bytestream = &object->IMFByteStream_iface;
4653 return S_OK;
4656 /***********************************************************************
4657 * MFCreateFile (mfplat.@)
4659 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4660 const WCHAR *path, IMFByteStream **bytestream)
4662 TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(path), bytestream);
4664 return create_file_bytestream(accessmode, openmode, flags, path, FALSE, bytestream);
4667 /***********************************************************************
4668 * MFCreateTempFile (mfplat.@)
4670 HRESULT WINAPI MFCreateTempFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
4671 IMFByteStream **bytestream)
4673 WCHAR name[24], tmppath[MAX_PATH], *path;
4674 ULONG64 rnd;
4675 size_t len;
4676 HRESULT hr;
4678 TRACE("%d, %d, %#x, %p.\n", accessmode, openmode, flags, bytestream);
4680 BCryptGenRandom(NULL, (UCHAR *)&rnd, sizeof(rnd), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
4681 swprintf(name, ARRAY_SIZE(name), L"MFP%llX.TMP", rnd);
4682 GetTempPathW(ARRAY_SIZE(tmppath), tmppath);
4684 len = wcslen(tmppath) + wcslen(name) + 2;
4685 if (!(path = malloc(len * sizeof(*path))))
4686 return E_OUTOFMEMORY;
4688 wcscpy(path, tmppath);
4689 PathCchAppend(path, len, name);
4691 hr = create_file_bytestream(accessmode, openmode, flags, path, TRUE, bytestream);
4693 free(path);
4695 return hr;
4698 struct bytestream_wrapper
4700 IMFByteStreamCacheControl IMFByteStreamCacheControl_iface;
4701 IMFByteStreamBuffering IMFByteStreamBuffering_iface;
4702 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
4703 IMFByteStreamTimeSeek IMFByteStreamTimeSeek_iface;
4704 IMFSampleOutputStream IMFSampleOutputStream_iface;
4705 IPropertyStore IPropertyStore_iface;
4706 IMFByteStream IMFByteStream_iface;
4707 IMFAttributes IMFAttributes_iface;
4708 LONG refcount;
4710 IMFByteStreamCacheControl *cache_control;
4711 IMFByteStreamBuffering *stream_buffering;
4712 IMFMediaEventGenerator *event_generator;
4713 IMFByteStreamTimeSeek *time_seek;
4714 IMFSampleOutputStream *sample_output;
4715 IPropertyStore *propstore;
4716 IMFByteStream *stream;
4717 IMFAttributes *attributes;
4718 BOOL is_closed;
4721 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStream(IMFByteStream *iface)
4723 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStream_iface);
4726 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamCacheControl(IMFByteStreamCacheControl *iface)
4728 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamCacheControl_iface);
4731 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamBuffering(IMFByteStreamBuffering *iface)
4733 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamBuffering_iface);
4736 static struct bytestream_wrapper *impl_wrapper_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
4738 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFMediaEventGenerator_iface);
4741 static struct bytestream_wrapper *impl_wrapper_from_IMFByteStreamTimeSeek(IMFByteStreamTimeSeek *iface)
4743 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFByteStreamTimeSeek_iface);
4746 static struct bytestream_wrapper *impl_wrapper_from_IMFSampleOutputStream(IMFSampleOutputStream *iface)
4748 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFSampleOutputStream_iface);
4751 static struct bytestream_wrapper *impl_wrapper_from_IPropertyStore(IPropertyStore *iface)
4753 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IPropertyStore_iface);
4756 static struct bytestream_wrapper *impl_wrapper_from_IMFAttributes(IMFAttributes *iface)
4758 return CONTAINING_RECORD(iface, struct bytestream_wrapper, IMFAttributes_iface);
4761 static HRESULT WINAPI bytestream_wrapper_QueryInterface(IMFByteStream *iface, REFIID riid, void **out)
4763 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4765 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
4767 if (IsEqualIID(riid, &IID_IMFByteStream) ||
4768 IsEqualIID(riid, &IID_IUnknown))
4770 *out = &wrapper->IMFByteStream_iface;
4772 else if (wrapper->cache_control && IsEqualIID(riid, &IID_IMFByteStreamCacheControl))
4774 *out = &wrapper->IMFByteStreamCacheControl_iface;
4776 else if (wrapper->stream_buffering && IsEqualIID(riid, &IID_IMFByteStreamBuffering))
4778 *out = &wrapper->IMFByteStreamBuffering_iface;
4780 else if (wrapper->event_generator && IsEqualIID(riid, &IID_IMFMediaEventGenerator))
4782 *out = &wrapper->IMFMediaEventGenerator_iface;
4784 else if (wrapper->time_seek && IsEqualIID(riid, &IID_IMFByteStreamTimeSeek))
4786 *out = &wrapper->IMFByteStreamTimeSeek_iface;
4788 else if (wrapper->sample_output && IsEqualIID(riid, &IID_IMFSampleOutputStream))
4790 *out = &wrapper->IMFSampleOutputStream_iface;
4792 else if (wrapper->propstore && IsEqualIID(riid, &IID_IPropertyStore))
4794 *out = &wrapper->IPropertyStore_iface;
4796 else if (wrapper->attributes && IsEqualIID(riid, &IID_IMFAttributes))
4798 *out = &wrapper->IMFAttributes_iface;
4800 else
4802 WARN("Unsupported %s.\n", debugstr_guid(riid));
4803 *out = NULL;
4804 return E_NOINTERFACE;
4807 IUnknown_AddRef((IUnknown *)*out);
4808 return S_OK;
4811 static ULONG WINAPI bytestream_wrapper_AddRef(IMFByteStream *iface)
4813 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4814 ULONG refcount = InterlockedIncrement(&wrapper->refcount);
4816 TRACE("%p, refcount %ld.\n", iface, refcount);
4818 return refcount;
4821 static ULONG WINAPI bytestream_wrapper_Release(IMFByteStream *iface)
4823 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4824 ULONG refcount = InterlockedDecrement(&wrapper->refcount);
4826 TRACE("%p, refcount %ld.\n", iface, refcount);
4828 if (!refcount)
4830 if (wrapper->cache_control)
4831 IMFByteStreamCacheControl_Release(wrapper->cache_control);
4832 if (wrapper->stream_buffering)
4833 IMFByteStreamBuffering_Release(wrapper->stream_buffering);
4834 if (wrapper->event_generator)
4835 IMFMediaEventGenerator_Release(wrapper->event_generator);
4836 if (wrapper->time_seek)
4837 IMFByteStreamTimeSeek_Release(wrapper->time_seek);
4838 if (wrapper->sample_output)
4839 IMFSampleOutputStream_Release(wrapper->sample_output);
4840 if (wrapper->propstore)
4841 IPropertyStore_Release(wrapper->propstore);
4842 if (wrapper->attributes)
4843 IMFAttributes_Release(wrapper->attributes);
4844 IMFByteStream_Release(wrapper->stream);
4845 free(wrapper);
4848 return refcount;
4851 static HRESULT WINAPI bytestream_wrapper_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
4853 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4855 TRACE("%p, %p.\n", iface, capabilities);
4857 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4858 IMFByteStream_GetCapabilities(wrapper->stream, capabilities);
4861 static HRESULT WINAPI bytestream_wrapper_GetLength(IMFByteStream *iface, QWORD *length)
4863 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4865 TRACE("%p, %p.\n", iface, length);
4867 if (wrapper->is_closed)
4868 return MF_E_INVALIDREQUEST;
4870 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4871 IMFByteStream_GetLength(wrapper->stream, length);
4874 static HRESULT WINAPI bytestream_wrapper_SetLength(IMFByteStream *iface, QWORD length)
4876 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4878 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(length));
4880 if (wrapper->is_closed)
4881 return MF_E_INVALIDREQUEST;
4883 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4884 IMFByteStream_SetLength(wrapper->stream, length);
4887 static HRESULT WINAPI bytestream_wrapper_GetCurrentPosition(IMFByteStream *iface, QWORD *position)
4889 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4891 TRACE("%p, %p.\n", iface, position);
4893 if (wrapper->is_closed)
4894 return MF_E_INVALIDREQUEST;
4896 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4897 IMFByteStream_GetCurrentPosition(wrapper->stream, position);
4900 static HRESULT WINAPI bytestream_wrapper_SetCurrentPosition(IMFByteStream *iface, QWORD position)
4902 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4904 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
4906 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4907 IMFByteStream_SetCurrentPosition(wrapper->stream, position);
4910 static HRESULT WINAPI bytestream_wrapper_IsEndOfStream(IMFByteStream *iface, BOOL *eos)
4912 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4914 TRACE("%p, %p.\n", iface, eos);
4916 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4917 IMFByteStream_IsEndOfStream(wrapper->stream, eos);
4920 static HRESULT WINAPI bytestream_wrapper_Read(IMFByteStream *iface, BYTE *data, ULONG count, ULONG *byte_read)
4922 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4924 TRACE("%p, %p, %lu, %p.\n", iface, data, count, byte_read);
4926 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4927 IMFByteStream_Read(wrapper->stream, data, count, byte_read);
4930 static HRESULT WINAPI bytestream_wrapper_BeginRead(IMFByteStream *iface, BYTE *data, ULONG size,
4931 IMFAsyncCallback *callback, IUnknown *state)
4933 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4935 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4937 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4938 IMFByteStream_BeginRead(wrapper->stream, data, size, callback, state);
4941 static HRESULT WINAPI bytestream_wrapper_EndRead(IMFByteStream *iface, IMFAsyncResult *result, ULONG *byte_read)
4943 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4945 TRACE("%p, %p, %p.\n", iface, result, byte_read);
4947 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4948 IMFByteStream_EndRead(wrapper->stream, result, byte_read);
4951 static HRESULT WINAPI bytestream_wrapper_Write(IMFByteStream *iface, const BYTE *data, ULONG count, ULONG *written)
4953 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4955 TRACE("%p, %p, %lu, %p.\n", iface, data, count, written);
4957 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4958 IMFByteStream_Write(wrapper->stream, data, count, written);
4961 static HRESULT WINAPI bytestream_wrapper_BeginWrite(IMFByteStream *iface, const BYTE *data, ULONG size,
4962 IMFAsyncCallback *callback, IUnknown *state)
4964 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4966 TRACE("%p, %p, %lu, %p, %p.\n", iface, data, size, callback, state);
4968 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4969 IMFByteStream_BeginWrite(wrapper->stream, data, size, callback, state);
4972 static HRESULT WINAPI bytestream_wrapper_EndWrite(IMFByteStream *iface, IMFAsyncResult *result, ULONG *written)
4974 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4976 TRACE("%p, %p, %p.\n", iface, result, written);
4978 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4979 IMFByteStream_EndWrite(wrapper->stream, result, written);
4982 static HRESULT WINAPI bytestream_wrapper_Seek(IMFByteStream *iface, MFBYTESTREAM_SEEK_ORIGIN seek, LONGLONG offset,
4983 DWORD flags, QWORD *current)
4985 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4987 TRACE("%p, %u, %s, %#lx, %p.\n", iface, seek, wine_dbgstr_longlong(offset), flags, current);
4989 return wrapper->is_closed ? MF_E_INVALIDREQUEST :
4990 IMFByteStream_Seek(wrapper->stream, seek, offset, flags, current);
4993 static HRESULT WINAPI bytestream_wrapper_Flush(IMFByteStream *iface)
4995 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
4997 TRACE("%p\n", iface);
4999 return wrapper->is_closed ? MF_E_INVALIDREQUEST : IMFByteStream_Flush(wrapper->stream);
5002 static HRESULT WINAPI bytestream_wrapper_Close(IMFByteStream *iface)
5004 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStream(iface);
5006 TRACE("%p\n", iface);
5008 wrapper->is_closed = TRUE;
5010 return S_OK;
5013 static const IMFByteStreamVtbl bytestream_wrapper_vtbl =
5015 bytestream_wrapper_QueryInterface,
5016 bytestream_wrapper_AddRef,
5017 bytestream_wrapper_Release,
5018 bytestream_wrapper_GetCapabilities,
5019 bytestream_wrapper_GetLength,
5020 bytestream_wrapper_SetLength,
5021 bytestream_wrapper_GetCurrentPosition,
5022 bytestream_wrapper_SetCurrentPosition,
5023 bytestream_wrapper_IsEndOfStream,
5024 bytestream_wrapper_Read,
5025 bytestream_wrapper_BeginRead,
5026 bytestream_wrapper_EndRead,
5027 bytestream_wrapper_Write,
5028 bytestream_wrapper_BeginWrite,
5029 bytestream_wrapper_EndWrite,
5030 bytestream_wrapper_Seek,
5031 bytestream_wrapper_Flush,
5032 bytestream_wrapper_Close,
5035 static HRESULT WINAPI bytestream_wrapper_cache_control_QueryInterface(IMFByteStreamCacheControl *iface,
5036 REFIID riid, void **obj)
5038 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5039 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5042 static ULONG WINAPI bytestream_wrapper_cache_control_AddRef(IMFByteStreamCacheControl *iface)
5044 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5045 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5048 static ULONG WINAPI bytestream_wrapper_cache_control_Release(IMFByteStreamCacheControl *iface)
5050 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5051 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5054 static HRESULT WINAPI bytestream_wrapper_cache_control_StopBackgroundTransfer(IMFByteStreamCacheControl *iface)
5056 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamCacheControl(iface);
5058 TRACE("%p.\n", iface);
5060 return IMFByteStreamCacheControl_StopBackgroundTransfer(wrapper->cache_control);
5063 static const IMFByteStreamCacheControlVtbl bytestream_wrapper_cache_control_vtbl =
5065 bytestream_wrapper_cache_control_QueryInterface,
5066 bytestream_wrapper_cache_control_AddRef,
5067 bytestream_wrapper_cache_control_Release,
5068 bytestream_wrapper_cache_control_StopBackgroundTransfer,
5071 static HRESULT WINAPI bytestream_wrapper_buffering_QueryInterface(IMFByteStreamBuffering *iface,
5072 REFIID riid, void **obj)
5074 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5075 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5078 static ULONG WINAPI bytestream_wrapper_buffering_AddRef(IMFByteStreamBuffering *iface)
5080 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5081 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5084 static ULONG WINAPI bytestream_wrapper_buffering_Release(IMFByteStreamBuffering *iface)
5086 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5087 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5090 static HRESULT WINAPI bytestream_wrapper_buffering_SetBufferingParams(IMFByteStreamBuffering *iface,
5091 MFBYTESTREAM_BUFFERING_PARAMS *params)
5093 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5095 TRACE("%p, %p.\n", iface, params);
5097 return IMFByteStreamBuffering_SetBufferingParams(wrapper->stream_buffering, params);
5100 static HRESULT WINAPI bytestream_wrapper_buffering_EnableBuffering(IMFByteStreamBuffering *iface,
5101 BOOL enable)
5103 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5105 TRACE("%p, %d.\n", iface, enable);
5107 return IMFByteStreamBuffering_EnableBuffering(wrapper->stream_buffering, enable);
5110 static HRESULT WINAPI bytestream_wrapper_buffering_StopBuffering(IMFByteStreamBuffering *iface)
5112 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamBuffering(iface);
5114 TRACE("%p.\n", iface);
5116 return IMFByteStreamBuffering_StopBuffering(wrapper->stream_buffering);
5119 static const IMFByteStreamBufferingVtbl bytestream_wrapper_buffering_vtbl =
5121 bytestream_wrapper_buffering_QueryInterface,
5122 bytestream_wrapper_buffering_AddRef,
5123 bytestream_wrapper_buffering_Release,
5124 bytestream_wrapper_buffering_SetBufferingParams,
5125 bytestream_wrapper_buffering_EnableBuffering,
5126 bytestream_wrapper_buffering_StopBuffering,
5129 static HRESULT WINAPI bytestream_wrapper_timeseek_QueryInterface(IMFByteStreamTimeSeek *iface,
5130 REFIID riid, void **obj)
5132 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5133 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5136 static ULONG WINAPI bytestream_wrapper_timeseek_AddRef(IMFByteStreamTimeSeek *iface)
5138 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5139 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5142 static ULONG WINAPI bytestream_wrapper_timeseek_Release(IMFByteStreamTimeSeek *iface)
5144 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5145 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5148 static HRESULT WINAPI bytestream_wrapper_timeseek_IsTimeSeekSupported(IMFByteStreamTimeSeek *iface, BOOL *result)
5150 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5152 TRACE("%p, %p.\n", iface, result);
5154 return IMFByteStreamTimeSeek_IsTimeSeekSupported(wrapper->time_seek, result);
5157 static HRESULT WINAPI bytestream_wrapper_timeseek_TimeSeek(IMFByteStreamTimeSeek *iface, QWORD position)
5159 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5161 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(position));
5163 return IMFByteStreamTimeSeek_TimeSeek(wrapper->time_seek, position);
5166 static HRESULT WINAPI bytestream_wrapper_timeseek_GetTimeSeekResult(IMFByteStreamTimeSeek *iface, QWORD *start_time,
5167 QWORD *stop_time, QWORD *duration)
5169 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFByteStreamTimeSeek(iface);
5171 TRACE("%p, %p, %p, %p.\n", iface, start_time, stop_time, duration);
5173 return IMFByteStreamTimeSeek_GetTimeSeekResult(wrapper->time_seek, start_time, stop_time, duration);
5176 static const IMFByteStreamTimeSeekVtbl bytestream_wrapper_timeseek_vtbl =
5178 bytestream_wrapper_timeseek_QueryInterface,
5179 bytestream_wrapper_timeseek_AddRef,
5180 bytestream_wrapper_timeseek_Release,
5181 bytestream_wrapper_timeseek_IsTimeSeekSupported,
5182 bytestream_wrapper_timeseek_TimeSeek,
5183 bytestream_wrapper_timeseek_GetTimeSeekResult,
5186 static HRESULT WINAPI bytestream_wrapper_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
5188 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5189 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5192 static ULONG WINAPI bytestream_wrapper_events_AddRef(IMFMediaEventGenerator *iface)
5194 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5195 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5198 static ULONG WINAPI bytestream_wrapper_events_Release(IMFMediaEventGenerator *iface)
5200 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5201 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5204 static HRESULT WINAPI bytestream_wrapper_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
5206 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5208 TRACE("%p, %#lx, %p.\n", iface, flags, event);
5210 return IMFMediaEventGenerator_GetEvent(wrapper->event_generator, flags, event);
5213 static HRESULT WINAPI bytestream_wrapper_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback, IUnknown *state)
5215 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5217 TRACE("%p, %p, %p.\n", iface, callback, state);
5219 return IMFMediaEventGenerator_BeginGetEvent(wrapper->event_generator, callback, state);
5222 static HRESULT WINAPI bytestream_wrapper_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result, IMFMediaEvent **event)
5224 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5226 TRACE("%p, %p, %p.\n", iface, result, event);
5228 return IMFMediaEventGenerator_EndGetEvent(wrapper->event_generator, result, event);
5231 static HRESULT WINAPI bytestream_wrapper_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType type,
5232 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
5234 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFMediaEventGenerator(iface);
5236 TRACE("%p, %ld, %s, %#lx, %s.\n", iface, type, debugstr_guid(ext_type), hr, debugstr_propvar(value));
5238 return IMFMediaEventGenerator_QueueEvent(wrapper->event_generator, type, ext_type, hr, value);
5241 static const IMFMediaEventGeneratorVtbl bytestream_wrapper_events_vtbl =
5243 bytestream_wrapper_events_QueryInterface,
5244 bytestream_wrapper_events_AddRef,
5245 bytestream_wrapper_events_Release,
5246 bytestream_wrapper_events_GetEvent,
5247 bytestream_wrapper_events_BeginGetEvent,
5248 bytestream_wrapper_events_EndGetEvent,
5249 bytestream_wrapper_events_QueueEvent,
5252 static HRESULT WINAPI bytestream_wrapper_sample_output_QueryInterface(IMFSampleOutputStream *iface, REFIID riid, void **obj)
5254 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5255 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5258 static ULONG WINAPI bytestream_wrapper_sample_output_AddRef(IMFSampleOutputStream *iface)
5260 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5261 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5264 static ULONG WINAPI bytestream_wrapper_sample_output_Release(IMFSampleOutputStream *iface)
5266 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5267 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5270 static HRESULT WINAPI bytestream_wrapper_sample_output_BeginWriteSample(IMFSampleOutputStream *iface, IMFSample *sample,
5271 IMFAsyncCallback *callback, IUnknown *state)
5273 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5275 TRACE("%p, %p, %p, %p.\n", iface, sample, callback, state);
5277 return IMFSampleOutputStream_BeginWriteSample(wrapper->sample_output, sample, callback, state);
5280 static HRESULT WINAPI bytestream_wrapper_sample_output_EndWriteSample(IMFSampleOutputStream *iface, IMFAsyncResult *result)
5282 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5284 TRACE("%p, %p.\n", iface, result);
5286 return IMFSampleOutputStream_EndWriteSample(wrapper->sample_output, result);
5289 static HRESULT WINAPI bytestream_wrapper_sample_output_Close(IMFSampleOutputStream *iface)
5291 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFSampleOutputStream(iface);
5293 TRACE("%p.\n", iface);
5295 return IMFSampleOutputStream_Close(wrapper->sample_output);
5298 static const IMFSampleOutputStreamVtbl bytestream_wrapper_sample_output_vtbl =
5300 bytestream_wrapper_sample_output_QueryInterface,
5301 bytestream_wrapper_sample_output_AddRef,
5302 bytestream_wrapper_sample_output_Release,
5303 bytestream_wrapper_sample_output_BeginWriteSample,
5304 bytestream_wrapper_sample_output_EndWriteSample,
5305 bytestream_wrapper_sample_output_Close,
5308 static HRESULT WINAPI bytestream_wrapper_propstore_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
5310 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5311 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5314 static ULONG WINAPI bytestream_wrapper_propstore_AddRef(IPropertyStore *iface)
5316 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5317 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5320 static ULONG WINAPI bytestream_wrapper_propstore_Release(IPropertyStore *iface)
5322 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5323 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5326 static HRESULT WINAPI bytestream_wrapper_propstore_GetCount(IPropertyStore *iface, DWORD *count)
5328 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5330 TRACE("%p, %p.\n", iface, count);
5332 return IPropertyStore_GetCount(wrapper->propstore, count);
5335 static HRESULT WINAPI bytestream_wrapper_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
5337 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5339 TRACE("%p, %lu, %p.\n", iface, prop, key);
5341 return IPropertyStore_GetAt(wrapper->propstore, prop, key);
5344 static HRESULT WINAPI bytestream_wrapper_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
5346 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5348 TRACE("%p, %p, %p.\n", iface, key, value);
5350 return IPropertyStore_GetValue(wrapper->propstore, key, value);
5353 static HRESULT WINAPI bytestream_wrapper_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key,
5354 const PROPVARIANT *value)
5356 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5358 TRACE("%p, %p, %s.\n", iface, key, debugstr_propvar(value));
5360 return IPropertyStore_SetValue(wrapper->propstore, key, value);
5363 static HRESULT WINAPI bytestream_wrapper_propstore_Commit(IPropertyStore *iface)
5365 struct bytestream_wrapper *wrapper = impl_wrapper_from_IPropertyStore(iface);
5367 TRACE("%p.\n", iface);
5369 return IPropertyStore_Commit(wrapper->propstore);
5372 static const IPropertyStoreVtbl bytestream_wrapper_propstore_vtbl =
5374 bytestream_wrapper_propstore_QueryInterface,
5375 bytestream_wrapper_propstore_AddRef,
5376 bytestream_wrapper_propstore_Release,
5377 bytestream_wrapper_propstore_GetCount,
5378 bytestream_wrapper_propstore_GetAt,
5379 bytestream_wrapper_propstore_GetValue,
5380 bytestream_wrapper_propstore_SetValue,
5381 bytestream_wrapper_propstore_Commit,
5384 static HRESULT WINAPI bytestream_wrapper_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
5386 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5387 return IMFByteStream_QueryInterface(&wrapper->IMFByteStream_iface, riid, obj);
5390 static ULONG WINAPI bytestream_wrapper_attributes_AddRef(IMFAttributes *iface)
5392 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5393 return IMFByteStream_AddRef(&wrapper->IMFByteStream_iface);
5396 static ULONG WINAPI bytestream_wrapper_attributes_Release(IMFAttributes *iface)
5398 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5399 return IMFByteStream_Release(&wrapper->IMFByteStream_iface);
5402 static HRESULT WINAPI bytestream_wrapper_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
5404 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5406 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5408 return IMFAttributes_GetItem(wrapper->attributes, key, value);
5411 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
5413 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5415 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
5417 return IMFAttributes_GetItemType(wrapper->attributes, key, type);
5420 static HRESULT WINAPI bytestream_wrapper_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
5421 REFPROPVARIANT value, BOOL *result)
5423 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5425 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
5427 return IMFAttributes_CompareItem(wrapper->attributes, key, value, result);
5430 static HRESULT WINAPI bytestream_wrapper_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
5431 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
5433 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5435 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
5437 return IMFAttributes_Compare(wrapper->attributes, theirs, match_type, ret);
5440 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
5442 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5444 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5446 return IMFAttributes_GetUINT32(wrapper->attributes, key, value);
5449 static HRESULT WINAPI bytestream_wrapper_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
5451 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5453 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5455 return IMFAttributes_GetUINT64(wrapper->attributes, key, value);
5458 static HRESULT WINAPI bytestream_wrapper_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
5460 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5462 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5464 return IMFAttributes_GetDouble(wrapper->attributes, key, value);
5467 static HRESULT WINAPI bytestream_wrapper_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
5469 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5471 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
5473 return IMFAttributes_GetGUID(wrapper->attributes, key, value);
5476 static HRESULT WINAPI bytestream_wrapper_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
5478 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5480 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
5482 return IMFAttributes_GetStringLength(wrapper->attributes, key, length);
5485 static HRESULT WINAPI bytestream_wrapper_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
5486 UINT32 size, UINT32 *length)
5488 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5490 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
5492 return IMFAttributes_GetString(wrapper->attributes, key, value, size, length);
5495 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key, WCHAR **value, UINT32 *length)
5497 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5499 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
5501 return IMFAttributes_GetAllocatedString(wrapper->attributes, key, value, length);
5504 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
5506 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5508 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
5510 return IMFAttributes_GetBlobSize(wrapper->attributes, key, size);
5513 static HRESULT WINAPI bytestream_wrapper_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
5514 UINT32 bufsize, UINT32 *blobsize)
5516 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5518 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
5520 return IMFAttributes_GetBlob(wrapper->attributes, key, buf, bufsize, blobsize);
5523 static HRESULT WINAPI bytestream_wrapper_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
5525 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5527 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
5529 return IMFAttributes_GetAllocatedBlob(wrapper->attributes, key, buf, size);
5532 static HRESULT WINAPI bytestream_wrapper_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **obj)
5534 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5536 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
5538 return IMFAttributes_GetUnknown(wrapper->attributes, key, riid, obj);
5541 static HRESULT WINAPI bytestream_wrapper_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
5543 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5545 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
5547 return IMFAttributes_SetItem(wrapper->attributes, key, value);
5550 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
5552 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5554 TRACE("%p, %s.\n", iface, debugstr_attr(key));
5556 return IMFAttributes_DeleteItem(wrapper->attributes, key);
5559 static HRESULT WINAPI bytestream_wrapper_attributes_DeleteAllItems(IMFAttributes *iface)
5561 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5563 TRACE("%p.\n", iface);
5565 return IMFAttributes_DeleteAllItems(wrapper->attributes);
5568 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
5570 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5572 TRACE("%p, %s, %d.\n", iface, debugstr_attr(key), value);
5574 return IMFAttributes_SetUINT32(wrapper->attributes, key, value);
5577 static HRESULT WINAPI bytestream_wrapper_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
5579 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5581 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
5583 return IMFAttributes_SetUINT64(wrapper->attributes, key, value);
5586 static HRESULT WINAPI bytestream_wrapper_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
5588 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5590 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
5592 return IMFAttributes_SetDouble(wrapper->attributes, key, value);
5595 static HRESULT WINAPI bytestream_wrapper_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
5597 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5599 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
5601 return IMFAttributes_SetGUID(wrapper->attributes, key, value);
5604 static HRESULT WINAPI bytestream_wrapper_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
5606 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5608 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
5610 return IMFAttributes_SetString(wrapper->attributes, key, value);
5613 static HRESULT WINAPI bytestream_wrapper_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
5615 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5617 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
5619 return IMFAttributes_SetBlob(wrapper->attributes, key, buf, size);
5622 static HRESULT WINAPI bytestream_wrapper_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
5624 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5626 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
5628 return IMFAttributes_SetUnknown(wrapper->attributes, key, unknown);
5631 static HRESULT WINAPI bytestream_wrapper_attributes_LockStore(IMFAttributes *iface)
5633 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5635 TRACE("%p.\n", iface);
5637 return IMFAttributes_LockStore(wrapper->attributes);
5640 static HRESULT WINAPI bytestream_wrapper_attributes_UnlockStore(IMFAttributes *iface)
5642 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5644 TRACE("%p.\n", iface);
5646 return IMFAttributes_UnlockStore(wrapper->attributes);
5649 static HRESULT WINAPI bytestream_wrapper_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
5651 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5653 TRACE("%p, %p.\n", iface, count);
5655 return IMFAttributes_GetCount(wrapper->attributes, count);
5658 static HRESULT WINAPI bytestream_wrapper_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index, GUID *key, PROPVARIANT *value)
5660 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5662 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
5664 return IMFAttributes_GetItemByIndex(wrapper->attributes, index, key, value);
5667 static HRESULT WINAPI bytestream_wrapper_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
5669 struct bytestream_wrapper *wrapper = impl_wrapper_from_IMFAttributes(iface);
5671 TRACE("%p, %p.\n", iface, dest);
5673 return IMFAttributes_CopyAllItems(wrapper->attributes, dest);
5676 static const IMFAttributesVtbl bytestream_wrapper_attributes_vtbl =
5678 bytestream_wrapper_attributes_QueryInterface,
5679 bytestream_wrapper_attributes_AddRef,
5680 bytestream_wrapper_attributes_Release,
5681 bytestream_wrapper_attributes_GetItem,
5682 bytestream_wrapper_attributes_GetItemType,
5683 bytestream_wrapper_attributes_CompareItem,
5684 bytestream_wrapper_attributes_Compare,
5685 bytestream_wrapper_attributes_GetUINT32,
5686 bytestream_wrapper_attributes_GetUINT64,
5687 bytestream_wrapper_attributes_GetDouble,
5688 bytestream_wrapper_attributes_GetGUID,
5689 bytestream_wrapper_attributes_GetStringLength,
5690 bytestream_wrapper_attributes_GetString,
5691 bytestream_wrapper_attributes_GetAllocatedString,
5692 bytestream_wrapper_attributes_GetBlobSize,
5693 bytestream_wrapper_attributes_GetBlob,
5694 bytestream_wrapper_attributes_GetAllocatedBlob,
5695 bytestream_wrapper_attributes_GetUnknown,
5696 bytestream_wrapper_attributes_SetItem,
5697 bytestream_wrapper_attributes_DeleteItem,
5698 bytestream_wrapper_attributes_DeleteAllItems,
5699 bytestream_wrapper_attributes_SetUINT32,
5700 bytestream_wrapper_attributes_SetUINT64,
5701 bytestream_wrapper_attributes_SetDouble,
5702 bytestream_wrapper_attributes_SetGUID,
5703 bytestream_wrapper_attributes_SetString,
5704 bytestream_wrapper_attributes_SetBlob,
5705 bytestream_wrapper_attributes_SetUnknown,
5706 bytestream_wrapper_attributes_LockStore,
5707 bytestream_wrapper_attributes_UnlockStore,
5708 bytestream_wrapper_attributes_GetCount,
5709 bytestream_wrapper_attributes_GetItemByIndex,
5710 bytestream_wrapper_attributes_CopyAllItems
5713 /***********************************************************************
5714 * MFCreateMFByteStreamWrapper (mfplat.@)
5716 HRESULT WINAPI MFCreateMFByteStreamWrapper(IMFByteStream *stream, IMFByteStream **wrapper)
5718 struct bytestream_wrapper *object;
5720 TRACE("%p, %p.\n", stream, wrapper);
5722 if (!(object = calloc(1, sizeof(*object))))
5723 return E_OUTOFMEMORY;
5725 object->IMFByteStreamCacheControl_iface.lpVtbl = &bytestream_wrapper_cache_control_vtbl;
5726 object->IMFByteStreamBuffering_iface.lpVtbl = &bytestream_wrapper_buffering_vtbl;
5727 object->IMFMediaEventGenerator_iface.lpVtbl = &bytestream_wrapper_events_vtbl;
5728 object->IMFByteStreamTimeSeek_iface.lpVtbl = &bytestream_wrapper_timeseek_vtbl;
5729 object->IMFSampleOutputStream_iface.lpVtbl = &bytestream_wrapper_sample_output_vtbl;
5730 object->IMFByteStream_iface.lpVtbl = &bytestream_wrapper_vtbl;
5731 object->IPropertyStore_iface.lpVtbl = &bytestream_wrapper_propstore_vtbl;
5732 object->IMFAttributes_iface.lpVtbl = &bytestream_wrapper_attributes_vtbl;
5734 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamCacheControl, (void **)&object->cache_control);
5735 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamBuffering, (void **)&object->stream_buffering);
5736 IMFByteStream_QueryInterface(stream, &IID_IMFMediaEventGenerator, (void **)&object->event_generator);
5737 IMFByteStream_QueryInterface(stream, &IID_IMFByteStreamTimeSeek, (void **)&object->time_seek);
5738 IMFByteStream_QueryInterface(stream, &IID_IMFSampleOutputStream, (void **)&object->sample_output);
5739 IMFByteStream_QueryInterface(stream, &IID_IPropertyStore, (void **)&object->propstore);
5740 IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&object->attributes);
5742 object->stream = stream;
5743 IMFByteStream_AddRef(object->stream);
5745 object->refcount = 1;
5747 *wrapper = &object->IMFByteStream_iface;
5749 return S_OK;
5752 static HRESULT WINAPI MFPluginControl_QueryInterface(IMFPluginControl *iface, REFIID riid, void **ppv)
5754 if(IsEqualGUID(riid, &IID_IUnknown)) {
5755 TRACE("(IID_IUnknown %p)\n", ppv);
5756 *ppv = iface;
5757 }else if(IsEqualGUID(riid, &IID_IMFPluginControl)) {
5758 TRACE("(IID_IMFPluginControl %p)\n", ppv);
5759 *ppv = iface;
5760 }else {
5761 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
5762 *ppv = NULL;
5763 return E_NOINTERFACE;
5766 IUnknown_AddRef((IUnknown*)*ppv);
5767 return S_OK;
5770 static ULONG WINAPI MFPluginControl_AddRef(IMFPluginControl *iface)
5772 TRACE("\n");
5773 return 2;
5776 static ULONG WINAPI MFPluginControl_Release(IMFPluginControl *iface)
5778 TRACE("\n");
5779 return 1;
5782 static HRESULT WINAPI MFPluginControl_GetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5783 const WCHAR *selector, CLSID *clsid)
5785 FIXME("(%ld %s %p)\n", plugin_type, debugstr_w(selector), clsid);
5786 return E_NOTIMPL;
5789 static HRESULT WINAPI MFPluginControl_GetPreferredClsidByIndex(IMFPluginControl *iface, DWORD plugin_type,
5790 DWORD index, WCHAR **selector, CLSID *clsid)
5792 FIXME("(%ld %ld %p %p)\n", plugin_type, index, selector, clsid);
5793 return E_NOTIMPL;
5796 static HRESULT WINAPI MFPluginControl_SetPreferredClsid(IMFPluginControl *iface, DWORD plugin_type,
5797 const WCHAR *selector, const CLSID *clsid)
5799 FIXME("(%ld %s %s)\n", plugin_type, debugstr_w(selector), debugstr_guid(clsid));
5800 return E_NOTIMPL;
5803 static HRESULT WINAPI MFPluginControl_IsDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid)
5805 FIXME("(%ld %s)\n", plugin_type, debugstr_guid(clsid));
5806 return E_NOTIMPL;
5809 static HRESULT WINAPI MFPluginControl_GetDisabledByIndex(IMFPluginControl *iface, DWORD plugin_type, DWORD index, CLSID *clsid)
5811 FIXME("(%ld %ld %p)\n", plugin_type, index, clsid);
5812 return E_NOTIMPL;
5815 static HRESULT WINAPI MFPluginControl_SetDisabled(IMFPluginControl *iface, DWORD plugin_type, REFCLSID clsid, BOOL disabled)
5817 FIXME("(%ld %s %x)\n", plugin_type, debugstr_guid(clsid), disabled);
5818 return E_NOTIMPL;
5821 static const IMFPluginControlVtbl MFPluginControlVtbl = {
5822 MFPluginControl_QueryInterface,
5823 MFPluginControl_AddRef,
5824 MFPluginControl_Release,
5825 MFPluginControl_GetPreferredClsid,
5826 MFPluginControl_GetPreferredClsidByIndex,
5827 MFPluginControl_SetPreferredClsid,
5828 MFPluginControl_IsDisabled,
5829 MFPluginControl_GetDisabledByIndex,
5830 MFPluginControl_SetDisabled
5833 static IMFPluginControl plugin_control = { &MFPluginControlVtbl };
5835 /***********************************************************************
5836 * MFGetPluginControl (mfplat.@)
5838 HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
5840 TRACE("(%p)\n", ret);
5842 *ret = &plugin_control;
5843 return S_OK;
5846 enum resolved_object_origin
5848 OBJECT_FROM_BYTESTREAM,
5849 OBJECT_FROM_URL,
5852 struct resolver_queued_result
5854 struct list entry;
5855 IUnknown *object;
5856 MF_OBJECT_TYPE obj_type;
5857 HRESULT hr;
5858 IRtwqAsyncResult *inner_result;
5859 enum resolved_object_origin origin;
5862 struct resolver_cancel_object
5864 IUnknown IUnknown_iface;
5865 LONG refcount;
5866 union
5868 IUnknown *handler;
5869 IMFByteStreamHandler *stream_handler;
5870 IMFSchemeHandler *scheme_handler;
5871 } u;
5872 IUnknown *cancel_cookie;
5873 enum resolved_object_origin origin;
5876 struct source_resolver
5878 IMFSourceResolver IMFSourceResolver_iface;
5879 LONG refcount;
5880 IRtwqAsyncCallback stream_callback;
5881 IRtwqAsyncCallback url_callback;
5882 CRITICAL_SECTION cs;
5883 struct list pending;
5886 static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface)
5888 return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface);
5891 static struct source_resolver *impl_from_stream_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5893 return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
5896 static struct source_resolver *impl_from_url_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
5898 return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
5901 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
5902 IRtwqAsyncResult *result)
5904 IRtwqAsyncResult *inner_result = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
5905 RTWQASYNCRESULT *data = (RTWQASYNCRESULT *)inner_result;
5906 struct resolver_queued_result *queued_result;
5907 union
5909 IUnknown *handler;
5910 IMFByteStreamHandler *stream_handler;
5911 IMFSchemeHandler *scheme_handler;
5912 } handler;
5914 if (!(queued_result = calloc(1, sizeof(*queued_result))))
5915 return E_OUTOFMEMORY;
5917 queued_result->origin = origin;
5919 IRtwqAsyncResult_GetObject(inner_result, &handler.handler);
5921 switch (origin)
5923 case OBJECT_FROM_BYTESTREAM:
5924 queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, (IMFAsyncResult *)result,
5925 &queued_result->obj_type, &queued_result->object);
5926 break;
5927 case OBJECT_FROM_URL:
5928 queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, (IMFAsyncResult *)result,
5929 &queued_result->obj_type, &queued_result->object);
5930 break;
5931 default:
5932 queued_result->hr = E_FAIL;
5935 IUnknown_Release(handler.handler);
5937 if (data->hEvent)
5939 queued_result->inner_result = inner_result;
5940 IRtwqAsyncResult_AddRef(queued_result->inner_result);
5943 /* Push resolved object type and created object, so we don't have to guess on End*() call. */
5944 EnterCriticalSection(&resolver->cs);
5945 list_add_tail(&resolver->pending, &queued_result->entry);
5946 LeaveCriticalSection(&resolver->cs);
5948 if (data->hEvent)
5949 SetEvent(data->hEvent);
5950 else
5952 IUnknown *caller_state = IRtwqAsyncResult_GetStateNoAddRef(inner_result);
5953 IRtwqAsyncResult *caller_result;
5955 if (SUCCEEDED(RtwqCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
5957 RtwqInvokeCallback(caller_result);
5958 IRtwqAsyncResult_Release(caller_result);
5962 return S_OK;
5965 static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
5967 return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
5970 static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
5972 if (IsEqualIID(riid, &IID_IUnknown))
5974 *obj = iface;
5975 IUnknown_AddRef(iface);
5976 return S_OK;
5979 *obj = NULL;
5980 return E_NOINTERFACE;
5983 static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface)
5985 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5986 return InterlockedIncrement(&object->refcount);
5989 static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
5991 struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
5992 ULONG refcount = InterlockedDecrement(&object->refcount);
5994 if (!refcount)
5996 if (object->cancel_cookie)
5997 IUnknown_Release(object->cancel_cookie);
5998 IUnknown_Release(object->u.handler);
5999 free(object);
6002 return refcount;
6005 static const IUnknownVtbl resolver_cancel_object_vtbl =
6007 resolver_cancel_object_QueryInterface,
6008 resolver_cancel_object_AddRef,
6009 resolver_cancel_object_Release,
6012 static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
6014 if (!iface)
6015 return NULL;
6017 return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
6018 CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
6021 static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
6022 IUnknown *cancel_cookie, IUnknown **cancel_object)
6024 struct resolver_cancel_object *object;
6026 if (!(object = calloc(1, sizeof(*object))))
6027 return E_OUTOFMEMORY;
6029 object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
6030 object->refcount = 1;
6031 object->u.handler = handler;
6032 IUnknown_AddRef(object->u.handler);
6033 object->cancel_cookie = cancel_cookie;
6034 IUnknown_AddRef(object->cancel_cookie);
6035 object->origin = origin;
6037 *cancel_object = &object->IUnknown_iface;
6039 return S_OK;
6042 static HRESULT WINAPI source_resolver_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
6044 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
6045 IsEqualIID(riid, &IID_IUnknown))
6047 *obj = iface;
6048 IRtwqAsyncCallback_AddRef(iface);
6049 return S_OK;
6052 *obj = NULL;
6053 return E_NOINTERFACE;
6056 static ULONG WINAPI source_resolver_callback_stream_AddRef(IRtwqAsyncCallback *iface)
6058 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6059 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
6062 static ULONG WINAPI source_resolver_callback_stream_Release(IRtwqAsyncCallback *iface)
6064 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6065 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
6068 static HRESULT WINAPI source_resolver_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
6070 return E_NOTIMPL;
6073 static HRESULT WINAPI source_resolver_callback_stream_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
6075 struct source_resolver *resolver = impl_from_stream_IRtwqAsyncCallback(iface);
6077 return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result);
6080 static const IRtwqAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
6082 source_resolver_callback_QueryInterface,
6083 source_resolver_callback_stream_AddRef,
6084 source_resolver_callback_stream_Release,
6085 source_resolver_callback_GetParameters,
6086 source_resolver_callback_stream_Invoke,
6089 static ULONG WINAPI source_resolver_callback_url_AddRef(IRtwqAsyncCallback *iface)
6091 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6092 return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
6095 static ULONG WINAPI source_resolver_callback_url_Release(IRtwqAsyncCallback *iface)
6097 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6098 return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
6101 static HRESULT WINAPI source_resolver_callback_url_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
6103 struct source_resolver *resolver = impl_from_url_IRtwqAsyncCallback(iface);
6105 return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
6108 static const IRtwqAsyncCallbackVtbl source_resolver_callback_url_vtbl =
6110 source_resolver_callback_QueryInterface,
6111 source_resolver_callback_url_AddRef,
6112 source_resolver_callback_url_Release,
6113 source_resolver_callback_GetParameters,
6114 source_resolver_callback_url_Invoke,
6117 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
6119 DWORD name_length, type;
6120 HRESULT hr = E_FAIL;
6121 unsigned int j = 0;
6122 WCHAR clsidW[39];
6123 CLSID clsid;
6125 name_length = ARRAY_SIZE(clsidW);
6126 while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL))
6128 if (type == REG_SZ)
6130 if (SUCCEEDED(CLSIDFromString(clsidW, &clsid)))
6132 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler);
6133 if (SUCCEEDED(hr))
6134 break;
6138 name_length = ARRAY_SIZE(clsidW);
6141 return hr;
6144 static HRESULT resolver_create_bytestream_handler(IMFByteStream *stream, DWORD flags, const WCHAR *mime,
6145 const WCHAR *extension, IMFByteStreamHandler **handler)
6147 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6148 HRESULT hr = E_FAIL;
6149 unsigned int i, j;
6151 *handler = NULL;
6153 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6155 struct local_handler *local_handler;
6157 EnterCriticalSection(&local_handlers_section);
6159 LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
6161 if ((mime && !lstrcmpiW(mime, local_handler->u.bytestream.mime))
6162 || (extension && !lstrcmpiW(extension, local_handler->u.bytestream.extension)))
6164 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
6165 (void **)handler)))
6166 break;
6170 LeaveCriticalSection(&local_handlers_section);
6172 if (*handler)
6173 return hr;
6176 for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
6178 const WCHAR *namesW[2] = { mime, extension };
6179 HKEY hkey, hkey_handler;
6181 if (RegOpenKeyW(hkey_roots[i], L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", &hkey))
6182 continue;
6184 for (j = 0; j < ARRAY_SIZE(namesW); ++j)
6186 if (!namesW[j])
6187 continue;
6189 if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler))
6191 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler);
6192 RegCloseKey(hkey_handler);
6195 if (SUCCEEDED(hr))
6196 break;
6199 RegCloseKey(hkey);
6201 if (SUCCEEDED(hr))
6202 break;
6205 return hr;
6208 static HRESULT resolver_get_bytestream_url_hint(IMFByteStream *stream, WCHAR const **url)
6210 static const unsigned char asfmagic[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c};
6211 static const unsigned char wavmagic[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '};
6212 static const unsigned char wavmask[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
6213 static const unsigned char isommagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm',0x00,0x00,0x00,0x00};
6214 static const unsigned char mp4_magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', 'S', 'N', 'V',0x00,0x00,0x00,0x00};
6215 static const unsigned char mp42magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'm', 'p', '4', '2',0x00,0x00,0x00,0x00};
6216 static const unsigned char mp4vmagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', '4', 'V', ' ',0x00,0x00,0x00,0x00};
6217 static const unsigned char mp4mask[] = {0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00};
6218 static const struct stream_content_url_hint
6220 const unsigned char *magic;
6221 const WCHAR *url;
6222 const unsigned char *mask;
6224 url_hints[] =
6226 { asfmagic, L".asf" },
6227 { wavmagic, L".wav", wavmask },
6228 { isommagic, L".mp4", mp4mask },
6229 { mp42magic, L".mp4", mp4mask },
6230 { mp4_magic, L".mp4", mp4mask },
6231 { mp4vmagic, L".m4v", mp4mask },
6233 unsigned char buffer[4 * sizeof(unsigned int)], pattern[4 * sizeof(unsigned int)];
6234 IMFAttributes *attributes;
6235 DWORD length = 0, caps = 0;
6236 unsigned int i, j;
6237 QWORD position;
6238 HRESULT hr;
6240 *url = NULL;
6242 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6244 UINT32 string_length = 0;
6245 IMFAttributes_GetStringLength(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &string_length);
6246 IMFAttributes_Release(attributes);
6248 if (string_length)
6249 return S_OK;
6252 if (FAILED(hr = IMFByteStream_GetCapabilities(stream, &caps)))
6253 return hr;
6255 if (!(caps & MFBYTESTREAM_IS_SEEKABLE))
6256 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6258 if (FAILED(hr = IMFByteStream_GetCurrentPosition(stream, &position)))
6259 return hr;
6261 hr = IMFByteStream_Read(stream, buffer, sizeof(buffer), &length);
6262 IMFByteStream_SetCurrentPosition(stream, position);
6263 if (FAILED(hr))
6264 return hr;
6266 if (length < sizeof(buffer))
6267 return S_OK;
6269 for (i = 0; i < ARRAY_SIZE(url_hints); ++i)
6271 memcpy(pattern, buffer, sizeof(buffer));
6272 if (url_hints[i].mask)
6274 unsigned int *mask = (unsigned int *)url_hints[i].mask;
6275 unsigned int *data = (unsigned int *)pattern;
6277 for (j = 0; j < sizeof(buffer) / sizeof(unsigned int); ++j)
6278 data[j] &= mask[j];
6281 if (!memcmp(pattern, url_hints[i].magic, sizeof(pattern)))
6283 *url = url_hints[i].url;
6284 break;
6288 if (*url)
6289 TRACE("Content type guessed as %s from %s.\n", debugstr_w(*url), debugstr_an((char *)buffer, length));
6290 else
6291 WARN("Unrecognized content type %s.\n", debugstr_an((char *)buffer, length));
6293 return S_OK;
6296 static HRESULT resolver_create_gstreamer_handler(IMFByteStreamHandler **handler)
6298 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6299 return CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6302 static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
6303 IMFByteStreamHandler **handler)
6305 WCHAR *mimeW = NULL, *urlW = NULL;
6306 IMFAttributes *attributes;
6307 const WCHAR *url_ext;
6308 HRESULT hr = E_FAIL;
6309 UINT32 length;
6311 *handler = NULL;
6313 /* MIME type */
6314 if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6316 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
6317 if (!url)
6319 IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_ORIGIN_NAME, &urlW, &length);
6320 url = urlW;
6322 IMFAttributes_Release(attributes);
6325 /* Extension */
6326 url_ext = url ? wcsrchr(url, '.') : NULL;
6328 /* If content type was provided by the caller, it's tried first. Otherwise an attempt to deduce
6329 content type from the content itself is made.
6331 TODO: wine specific fallback to predefined handler could be replaced by normally registering
6332 this handler for all possible types.
6335 if (url_ext || mimeW)
6337 hr = resolver_create_bytestream_handler(stream, flags, mimeW, url_ext, handler);
6339 if (FAILED(hr))
6340 hr = resolver_create_gstreamer_handler(handler);
6343 CoTaskMemFree(mimeW);
6344 CoTaskMemFree(urlW);
6346 if (SUCCEEDED(hr))
6347 return hr;
6349 if (!(flags & MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE))
6350 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6352 if (FAILED(hr = resolver_get_bytestream_url_hint(stream, &url_ext)))
6353 return hr;
6355 hr = resolver_create_bytestream_handler(stream, flags, NULL, url_ext, handler);
6357 if (FAILED(hr))
6358 hr = resolver_create_gstreamer_handler(handler);
6360 return hr;
6363 static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
6365 static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6366 HRESULT hr = MF_E_UNSUPPORTED_SCHEME;
6367 unsigned int i;
6369 TRACE("%s, %#lx, %p.\n", debugstr_w(scheme), flags, handler);
6371 *handler = NULL;
6373 if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
6375 struct local_handler *local_handler;
6377 EnterCriticalSection(&local_handlers_section);
6379 LIST_FOR_EACH_ENTRY(local_handler, &local_scheme_handlers, struct local_handler, entry)
6381 if (!lstrcmpiW(scheme, local_handler->u.scheme))
6383 if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFSchemeHandler,
6384 (void **)handler)))
6385 break;
6389 LeaveCriticalSection(&local_handlers_section);
6391 if (*handler)
6392 return hr;
6395 for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
6397 HKEY hkey, hkey_handler;
6399 hr = MF_E_UNSUPPORTED_SCHEME;
6401 if (RegOpenKeyW(hkey_roots[i], L"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", &hkey))
6402 continue;
6404 if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
6406 hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
6407 RegCloseKey(hkey_handler);
6410 RegCloseKey(hkey);
6412 if (SUCCEEDED(hr))
6413 break;
6416 return hr;
6419 static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
6421 static const WCHAR fileschemeW[] = L"file:";
6422 const WCHAR *ptr = url;
6423 unsigned int len;
6424 WCHAR *scheme;
6425 HRESULT hr;
6427 /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
6428 while (*ptr)
6430 WCHAR ch = towlower(*ptr);
6432 if (*ptr == '*' && ptr == url)
6434 ptr++;
6435 break;
6437 else if (!(*ptr >= '0' && *ptr <= '9') &&
6438 !(ch >= 'a' && ch <= 'z') &&
6439 *ptr != '+' && *ptr != '-' && *ptr != '.')
6441 break;
6444 ptr++;
6447 /* Schemes must end with a ':', if not found try "file:" */
6448 if (ptr == url || *ptr != ':')
6450 url = fileschemeW;
6451 len = ARRAY_SIZE(fileschemeW) - 1;
6453 else
6454 len = ptr - url + 1;
6456 scheme = malloc((len + 1) * sizeof(WCHAR));
6457 if (!scheme)
6458 return E_OUTOFMEMORY;
6460 memcpy(scheme, url, len * sizeof(WCHAR));
6461 scheme[len] = 0;
6463 hr = resolver_create_scheme_handler(scheme, flags, handler);
6464 if (FAILED(hr) && url != fileschemeW)
6465 hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
6467 free(scheme);
6469 return hr;
6472 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
6473 IRtwqAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
6475 struct resolver_queued_result *queued_result = NULL, *iter;
6476 IUnknown *object;
6477 HRESULT hr;
6479 if (FAILED(hr = IRtwqAsyncResult_GetObject(result, &object)))
6480 return hr;
6482 EnterCriticalSection(&resolver->cs);
6484 LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry)
6486 if (iter->inner_result == result || (iter->object == object && iter->origin == origin))
6488 list_remove(&iter->entry);
6489 queued_result = iter;
6490 break;
6494 LeaveCriticalSection(&resolver->cs);
6496 IUnknown_Release(object);
6498 if (queued_result)
6500 *out = queued_result->object;
6501 *obj_type = queued_result->obj_type;
6502 hr = queued_result->hr;
6503 if (queued_result->inner_result)
6504 IRtwqAsyncResult_Release(queued_result->inner_result);
6505 free(queued_result);
6507 else
6508 hr = E_UNEXPECTED;
6510 return hr;
6513 static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
6515 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6517 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
6519 if (IsEqualIID(riid, &IID_IMFSourceResolver) ||
6520 IsEqualIID(riid, &IID_IUnknown))
6522 *obj = &resolver->IMFSourceResolver_iface;
6524 else
6526 *obj = NULL;
6527 FIXME("unsupported interface %s\n", debugstr_guid(riid));
6528 return E_NOINTERFACE;
6531 IUnknown_AddRef((IUnknown *)*obj);
6532 return S_OK;
6535 static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface)
6537 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6538 ULONG refcount = InterlockedIncrement(&resolver->refcount);
6540 TRACE("%p, refcount %ld.\n", iface, refcount);
6542 return refcount;
6545 static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
6547 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6548 ULONG refcount = InterlockedDecrement(&resolver->refcount);
6549 struct resolver_queued_result *result, *result2;
6551 TRACE("%p, refcount %ld.\n", iface, refcount);
6553 if (!refcount)
6555 LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry)
6557 if (result->object)
6558 IUnknown_Release(result->object);
6559 list_remove(&result->entry);
6560 free(result);
6562 DeleteCriticalSection(&resolver->cs);
6563 free(resolver);
6566 return refcount;
6569 static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6570 DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6572 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6573 IMFSchemeHandler *handler;
6574 IRtwqAsyncResult *result;
6575 RTWQASYNCRESULT *data;
6576 HRESULT hr;
6578 TRACE("%p, %s, %#lx, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
6580 if (!url || !obj_type || !object)
6581 return E_POINTER;
6583 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6584 return hr;
6586 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6587 IMFSchemeHandler_Release(handler);
6588 if (FAILED(hr))
6589 return hr;
6591 data = (RTWQASYNCRESULT *)result;
6592 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6594 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, (IMFAsyncCallback *)&resolver->url_callback,
6595 (IUnknown *)result);
6596 if (FAILED(hr))
6598 IRtwqAsyncResult_Release(result);
6599 return hr;
6602 WaitForSingleObject(data->hEvent, INFINITE);
6604 hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
6605 IRtwqAsyncResult_Release(result);
6607 return hr;
6610 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6611 const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
6613 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6614 IMFByteStreamHandler *handler;
6615 IRtwqAsyncResult *result;
6616 RTWQASYNCRESULT *data;
6617 HRESULT hr;
6619 TRACE("%p, %p, %s, %#lx, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
6621 if (!stream || !obj_type || !object)
6622 return E_POINTER;
6624 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6625 return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6627 hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
6628 IMFByteStreamHandler_Release(handler);
6629 if (FAILED(hr))
6630 return hr;
6632 data = (RTWQASYNCRESULT *)result;
6633 data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
6635 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL,
6636 (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6637 if (FAILED(hr))
6639 IRtwqAsyncResult_Release(result);
6640 return hr;
6643 WaitForSingleObject(data->hEvent, INFINITE);
6645 hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
6646 IRtwqAsyncResult_Release(result);
6648 return hr;
6651 static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
6652 DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
6654 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6655 IMFSchemeHandler *handler;
6656 IUnknown *inner_cookie = NULL;
6657 IRtwqAsyncResult *result;
6658 HRESULT hr;
6660 TRACE("%p, %s, %#lx, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
6662 if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
6663 return hr;
6665 if (cancel_cookie)
6666 *cancel_cookie = NULL;
6668 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6669 IMFSchemeHandler_Release(handler);
6670 if (FAILED(hr))
6671 return hr;
6673 hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL,
6674 (IMFAsyncCallback *)&resolver->url_callback, (IUnknown *)result);
6676 if (SUCCEEDED(hr) && inner_cookie)
6677 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie);
6679 IRtwqAsyncResult_Release(result);
6681 return hr;
6684 static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result,
6685 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6687 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6689 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6691 return resolver_end_create_object(resolver, OBJECT_FROM_URL, (IRtwqAsyncResult *)result, obj_type, object);
6694 static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
6695 const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
6696 IUnknown *state)
6698 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6699 IMFByteStreamHandler *handler;
6700 IUnknown *inner_cookie = NULL;
6701 IRtwqAsyncResult *result;
6702 HRESULT hr;
6704 TRACE("%p, %p, %s, %#lx, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
6705 callback, state);
6707 if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
6708 return hr;
6710 if (cancel_cookie)
6711 *cancel_cookie = NULL;
6713 hr = RtwqCreateAsyncResult((IUnknown *)handler, (IRtwqAsyncCallback *)callback, state, &result);
6714 IMFByteStreamHandler_Release(handler);
6715 if (FAILED(hr))
6716 return hr;
6718 hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
6719 cancel_cookie ? &inner_cookie : NULL, (IMFAsyncCallback *)&resolver->stream_callback, (IUnknown *)result);
6721 /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
6722 if (SUCCEEDED(hr) && inner_cookie)
6723 resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
6725 IRtwqAsyncResult_Release(result);
6727 return hr;
6730 static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
6731 MF_OBJECT_TYPE *obj_type, IUnknown **object)
6733 struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
6735 TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
6737 return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, (IRtwqAsyncResult *)result, obj_type, object);
6740 static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
6742 struct resolver_cancel_object *object;
6743 HRESULT hr;
6745 TRACE("%p, %p.\n", iface, cancel_cookie);
6747 if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
6748 return E_UNEXPECTED;
6750 switch (object->origin)
6752 case OBJECT_FROM_BYTESTREAM:
6753 hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
6754 break;
6755 case OBJECT_FROM_URL:
6756 hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie);
6757 break;
6758 default:
6759 hr = E_UNEXPECTED;
6762 return hr;
6765 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
6767 source_resolver_QueryInterface,
6768 source_resolver_AddRef,
6769 source_resolver_Release,
6770 source_resolver_CreateObjectFromURL,
6771 source_resolver_CreateObjectFromByteStream,
6772 source_resolver_BeginCreateObjectFromURL,
6773 source_resolver_EndCreateObjectFromURL,
6774 source_resolver_BeginCreateObjectFromByteStream,
6775 source_resolver_EndCreateObjectFromByteStream,
6776 source_resolver_CancelObjectCreation,
6779 /***********************************************************************
6780 * MFCreateSourceResolver (mfplat.@)
6782 HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
6784 struct source_resolver *object;
6786 TRACE("%p\n", resolver);
6788 if (!resolver)
6789 return E_POINTER;
6791 if (!(object = calloc(1, sizeof(*object))))
6792 return E_OUTOFMEMORY;
6794 object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
6795 object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
6796 object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
6797 object->refcount = 1;
6798 list_init(&object->pending);
6799 InitializeCriticalSection(&object->cs);
6801 *resolver = &object->IMFSourceResolver_iface;
6803 return S_OK;
6806 struct media_event
6808 struct attributes attributes;
6809 IMFMediaEvent IMFMediaEvent_iface;
6811 MediaEventType type;
6812 GUID extended_type;
6813 HRESULT status;
6814 PROPVARIANT value;
6817 static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface)
6819 return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface);
6822 static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out)
6824 struct media_event *event = impl_from_IMFMediaEvent(iface);
6826 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
6828 if(IsEqualGUID(riid, &IID_IUnknown) ||
6829 IsEqualGUID(riid, &IID_IMFAttributes) ||
6830 IsEqualGUID(riid, &IID_IMFMediaEvent))
6832 *out = &event->IMFMediaEvent_iface;
6834 else
6836 FIXME("%s, %p.\n", debugstr_guid(riid), out);
6837 *out = NULL;
6838 return E_NOINTERFACE;
6841 IUnknown_AddRef((IUnknown*)*out);
6842 return S_OK;
6845 static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
6847 struct media_event *event = impl_from_IMFMediaEvent(iface);
6848 ULONG refcount = InterlockedIncrement(&event->attributes.ref);
6850 TRACE("%p, refcount %lu.\n", iface, refcount);
6852 return refcount;
6855 static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
6857 struct media_event *event = impl_from_IMFMediaEvent(iface);
6858 ULONG refcount = InterlockedDecrement(&event->attributes.ref);
6860 TRACE("%p, refcount %lu.\n", iface, refcount);
6862 if (!refcount)
6864 clear_attributes_object(&event->attributes);
6865 PropVariantClear(&event->value);
6866 free(event);
6869 return refcount;
6872 static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value)
6874 struct media_event *event = impl_from_IMFMediaEvent(iface);
6876 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6878 return attributes_GetItem(&event->attributes, key, value);
6881 static HRESULT WINAPI mfmediaevent_GetItemType(IMFMediaEvent *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
6883 struct media_event *event = impl_from_IMFMediaEvent(iface);
6885 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
6887 return attributes_GetItemType(&event->attributes, key, type);
6890 static HRESULT WINAPI mfmediaevent_CompareItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
6892 struct media_event *event = impl_from_IMFMediaEvent(iface);
6894 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
6896 return attributes_CompareItem(&event->attributes, key, value, result);
6899 static HRESULT WINAPI mfmediaevent_Compare(IMFMediaEvent *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
6900 BOOL *result)
6902 struct media_event *event = impl_from_IMFMediaEvent(iface);
6904 TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
6906 return attributes_Compare(&event->attributes, attrs, type, result);
6909 static HRESULT WINAPI mfmediaevent_GetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 *value)
6911 struct media_event *event = impl_from_IMFMediaEvent(iface);
6913 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6915 return attributes_GetUINT32(&event->attributes, key, value);
6918 static HRESULT WINAPI mfmediaevent_GetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 *value)
6920 struct media_event *event = impl_from_IMFMediaEvent(iface);
6922 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6924 return attributes_GetUINT64(&event->attributes, key, value);
6927 static HRESULT WINAPI mfmediaevent_GetDouble(IMFMediaEvent *iface, REFGUID key, double *value)
6929 struct media_event *event = impl_from_IMFMediaEvent(iface);
6931 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6933 return attributes_GetDouble(&event->attributes, key, value);
6936 static HRESULT WINAPI mfmediaevent_GetGUID(IMFMediaEvent *iface, REFGUID key, GUID *value)
6938 struct media_event *event = impl_from_IMFMediaEvent(iface);
6940 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
6942 return attributes_GetGUID(&event->attributes, key, value);
6945 static HRESULT WINAPI mfmediaevent_GetStringLength(IMFMediaEvent *iface, REFGUID key, UINT32 *length)
6947 struct media_event *event = impl_from_IMFMediaEvent(iface);
6949 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
6951 return attributes_GetStringLength(&event->attributes, key, length);
6954 static HRESULT WINAPI mfmediaevent_GetString(IMFMediaEvent *iface, REFGUID key, WCHAR *value,
6955 UINT32 size, UINT32 *length)
6957 struct media_event *event = impl_from_IMFMediaEvent(iface);
6959 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
6961 return attributes_GetString(&event->attributes, key, value, size, length);
6964 static HRESULT WINAPI mfmediaevent_GetAllocatedString(IMFMediaEvent *iface, REFGUID key,
6965 WCHAR **value, UINT32 *length)
6967 struct media_event *event = impl_from_IMFMediaEvent(iface);
6969 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
6971 return attributes_GetAllocatedString(&event->attributes, key, value, length);
6974 static HRESULT WINAPI mfmediaevent_GetBlobSize(IMFMediaEvent *iface, REFGUID key, UINT32 *size)
6976 struct media_event *event = impl_from_IMFMediaEvent(iface);
6978 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
6980 return attributes_GetBlobSize(&event->attributes, key, size);
6983 static HRESULT WINAPI mfmediaevent_GetBlob(IMFMediaEvent *iface, REFGUID key, UINT8 *buf,
6984 UINT32 bufsize, UINT32 *blobsize)
6986 struct media_event *event = impl_from_IMFMediaEvent(iface);
6988 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
6990 return attributes_GetBlob(&event->attributes, key, buf, bufsize, blobsize);
6993 static HRESULT WINAPI mfmediaevent_GetAllocatedBlob(IMFMediaEvent *iface, REFGUID key, UINT8 **buf, UINT32 *size)
6995 struct media_event *event = impl_from_IMFMediaEvent(iface);
6997 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
6999 return attributes_GetAllocatedBlob(&event->attributes, key, buf, size);
7002 static HRESULT WINAPI mfmediaevent_GetUnknown(IMFMediaEvent *iface, REFGUID key, REFIID riid, void **out)
7004 struct media_event *event = impl_from_IMFMediaEvent(iface);
7006 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
7008 return attributes_GetUnknown(&event->attributes, key, riid, out);
7011 static HRESULT WINAPI mfmediaevent_SetItem(IMFMediaEvent *iface, REFGUID key, REFPROPVARIANT value)
7013 struct media_event *event = impl_from_IMFMediaEvent(iface);
7015 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
7017 return attributes_SetItem(&event->attributes, key, value);
7020 static HRESULT WINAPI mfmediaevent_DeleteItem(IMFMediaEvent *iface, REFGUID key)
7022 struct media_event *event = impl_from_IMFMediaEvent(iface);
7024 TRACE("%p, %s.\n", iface, debugstr_attr(key));
7026 return attributes_DeleteItem(&event->attributes, key);
7029 static HRESULT WINAPI mfmediaevent_DeleteAllItems(IMFMediaEvent *iface)
7031 struct media_event *event = impl_from_IMFMediaEvent(iface);
7033 TRACE("%p.\n", iface);
7035 return attributes_DeleteAllItems(&event->attributes);
7038 static HRESULT WINAPI mfmediaevent_SetUINT32(IMFMediaEvent *iface, REFGUID key, UINT32 value)
7040 struct media_event *event = impl_from_IMFMediaEvent(iface);
7042 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
7044 return attributes_SetUINT32(&event->attributes, key, value);
7047 static HRESULT WINAPI mfmediaevent_SetUINT64(IMFMediaEvent *iface, REFGUID key, UINT64 value)
7049 struct media_event *event = impl_from_IMFMediaEvent(iface);
7051 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
7053 return attributes_SetUINT64(&event->attributes, key, value);
7056 static HRESULT WINAPI mfmediaevent_SetDouble(IMFMediaEvent *iface, REFGUID key, double value)
7058 struct media_event *event = impl_from_IMFMediaEvent(iface);
7060 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
7062 return attributes_SetDouble(&event->attributes, key, value);
7065 static HRESULT WINAPI mfmediaevent_SetGUID(IMFMediaEvent *iface, REFGUID key, REFGUID value)
7067 struct media_event *event = impl_from_IMFMediaEvent(iface);
7069 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
7071 return attributes_SetGUID(&event->attributes, key, value);
7074 static HRESULT WINAPI mfmediaevent_SetString(IMFMediaEvent *iface, REFGUID key, const WCHAR *value)
7076 struct media_event *event = impl_from_IMFMediaEvent(iface);
7078 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
7080 return attributes_SetString(&event->attributes, key, value);
7083 static HRESULT WINAPI mfmediaevent_SetBlob(IMFMediaEvent *iface, REFGUID key, const UINT8 *buf, UINT32 size)
7085 struct media_event *event = impl_from_IMFMediaEvent(iface);
7087 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
7089 return attributes_SetBlob(&event->attributes, key, buf, size);
7092 static HRESULT WINAPI mfmediaevent_SetUnknown(IMFMediaEvent *iface, REFGUID key, IUnknown *unknown)
7094 struct media_event *event = impl_from_IMFMediaEvent(iface);
7096 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
7098 return attributes_SetUnknown(&event->attributes, key, unknown);
7101 static HRESULT WINAPI mfmediaevent_LockStore(IMFMediaEvent *iface)
7103 struct media_event *event = impl_from_IMFMediaEvent(iface);
7105 TRACE("%p.\n", iface);
7107 return attributes_LockStore(&event->attributes);
7110 static HRESULT WINAPI mfmediaevent_UnlockStore(IMFMediaEvent *iface)
7112 struct media_event *event = impl_from_IMFMediaEvent(iface);
7114 TRACE("%p.\n", iface);
7116 return attributes_UnlockStore(&event->attributes);
7119 static HRESULT WINAPI mfmediaevent_GetCount(IMFMediaEvent *iface, UINT32 *count)
7121 struct media_event *event = impl_from_IMFMediaEvent(iface);
7123 TRACE("%p, %p.\n", iface, count);
7125 return attributes_GetCount(&event->attributes, count);
7128 static HRESULT WINAPI mfmediaevent_GetItemByIndex(IMFMediaEvent *iface, UINT32 index, GUID *key, PROPVARIANT *value)
7130 struct media_event *event = impl_from_IMFMediaEvent(iface);
7132 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
7134 return attributes_GetItemByIndex(&event->attributes, index, key, value);
7137 static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttributes *dest)
7139 struct media_event *event = impl_from_IMFMediaEvent(iface);
7141 TRACE("%p, %p.\n", iface, dest);
7143 return attributes_CopyAllItems(&event->attributes, dest);
7146 static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type)
7148 struct media_event *event = impl_from_IMFMediaEvent(iface);
7150 TRACE("%p, %p.\n", iface, type);
7152 *type = event->type;
7154 return S_OK;
7157 static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type)
7159 struct media_event *event = impl_from_IMFMediaEvent(iface);
7161 TRACE("%p, %p.\n", iface, extended_type);
7163 *extended_type = event->extended_type;
7165 return S_OK;
7168 static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status)
7170 struct media_event *event = impl_from_IMFMediaEvent(iface);
7172 TRACE("%p, %p.\n", iface, status);
7174 *status = event->status;
7176 return S_OK;
7179 static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value)
7181 struct media_event *event = impl_from_IMFMediaEvent(iface);
7183 TRACE("%p, %p.\n", iface, value);
7185 PropVariantCopy(value, &event->value);
7187 return S_OK;
7190 static const IMFMediaEventVtbl mfmediaevent_vtbl =
7192 mfmediaevent_QueryInterface,
7193 mfmediaevent_AddRef,
7194 mfmediaevent_Release,
7195 mfmediaevent_GetItem,
7196 mfmediaevent_GetItemType,
7197 mfmediaevent_CompareItem,
7198 mfmediaevent_Compare,
7199 mfmediaevent_GetUINT32,
7200 mfmediaevent_GetUINT64,
7201 mfmediaevent_GetDouble,
7202 mfmediaevent_GetGUID,
7203 mfmediaevent_GetStringLength,
7204 mfmediaevent_GetString,
7205 mfmediaevent_GetAllocatedString,
7206 mfmediaevent_GetBlobSize,
7207 mfmediaevent_GetBlob,
7208 mfmediaevent_GetAllocatedBlob,
7209 mfmediaevent_GetUnknown,
7210 mfmediaevent_SetItem,
7211 mfmediaevent_DeleteItem,
7212 mfmediaevent_DeleteAllItems,
7213 mfmediaevent_SetUINT32,
7214 mfmediaevent_SetUINT64,
7215 mfmediaevent_SetDouble,
7216 mfmediaevent_SetGUID,
7217 mfmediaevent_SetString,
7218 mfmediaevent_SetBlob,
7219 mfmediaevent_SetUnknown,
7220 mfmediaevent_LockStore,
7221 mfmediaevent_UnlockStore,
7222 mfmediaevent_GetCount,
7223 mfmediaevent_GetItemByIndex,
7224 mfmediaevent_CopyAllItems,
7225 mfmediaevent_GetType,
7226 mfmediaevent_GetExtendedType,
7227 mfmediaevent_GetStatus,
7228 mfmediaevent_GetValue,
7231 /***********************************************************************
7232 * MFCreateMediaEvent (mfplat.@)
7234 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value,
7235 IMFMediaEvent **event)
7237 struct media_event *object;
7238 HRESULT hr;
7240 TRACE("%s, %s, %#lx, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status,
7241 debugstr_propvar(value), event);
7243 object = malloc(sizeof(*object));
7244 if (!object)
7245 return E_OUTOFMEMORY;
7247 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
7249 free(object);
7250 return hr;
7252 object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
7254 object->type = type;
7255 object->extended_type = *extended_type;
7256 object->status = status;
7258 PropVariantInit(&object->value);
7259 if (value)
7260 PropVariantCopy(&object->value, value);
7262 *event = &object->IMFMediaEvent_iface;
7264 TRACE("Created event %p.\n", *event);
7266 return S_OK;
7269 struct event_queue
7271 IMFMediaEventQueue IMFMediaEventQueue_iface;
7272 LONG refcount;
7274 CRITICAL_SECTION cs;
7275 CONDITION_VARIABLE update_event;
7276 struct list events;
7277 BOOL is_shut_down;
7278 BOOL notified;
7279 IRtwqAsyncResult *subscriber;
7282 struct queued_event
7284 struct list entry;
7285 IMFMediaEvent *event;
7288 static inline struct event_queue *impl_from_IMFMediaEventQueue(IMFMediaEventQueue *iface)
7290 return CONTAINING_RECORD(iface, struct event_queue, IMFMediaEventQueue_iface);
7293 static IMFMediaEvent *queue_pop_event(struct event_queue *queue)
7295 struct list *head = list_head(&queue->events);
7296 struct queued_event *queued_event;
7297 IMFMediaEvent *event;
7299 if (!head)
7300 return NULL;
7302 queued_event = LIST_ENTRY(head, struct queued_event, entry);
7303 event = queued_event->event;
7304 list_remove(&queued_event->entry);
7305 free(queued_event);
7306 return event;
7309 static void event_queue_clear_subscriber(struct event_queue *queue)
7311 if (queue->subscriber)
7312 IRtwqAsyncResult_Release(queue->subscriber);
7313 queue->subscriber = NULL;
7316 static void event_queue_cleanup(struct event_queue *queue)
7318 IMFMediaEvent *event;
7320 while ((event = queue_pop_event(queue)))
7321 IMFMediaEvent_Release(event);
7322 event_queue_clear_subscriber(queue);
7325 static HRESULT WINAPI eventqueue_QueryInterface(IMFMediaEventQueue *iface, REFIID riid, void **out)
7327 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7329 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7331 if (IsEqualIID(riid, &IID_IMFMediaEventQueue) ||
7332 IsEqualIID(riid, &IID_IUnknown))
7334 *out = &queue->IMFMediaEventQueue_iface;
7335 IMFMediaEventQueue_AddRef(iface);
7336 return S_OK;
7339 WARN("Unsupported %s.\n", debugstr_guid(riid));
7340 *out = NULL;
7341 return E_NOINTERFACE;
7344 static ULONG WINAPI eventqueue_AddRef(IMFMediaEventQueue *iface)
7346 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7347 ULONG refcount = InterlockedIncrement(&queue->refcount);
7349 TRACE("%p, refcount %lu.\n", iface, refcount);
7351 return refcount;
7354 static ULONG WINAPI eventqueue_Release(IMFMediaEventQueue *iface)
7356 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7357 ULONG refcount = InterlockedDecrement(&queue->refcount);
7359 TRACE("%p, refcount %lu.\n", queue, refcount);
7361 if (!refcount)
7363 event_queue_cleanup(queue);
7364 DeleteCriticalSection(&queue->cs);
7365 free(queue);
7368 return refcount;
7371 static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags, IMFMediaEvent **event)
7373 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7374 HRESULT hr = S_OK;
7376 TRACE("%p, %p.\n", iface, event);
7378 EnterCriticalSection(&queue->cs);
7380 if (queue->is_shut_down)
7381 hr = MF_E_SHUTDOWN;
7382 else if (queue->subscriber)
7383 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7384 else
7386 if (flags & MF_EVENT_FLAG_NO_WAIT)
7388 if (!(*event = queue_pop_event(queue)))
7389 hr = MF_E_NO_EVENTS_AVAILABLE;
7391 else
7393 while (list_empty(&queue->events) && !queue->is_shut_down)
7395 SleepConditionVariableCS(&queue->update_event, &queue->cs, INFINITE);
7397 *event = queue_pop_event(queue);
7398 if (queue->is_shut_down)
7399 hr = MF_E_SHUTDOWN;
7403 LeaveCriticalSection(&queue->cs);
7405 return hr;
7408 static void queue_notify_subscriber(struct event_queue *queue)
7410 if (list_empty(&queue->events) || !queue->subscriber || queue->notified)
7411 return;
7413 queue->notified = TRUE;
7414 RtwqPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, 0, queue->subscriber);
7417 static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state)
7419 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7420 RTWQASYNCRESULT *result_data;
7421 HRESULT hr;
7423 TRACE("%p, %p, %p.\n", iface, callback, state);
7425 if (!callback)
7426 return E_INVALIDARG;
7428 EnterCriticalSection(&queue->cs);
7430 if (queue->is_shut_down)
7431 hr = MF_E_SHUTDOWN;
7432 else if ((result_data = (RTWQASYNCRESULT *)queue->subscriber))
7434 if (result_data->pCallback == (IRtwqAsyncCallback *)callback)
7435 hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
7436 MF_S_MULTIPLE_BEGIN : MF_E_MULTIPLE_BEGIN;
7437 else
7438 hr = MF_E_MULTIPLE_SUBSCRIBERS;
7440 else
7442 hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &queue->subscriber);
7443 if (SUCCEEDED(hr))
7444 queue_notify_subscriber(queue);
7447 LeaveCriticalSection(&queue->cs);
7449 return hr;
7452 static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsyncResult *result, IMFMediaEvent **event)
7454 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7455 HRESULT hr = E_FAIL;
7457 TRACE("%p, %p, %p.\n", iface, result, event);
7459 EnterCriticalSection(&queue->cs);
7461 if (queue->is_shut_down)
7462 hr = MF_E_SHUTDOWN;
7463 else if (queue->subscriber == (IRtwqAsyncResult *)result)
7465 *event = queue_pop_event(queue);
7466 event_queue_clear_subscriber(queue);
7467 queue->notified = FALSE;
7468 hr = *event ? S_OK : E_FAIL;
7471 LeaveCriticalSection(&queue->cs);
7473 return hr;
7476 static HRESULT eventqueue_queue_event(struct event_queue *queue, IMFMediaEvent *event)
7478 struct queued_event *queued_event;
7479 HRESULT hr = S_OK;
7481 queued_event = malloc(sizeof(*queued_event));
7482 if (!queued_event)
7483 return E_OUTOFMEMORY;
7485 queued_event->event = event;
7487 EnterCriticalSection(&queue->cs);
7489 if (queue->is_shut_down)
7490 hr = MF_E_SHUTDOWN;
7491 else
7493 IMFMediaEvent_AddRef(queued_event->event);
7494 list_add_tail(&queue->events, &queued_event->entry);
7495 queue_notify_subscriber(queue);
7498 LeaveCriticalSection(&queue->cs);
7500 if (FAILED(hr))
7501 free(queued_event);
7503 WakeAllConditionVariable(&queue->update_event);
7505 return hr;
7508 static HRESULT WINAPI eventqueue_QueueEvent(IMFMediaEventQueue *iface, IMFMediaEvent *event)
7510 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7512 TRACE("%p, %p.\n", iface, event);
7514 return eventqueue_queue_event(queue, event);
7517 static HRESULT WINAPI eventqueue_QueueEventParamVar(IMFMediaEventQueue *iface, MediaEventType event_type,
7518 REFGUID extended_type, HRESULT status, const PROPVARIANT *value)
7520 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7521 IMFMediaEvent *event;
7522 HRESULT hr;
7524 TRACE("%p, %s, %s, %#lx, %s\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status,
7525 debugstr_propvar(value));
7527 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, value, &event)))
7528 return hr;
7530 hr = eventqueue_queue_event(queue, event);
7531 IMFMediaEvent_Release(event);
7532 return hr;
7535 static HRESULT WINAPI eventqueue_QueueEventParamUnk(IMFMediaEventQueue *iface, MediaEventType event_type,
7536 REFGUID extended_type, HRESULT status, IUnknown *unk)
7538 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7539 IMFMediaEvent *event;
7540 PROPVARIANT value;
7541 HRESULT hr;
7543 TRACE("%p, %s, %s, %#lx, %p.\n", iface, debugstr_eventid(event_type), debugstr_guid(extended_type), status, unk);
7545 value.vt = VT_UNKNOWN;
7546 value.punkVal = unk;
7548 if (FAILED(hr = MFCreateMediaEvent(event_type, extended_type, status, &value, &event)))
7549 return hr;
7551 hr = eventqueue_queue_event(queue, event);
7552 IMFMediaEvent_Release(event);
7553 return hr;
7556 static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface)
7558 struct event_queue *queue = impl_from_IMFMediaEventQueue(iface);
7560 TRACE("%p\n", queue);
7562 EnterCriticalSection(&queue->cs);
7564 if (!queue->is_shut_down)
7566 event_queue_cleanup(queue);
7567 queue->is_shut_down = TRUE;
7570 LeaveCriticalSection(&queue->cs);
7572 WakeAllConditionVariable(&queue->update_event);
7574 return S_OK;
7577 static const IMFMediaEventQueueVtbl eventqueuevtbl =
7579 eventqueue_QueryInterface,
7580 eventqueue_AddRef,
7581 eventqueue_Release,
7582 eventqueue_GetEvent,
7583 eventqueue_BeginGetEvent,
7584 eventqueue_EndGetEvent,
7585 eventqueue_QueueEvent,
7586 eventqueue_QueueEventParamVar,
7587 eventqueue_QueueEventParamUnk,
7588 eventqueue_Shutdown
7591 /***********************************************************************
7592 * MFCreateEventQueue (mfplat.@)
7594 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue)
7596 struct event_queue *object;
7598 TRACE("%p\n", queue);
7600 if (!(object = calloc(1, sizeof(*object))))
7601 return E_OUTOFMEMORY;
7603 object->IMFMediaEventQueue_iface.lpVtbl = &eventqueuevtbl;
7604 object->refcount = 1;
7605 list_init(&object->events);
7606 InitializeCriticalSection(&object->cs);
7607 InitializeConditionVariable(&object->update_event);
7609 *queue = &object->IMFMediaEventQueue_iface;
7611 return S_OK;
7614 struct collection
7616 IMFCollection IMFCollection_iface;
7617 LONG refcount;
7618 IUnknown **elements;
7619 size_t capacity;
7620 size_t count;
7623 static struct collection *impl_from_IMFCollection(IMFCollection *iface)
7625 return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
7628 static void collection_clear(struct collection *collection)
7630 size_t i;
7632 for (i = 0; i < collection->count; ++i)
7634 if (collection->elements[i])
7635 IUnknown_Release(collection->elements[i]);
7638 free(collection->elements);
7639 collection->elements = NULL;
7640 collection->count = 0;
7641 collection->capacity = 0;
7644 static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
7646 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
7648 if (IsEqualIID(riid, &IID_IMFCollection) ||
7649 IsEqualIID(riid, &IID_IUnknown))
7651 *out = iface;
7652 IMFCollection_AddRef(iface);
7653 return S_OK;
7656 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
7657 *out = NULL;
7658 return E_NOINTERFACE;
7661 static ULONG WINAPI collection_AddRef(IMFCollection *iface)
7663 struct collection *collection = impl_from_IMFCollection(iface);
7664 ULONG refcount = InterlockedIncrement(&collection->refcount);
7666 TRACE("%p, %ld.\n", collection, refcount);
7668 return refcount;
7671 static ULONG WINAPI collection_Release(IMFCollection *iface)
7673 struct collection *collection = impl_from_IMFCollection(iface);
7674 ULONG refcount = InterlockedDecrement(&collection->refcount);
7676 TRACE("%p, %ld.\n", collection, refcount);
7678 if (!refcount)
7680 collection_clear(collection);
7681 free(collection->elements);
7682 free(collection);
7685 return refcount;
7688 static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
7690 struct collection *collection = impl_from_IMFCollection(iface);
7692 TRACE("%p, %p.\n", iface, count);
7694 if (!count)
7695 return E_POINTER;
7697 *count = collection->count;
7699 return S_OK;
7702 static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7704 struct collection *collection = impl_from_IMFCollection(iface);
7706 TRACE("%p, %lu, %p.\n", iface, idx, element);
7708 if (!element)
7709 return E_POINTER;
7711 if (idx >= collection->count)
7712 return E_INVALIDARG;
7714 *element = collection->elements[idx];
7715 if (*element)
7716 IUnknown_AddRef(*element);
7718 return *element ? S_OK : E_UNEXPECTED;
7721 static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
7723 struct collection *collection = impl_from_IMFCollection(iface);
7725 TRACE("%p, %p.\n", iface, element);
7727 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
7728 sizeof(*collection->elements)))
7729 return E_OUTOFMEMORY;
7731 collection->elements[collection->count++] = element;
7732 if (element)
7733 IUnknown_AddRef(element);
7735 return S_OK;
7738 static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
7740 struct collection *collection = impl_from_IMFCollection(iface);
7741 size_t count;
7743 TRACE("%p, %lu, %p.\n", iface, idx, element);
7745 if (!element)
7746 return E_POINTER;
7748 if (idx >= collection->count)
7749 return E_INVALIDARG;
7751 *element = collection->elements[idx];
7753 count = collection->count - idx - 1;
7754 if (count)
7755 memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
7756 collection->count--;
7758 return S_OK;
7761 static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
7763 struct collection *collection = impl_from_IMFCollection(iface);
7764 size_t i;
7766 TRACE("%p, %lu, %p.\n", iface, idx, element);
7768 if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
7769 sizeof(*collection->elements)))
7770 return E_OUTOFMEMORY;
7772 if (idx < collection->count)
7774 memmove(&collection->elements[idx + 1], &collection->elements[idx],
7775 (collection->count - idx) * sizeof(*collection->elements));
7776 collection->count++;
7778 else
7780 for (i = collection->count; i < idx; ++i)
7781 collection->elements[i] = NULL;
7782 collection->count = idx + 1;
7785 collection->elements[idx] = element;
7786 if (collection->elements[idx])
7787 IUnknown_AddRef(collection->elements[idx]);
7789 return S_OK;
7792 static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
7794 struct collection *collection = impl_from_IMFCollection(iface);
7796 TRACE("%p.\n", iface);
7798 collection_clear(collection);
7800 return S_OK;
7803 static const IMFCollectionVtbl mfcollectionvtbl =
7805 collection_QueryInterface,
7806 collection_AddRef,
7807 collection_Release,
7808 collection_GetElementCount,
7809 collection_GetElement,
7810 collection_AddElement,
7811 collection_RemoveElement,
7812 collection_InsertElementAt,
7813 collection_RemoveAllElements,
7816 /***********************************************************************
7817 * MFCreateCollection (mfplat.@)
7819 HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
7821 struct collection *object;
7823 TRACE("%p\n", collection);
7825 if (!collection)
7826 return E_POINTER;
7828 if (!(object = calloc(1, sizeof(*object))))
7829 return E_OUTOFMEMORY;
7831 object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
7832 object->refcount = 1;
7834 *collection = &object->IMFCollection_iface;
7836 return S_OK;
7839 /***********************************************************************
7840 * MFHeapAlloc (mfplat.@)
7842 void *WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type)
7844 TRACE("%Iu, %#lx, %s, %d, %#x.\n", size, flags, debugstr_a(file), line, type);
7845 return HeapAlloc(GetProcessHeap(), flags, size);
7848 /***********************************************************************
7849 * MFHeapFree (mfplat.@)
7851 void WINAPI MFHeapFree(void *p)
7853 TRACE("%p\n", p);
7854 HeapFree(GetProcessHeap(), 0, p);
7857 /***********************************************************************
7858 * MFCreateMFByteStreamOnStreamEx (mfplat.@)
7860 HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream)
7862 FIXME("(%p, %p): stub\n", stream, bytestream);
7864 return E_NOTIMPL;
7867 static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
7869 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7871 if (IsEqualIID(riid, &IID_IMFClock) ||
7872 IsEqualIID(riid, &IID_IUnknown))
7874 *obj = iface;
7875 IMFClock_AddRef(iface);
7876 return S_OK;
7879 WARN("Unsupported %s.\n", debugstr_guid(riid));
7880 *obj = NULL;
7881 return E_NOINTERFACE;
7884 static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
7886 struct system_clock *clock = impl_from_IMFClock(iface);
7887 ULONG refcount = InterlockedIncrement(&clock->refcount);
7889 TRACE("%p, refcount %lu.\n", iface, refcount);
7891 return refcount;
7894 static ULONG WINAPI system_clock_Release(IMFClock *iface)
7896 struct system_clock *clock = impl_from_IMFClock(iface);
7897 ULONG refcount = InterlockedDecrement(&clock->refcount);
7899 TRACE("%p, refcount %lu.\n", iface, refcount);
7901 if (!refcount)
7902 free(clock);
7904 return refcount;
7907 static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
7909 TRACE("%p, %p.\n", iface, flags);
7911 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
7912 MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
7914 return S_OK;
7917 static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
7918 MFTIME *system_time)
7920 TRACE("%p, %#lx, %p, %p.\n", iface, reserved, clock_time, system_time);
7922 *clock_time = *system_time = MFGetSystemTime();
7924 return S_OK;
7927 static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
7929 TRACE("%p, %p.\n", iface, key);
7931 *key = 0;
7933 return S_OK;
7936 static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
7938 TRACE("%p, %#lx, %p.\n", iface, reserved, state);
7940 *state = MFCLOCK_STATE_RUNNING;
7942 return S_OK;
7945 static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
7947 TRACE("%p, %p.\n", iface, props);
7949 if (!props)
7950 return E_POINTER;
7952 memset(props, 0, sizeof(*props));
7953 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
7954 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
7955 props->dwClockJitter = 1;
7957 return S_OK;
7960 static const IMFClockVtbl system_clock_vtbl =
7962 system_clock_QueryInterface,
7963 system_clock_AddRef,
7964 system_clock_Release,
7965 system_clock_GetClockCharacteristics,
7966 system_clock_GetCorrelatedTime,
7967 system_clock_GetContinuityKey,
7968 system_clock_GetState,
7969 system_clock_GetProperties,
7972 static HRESULT create_system_clock(IMFClock **clock)
7974 struct system_clock *object;
7976 if (!(object = malloc(sizeof(*object))))
7977 return E_OUTOFMEMORY;
7979 object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
7980 object->refcount = 1;
7982 *clock = &object->IMFClock_iface;
7984 return S_OK;
7987 static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
7989 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
7991 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
7993 if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) ||
7994 IsEqualIID(riid, &IID_IUnknown))
7996 *obj = &source->IMFPresentationTimeSource_iface;
7998 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
8000 *obj = &source->IMFClockStateSink_iface;
8002 else
8004 WARN("Unsupported %s.\n", debugstr_guid(riid));
8005 *obj = NULL;
8006 return E_NOINTERFACE;
8009 IUnknown_AddRef((IUnknown *)*obj);
8010 return S_OK;
8013 static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface)
8015 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8016 ULONG refcount = InterlockedIncrement(&source->refcount);
8018 TRACE("%p, refcount %lu.\n", iface, refcount);
8020 return refcount;
8023 static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
8025 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8026 ULONG refcount = InterlockedDecrement(&source->refcount);
8028 TRACE("%p, refcount %lu.\n", iface, refcount);
8030 if (!refcount)
8032 if (source->clock)
8033 IMFClock_Release(source->clock);
8034 DeleteCriticalSection(&source->cs);
8035 free(source);
8038 return refcount;
8041 static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags)
8043 TRACE("%p, %p.\n", iface, flags);
8045 *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
8047 return S_OK;
8050 static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved,
8051 LONGLONG *clock_time, MFTIME *system_time)
8053 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8054 HRESULT hr;
8056 TRACE("%p, %#lx, %p, %p.\n", iface, reserved, clock_time, system_time);
8058 EnterCriticalSection(&source->cs);
8059 if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
8061 if (source->state == MFCLOCK_STATE_RUNNING)
8062 system_time_source_update_clock_time(source, *system_time);
8063 *clock_time = source->start_offset + source->clock_time;
8065 LeaveCriticalSection(&source->cs);
8067 return hr;
8070 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
8072 TRACE("%p, %p.\n", iface, key);
8074 *key = 0;
8076 return S_OK;
8079 static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved,
8080 MFCLOCK_STATE *state)
8082 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8084 TRACE("%p, %#lx, %p.\n", iface, reserved, state);
8086 EnterCriticalSection(&source->cs);
8087 *state = source->state;
8088 LeaveCriticalSection(&source->cs);
8090 return S_OK;
8093 static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props)
8095 TRACE("%p, %p.\n", iface, props);
8097 if (!props)
8098 return E_POINTER;
8100 memset(props, 0, sizeof(*props));
8101 props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
8102 props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
8103 props->dwClockJitter = 1;
8105 return S_OK;
8108 static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
8110 struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
8112 TRACE("%p, %p.\n", iface, clock);
8114 *clock = source->clock;
8115 IMFClock_AddRef(*clock);
8117 return S_OK;
8120 static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
8122 system_time_source_QueryInterface,
8123 system_time_source_AddRef,
8124 system_time_source_Release,
8125 system_time_source_GetClockCharacteristics,
8126 system_time_source_GetCorrelatedTime,
8127 system_time_source_GetContinuityKey,
8128 system_time_source_GetState,
8129 system_time_source_GetProperties,
8130 system_time_source_GetUnderlyingClock,
8133 static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out)
8135 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8136 return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out);
8139 static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface)
8141 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8142 return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface);
8145 static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface)
8147 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8148 return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface);
8151 enum clock_command
8153 CLOCK_CMD_START = 0,
8154 CLOCK_CMD_STOP,
8155 CLOCK_CMD_PAUSE,
8156 CLOCK_CMD_RESTART,
8157 CLOCK_CMD_MAX,
8160 static HRESULT system_time_source_change_state(struct system_time_source *source, enum clock_command command)
8162 static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
8163 { /* S S* P R */
8164 /* INVALID */ { 1, 0, 1, 0 },
8165 /* RUNNING */ { 1, 1, 1, 0 },
8166 /* STOPPED */ { 1, 1, 0, 0 },
8167 /* PAUSED */ { 1, 1, 0, 1 },
8169 static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
8171 /* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
8172 /* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
8173 /* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
8174 /* CLOCK_CMD_RESTART */ MFCLOCK_STATE_RUNNING,
8177 /* Special case that go against usual state change vs return value behavior. */
8178 if (source->state == MFCLOCK_STATE_INVALID && command == CLOCK_CMD_STOP)
8179 return S_OK;
8181 if (!state_change_is_allowed[source->state][command])
8182 return MF_E_INVALIDREQUEST;
8184 source->state = states[command];
8186 return S_OK;
8189 static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time,
8190 LONGLONG start_offset)
8192 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8193 MFCLOCK_STATE state;
8194 HRESULT hr;
8196 TRACE("%p, %s, %s.\n", iface, debugstr_time(system_time), debugstr_time(start_offset));
8198 EnterCriticalSection(&source->cs);
8199 state = source->state;
8200 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
8202 if (start_offset == PRESENTATION_CURRENT_POSITION)
8204 if (state != MFCLOCK_STATE_RUNNING)
8206 source->start_offset -= system_time;
8207 source->system_time = 0;
8210 else
8212 source->start_offset = start_offset;
8213 source->system_time = system_time;
8214 source->clock_time = 0;
8217 LeaveCriticalSection(&source->cs);
8219 return hr;
8222 static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
8224 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8225 HRESULT hr;
8227 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8229 EnterCriticalSection(&source->cs);
8230 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
8232 source->start_offset = source->system_time = source->clock_time = 0;
8234 LeaveCriticalSection(&source->cs);
8236 return hr;
8239 static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
8241 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8242 HRESULT hr;
8244 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8246 EnterCriticalSection(&source->cs);
8247 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
8249 system_time_source_update_clock_time(source, system_time);
8251 LeaveCriticalSection(&source->cs);
8253 return hr;
8256 static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
8258 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8259 HRESULT hr;
8261 TRACE("%p, %s.\n", iface, debugstr_time(system_time));
8263 EnterCriticalSection(&source->cs);
8264 if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
8266 source->system_time = system_time;
8268 LeaveCriticalSection(&source->cs);
8270 return hr;
8273 static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
8275 struct system_time_source *source = impl_from_IMFClockStateSink(iface);
8276 double intpart;
8278 TRACE("%p, %s, %f.\n", iface, debugstr_time(system_time), rate);
8280 if (rate == 0.0f)
8281 return MF_E_UNSUPPORTED_RATE;
8283 modf(rate, &intpart);
8285 EnterCriticalSection(&source->cs);
8286 source->rate = rate;
8287 source->i_rate = rate == intpart ? rate : 0;
8288 LeaveCriticalSection(&source->cs);
8290 return S_OK;
8293 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
8295 system_time_source_sink_QueryInterface,
8296 system_time_source_sink_AddRef,
8297 system_time_source_sink_Release,
8298 system_time_source_sink_OnClockStart,
8299 system_time_source_sink_OnClockStop,
8300 system_time_source_sink_OnClockPause,
8301 system_time_source_sink_OnClockRestart,
8302 system_time_source_sink_OnClockSetRate,
8305 /***********************************************************************
8306 * MFCreateSystemTimeSource (mfplat.@)
8308 HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
8310 struct system_time_source *object;
8311 HRESULT hr;
8313 TRACE("%p.\n", time_source);
8315 object = calloc(1, sizeof(*object));
8316 if (!object)
8317 return E_OUTOFMEMORY;
8319 object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
8320 object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
8321 object->refcount = 1;
8322 object->rate = 1.0f;
8323 object->i_rate = 1;
8324 InitializeCriticalSection(&object->cs);
8326 if (FAILED(hr = create_system_clock(&object->clock)))
8328 IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
8329 return hr;
8332 *time_source = &object->IMFPresentationTimeSource_iface;
8334 return S_OK;
8337 struct async_create_file
8339 IRtwqAsyncCallback IRtwqAsyncCallback_iface;
8340 LONG refcount;
8341 MF_FILE_ACCESSMODE access_mode;
8342 MF_FILE_OPENMODE open_mode;
8343 MF_FILE_FLAGS flags;
8344 WCHAR *path;
8347 struct async_create_file_result
8349 struct list entry;
8350 IRtwqAsyncResult *result;
8351 IMFByteStream *stream;
8354 static struct list async_create_file_results = LIST_INIT(async_create_file_results);
8355 static CRITICAL_SECTION async_create_file_cs = { NULL, -1, 0, 0, 0, 0 };
8357 static struct async_create_file *impl_from_create_file_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
8359 return CONTAINING_RECORD(iface, struct async_create_file, IRtwqAsyncCallback_iface);
8362 static HRESULT WINAPI async_create_file_callback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
8364 if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) ||
8365 IsEqualIID(riid, &IID_IUnknown))
8367 *obj = iface;
8368 IRtwqAsyncCallback_AddRef(iface);
8369 return S_OK;
8372 *obj = NULL;
8373 return E_NOINTERFACE;
8376 static ULONG WINAPI async_create_file_callback_AddRef(IRtwqAsyncCallback *iface)
8378 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8379 ULONG refcount = InterlockedIncrement(&async->refcount);
8381 TRACE("%p, refcount %lu.\n", iface, refcount);
8383 return refcount;
8386 static ULONG WINAPI async_create_file_callback_Release(IRtwqAsyncCallback *iface)
8388 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8389 ULONG refcount = InterlockedDecrement(&async->refcount);
8391 TRACE("%p, refcount %lu.\n", iface, refcount);
8393 if (!refcount)
8395 free(async->path);
8396 free(async);
8399 return refcount;
8402 static HRESULT WINAPI async_create_file_callback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue)
8404 return E_NOTIMPL;
8407 static HRESULT WINAPI async_create_file_callback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result)
8409 struct async_create_file *async = impl_from_create_file_IRtwqAsyncCallback(iface);
8410 IRtwqAsyncResult *caller;
8411 IMFByteStream *stream;
8412 HRESULT hr;
8414 caller = (IRtwqAsyncResult *)IRtwqAsyncResult_GetStateNoAddRef(result);
8416 hr = MFCreateFile(async->access_mode, async->open_mode, async->flags, async->path, &stream);
8417 if (SUCCEEDED(hr))
8419 struct async_create_file_result *result_item;
8421 result_item = malloc(sizeof(*result_item));
8422 if (result_item)
8424 result_item->result = caller;
8425 IRtwqAsyncResult_AddRef(caller);
8426 result_item->stream = stream;
8427 IMFByteStream_AddRef(stream);
8429 EnterCriticalSection(&async_create_file_cs);
8430 list_add_tail(&async_create_file_results, &result_item->entry);
8431 LeaveCriticalSection(&async_create_file_cs);
8434 IMFByteStream_Release(stream);
8436 else
8437 IRtwqAsyncResult_SetStatus(caller, hr);
8439 RtwqInvokeCallback(caller);
8441 return S_OK;
8444 static const IRtwqAsyncCallbackVtbl async_create_file_callback_vtbl =
8446 async_create_file_callback_QueryInterface,
8447 async_create_file_callback_AddRef,
8448 async_create_file_callback_Release,
8449 async_create_file_callback_GetParameters,
8450 async_create_file_callback_Invoke,
8453 /***********************************************************************
8454 * MFBeginCreateFile (mfplat.@)
8456 HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags,
8457 const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie)
8459 struct async_create_file *async = NULL;
8460 IRtwqAsyncResult *caller, *item = NULL;
8461 HRESULT hr;
8463 TRACE("%#x, %#x, %#x, %s, %p, %p, %p.\n", access_mode, open_mode, flags, debugstr_w(path), callback, state,
8464 cancel_cookie);
8466 if (cancel_cookie)
8467 *cancel_cookie = NULL;
8469 if (FAILED(hr = RtwqCreateAsyncResult(NULL, (IRtwqAsyncCallback *)callback, state, &caller)))
8470 return hr;
8472 if (!(async = malloc(sizeof(*async))))
8474 hr = E_OUTOFMEMORY;
8475 goto failed;
8478 async->IRtwqAsyncCallback_iface.lpVtbl = &async_create_file_callback_vtbl;
8479 async->refcount = 1;
8480 async->access_mode = access_mode;
8481 async->open_mode = open_mode;
8482 async->flags = flags;
8483 if (!(async->path = wcsdup(path)))
8485 hr = E_OUTOFMEMORY;
8486 goto failed;
8489 hr = RtwqCreateAsyncResult(NULL, &async->IRtwqAsyncCallback_iface, (IUnknown *)caller, &item);
8490 if (FAILED(hr))
8491 goto failed;
8493 if (cancel_cookie)
8495 *cancel_cookie = (IUnknown *)caller;
8496 IUnknown_AddRef(*cancel_cookie);
8499 hr = RtwqInvokeCallback(item);
8501 failed:
8502 if (async)
8503 IRtwqAsyncCallback_Release(&async->IRtwqAsyncCallback_iface);
8504 if (item)
8505 IRtwqAsyncResult_Release(item);
8506 if (caller)
8507 IRtwqAsyncResult_Release(caller);
8509 return hr;
8512 static HRESULT async_create_file_pull_result(IUnknown *unk, IMFByteStream **stream)
8514 struct async_create_file_result *item;
8515 HRESULT hr = MF_E_UNEXPECTED;
8516 IRtwqAsyncResult *result;
8518 *stream = NULL;
8520 if (FAILED(IUnknown_QueryInterface(unk, &IID_IRtwqAsyncResult, (void **)&result)))
8521 return hr;
8523 EnterCriticalSection(&async_create_file_cs);
8525 LIST_FOR_EACH_ENTRY(item, &async_create_file_results, struct async_create_file_result, entry)
8527 if (result == item->result)
8529 *stream = item->stream;
8530 IRtwqAsyncResult_Release(item->result);
8531 list_remove(&item->entry);
8532 free(item);
8533 break;
8537 LeaveCriticalSection(&async_create_file_cs);
8539 if (*stream)
8540 hr = IRtwqAsyncResult_GetStatus(result);
8542 IRtwqAsyncResult_Release(result);
8544 return hr;
8547 /***********************************************************************
8548 * MFEndCreateFile (mfplat.@)
8550 HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream)
8552 TRACE("%p, %p.\n", result, stream);
8554 return async_create_file_pull_result((IUnknown *)result, stream);
8557 /***********************************************************************
8558 * MFCancelCreateFile (mfplat.@)
8560 HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
8562 IMFByteStream *stream = NULL;
8563 HRESULT hr;
8565 TRACE("%p.\n", cancel_cookie);
8567 hr = async_create_file_pull_result(cancel_cookie, &stream);
8569 if (stream)
8570 IMFByteStream_Release(stream);
8572 return hr;
8575 /***********************************************************************
8576 * MFRegisterLocalSchemeHandler (mfplat.@)
8578 HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate)
8580 struct local_handler *handler;
8582 TRACE("%s, %p.\n", debugstr_w(scheme), activate);
8584 if (!scheme || !activate)
8585 return E_INVALIDARG;
8587 if (!(handler = malloc(sizeof(*handler))))
8588 return E_OUTOFMEMORY;
8590 if (!(handler->u.scheme = wcsdup(scheme)))
8592 free(handler);
8593 return E_OUTOFMEMORY;
8595 handler->activate = activate;
8596 IMFActivate_AddRef(handler->activate);
8598 EnterCriticalSection(&local_handlers_section);
8599 list_add_head(&local_scheme_handlers, &handler->entry);
8600 LeaveCriticalSection(&local_handlers_section);
8602 return S_OK;
8605 /***********************************************************************
8606 * MFRegisterLocalByteStreamHandler (mfplat.@)
8608 HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate)
8610 struct local_handler *handler;
8612 TRACE("%s, %s, %p.\n", debugstr_w(extension), debugstr_w(mime), activate);
8614 if ((!extension && !mime) || !activate)
8615 return E_INVALIDARG;
8617 if (!(handler = calloc(1, sizeof(*handler))))
8618 return E_OUTOFMEMORY;
8620 if (extension && !(handler->u.bytestream.extension = wcsdup(extension)))
8621 goto failed;
8622 if (mime && !(handler->u.bytestream.mime = wcsdup(mime)))
8623 goto failed;
8625 EnterCriticalSection(&local_handlers_section);
8626 list_add_head(&local_bytestream_handlers, &handler->entry);
8627 LeaveCriticalSection(&local_handlers_section);
8629 return S_OK;
8631 failed:
8632 free(handler->u.bytestream.extension);
8633 free(handler->u.bytestream.mime);
8634 free(handler);
8636 return E_OUTOFMEMORY;
8639 struct property_store
8641 IPropertyStore IPropertyStore_iface;
8642 LONG refcount;
8643 CRITICAL_SECTION cs;
8644 size_t count, capacity;
8645 struct
8647 PROPERTYKEY key;
8648 PROPVARIANT value;
8649 } *values;
8652 static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
8654 return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
8657 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
8659 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8661 if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
8663 *obj = iface;
8664 IPropertyStore_AddRef(iface);
8665 return S_OK;
8668 *obj = NULL;
8669 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
8670 return E_NOINTERFACE;
8673 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
8675 struct property_store *store = impl_from_IPropertyStore(iface);
8676 ULONG refcount = InterlockedIncrement(&store->refcount);
8678 TRACE("%p, refcount %ld.\n", iface, refcount);
8680 return refcount;
8683 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
8685 struct property_store *store = impl_from_IPropertyStore(iface);
8686 ULONG refcount = InterlockedDecrement(&store->refcount);
8688 TRACE("%p, refcount %ld.\n", iface, refcount);
8690 if (!refcount)
8692 DeleteCriticalSection(&store->cs);
8693 free(store->values);
8694 free(store);
8697 return refcount;
8700 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
8702 struct property_store *store = impl_from_IPropertyStore(iface);
8704 TRACE("%p, %p.\n", iface, count);
8706 if (!count)
8707 return E_INVALIDARG;
8709 EnterCriticalSection(&store->cs);
8710 *count = store->count;
8711 LeaveCriticalSection(&store->cs);
8712 return S_OK;
8715 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
8717 struct property_store *store = impl_from_IPropertyStore(iface);
8719 TRACE("%p, %lu, %p.\n", iface, index, key);
8721 EnterCriticalSection(&store->cs);
8723 if (index >= store->count)
8725 LeaveCriticalSection(&store->cs);
8726 return E_INVALIDARG;
8729 *key = store->values[index].key;
8731 LeaveCriticalSection(&store->cs);
8732 return S_OK;
8735 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
8737 struct property_store *store = impl_from_IPropertyStore(iface);
8738 unsigned int i;
8740 TRACE("%p, %p, %p.\n", iface, key, value);
8742 if (!value)
8743 return E_INVALIDARG;
8745 if (!key)
8746 return S_FALSE;
8748 EnterCriticalSection(&store->cs);
8750 for (i = 0; i < store->count; ++i)
8752 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8754 PropVariantCopy(value, &store->values[i].value);
8755 LeaveCriticalSection(&store->cs);
8756 return S_OK;
8760 LeaveCriticalSection(&store->cs);
8761 return S_FALSE;
8764 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
8766 struct property_store *store = impl_from_IPropertyStore(iface);
8767 unsigned int i;
8769 TRACE("%p, %p, %p.\n", iface, key, value);
8771 EnterCriticalSection(&store->cs);
8773 for (i = 0; i < store->count; ++i)
8775 if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
8777 PropVariantCopy(&store->values[i].value, value);
8778 LeaveCriticalSection(&store->cs);
8779 return S_OK;
8783 if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
8785 LeaveCriticalSection(&store->cs);
8786 return E_OUTOFMEMORY;
8789 store->values[store->count].key = *key;
8790 PropVariantCopy(&store->values[store->count].value, value);
8791 ++store->count;
8793 LeaveCriticalSection(&store->cs);
8794 return S_OK;
8797 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
8799 TRACE("%p.\n", iface);
8801 return E_NOTIMPL;
8804 static const IPropertyStoreVtbl property_store_vtbl =
8806 property_store_QueryInterface,
8807 property_store_AddRef,
8808 property_store_Release,
8809 property_store_GetCount,
8810 property_store_GetAt,
8811 property_store_GetValue,
8812 property_store_SetValue,
8813 property_store_Commit,
8816 /***********************************************************************
8817 * CreatePropertyStore (mfplat.@)
8819 HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
8821 struct property_store *object;
8823 TRACE("%p.\n", store);
8825 if (!store)
8826 return E_INVALIDARG;
8828 if (!(object = calloc(1, sizeof(*object))))
8829 return E_OUTOFMEMORY;
8831 object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
8832 object->refcount = 1;
8833 InitializeCriticalSection(&object->cs);
8835 TRACE("Created store %p.\n", object);
8836 *store = &object->IPropertyStore_iface;
8838 return S_OK;
8841 struct shared_dxgi_manager
8843 IMFDXGIDeviceManager *manager;
8844 unsigned int token;
8845 unsigned int locks;
8848 static struct shared_dxgi_manager shared_dm;
8849 static CRITICAL_SECTION shared_dm_cs = { NULL, -1, 0, 0, 0, 0 };
8851 enum dxgi_device_handle_flags
8853 DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
8854 DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
8855 DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
8858 struct dxgi_device_manager
8860 IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
8861 LONG refcount;
8862 UINT token;
8863 IUnknown *device;
8865 unsigned int *handles;
8866 size_t count;
8867 size_t capacity;
8869 unsigned int locks;
8870 unsigned int locking_tid;
8872 CRITICAL_SECTION cs;
8873 CONDITION_VARIABLE lock;
8876 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
8878 return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
8881 static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
8883 if (!hdevice || hdevice > ULongToHandle(manager->count))
8884 return E_HANDLE;
8885 *idx = (ULONG_PTR)hdevice - 1;
8886 return S_OK;
8889 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
8891 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
8893 if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
8894 IsEqualGUID(riid, &IID_IUnknown))
8896 *obj = iface;
8897 IMFDXGIDeviceManager_AddRef(iface);
8898 return S_OK;
8901 WARN("Unsupported %s.\n", debugstr_guid(riid));
8902 *obj = NULL;
8903 return E_NOINTERFACE;
8906 static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
8908 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8909 ULONG refcount = InterlockedIncrement(&manager->refcount);
8911 TRACE("%p, refcount %lu.\n", iface, refcount);
8913 return refcount;
8916 static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
8918 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8919 ULONG refcount = InterlockedDecrement(&manager->refcount);
8921 TRACE("%p, refcount %lu.\n", iface, refcount);
8923 if (!refcount)
8925 if (manager->device)
8926 IUnknown_Release(manager->device);
8927 DeleteCriticalSection(&manager->cs);
8928 free(manager->handles);
8929 free(manager);
8932 return refcount;
8935 static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
8937 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
8938 return;
8940 manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8941 manager->locks++;
8944 static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
8946 if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
8947 return;
8949 manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
8950 if (!--manager->locks)
8951 manager->locking_tid = 0;
8954 static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
8956 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8957 HRESULT hr;
8958 size_t idx;
8960 TRACE("%p, %p.\n", iface, hdevice);
8962 EnterCriticalSection(&manager->cs);
8964 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8966 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
8968 dxgi_device_manager_unlock_handle(manager, idx);
8969 manager->handles[idx] = 0;
8970 if (idx == manager->count - 1)
8971 manager->count--;
8973 else
8974 hr = E_HANDLE;
8977 LeaveCriticalSection(&manager->cs);
8979 WakeAllConditionVariable(&manager->lock);
8981 return hr;
8984 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice,
8985 REFIID riid, void **service)
8987 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
8988 HRESULT hr;
8989 size_t idx;
8991 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service);
8993 EnterCriticalSection(&manager->cs);
8995 if (!manager->device)
8996 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
8997 else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
8999 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
9000 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9001 else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
9002 hr = IUnknown_QueryInterface(manager->device, riid, service);
9003 else
9004 hr = E_HANDLE;
9007 LeaveCriticalSection(&manager->cs);
9009 return hr;
9012 static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
9013 REFIID riid, void **obj, BOOL block)
9015 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9016 HRESULT hr;
9017 size_t idx;
9019 TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
9021 EnterCriticalSection(&manager->cs);
9023 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9025 if (!manager->device)
9027 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
9029 else if (manager->locking_tid == GetCurrentThreadId())
9031 if (SUCCEEDED(hr = IUnknown_QueryInterface(manager->device, riid, obj)))
9032 dxgi_device_manager_lock_handle(manager, idx);
9034 else if (manager->locking_tid && !block)
9036 hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
9038 else
9040 while (manager->locking_tid)
9042 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
9045 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9047 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
9048 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9049 else if (SUCCEEDED(hr = IUnknown_QueryInterface(manager->device, riid, obj)))
9051 manager->locking_tid = GetCurrentThreadId();
9052 dxgi_device_manager_lock_handle(manager, idx);
9058 LeaveCriticalSection(&manager->cs);
9060 return hr;
9063 static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
9065 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9066 HRESULT hr = S_OK;
9067 size_t i;
9069 TRACE("%p, %p.\n", iface, hdevice);
9071 *hdevice = NULL;
9073 EnterCriticalSection(&manager->cs);
9075 if (!manager->device)
9076 hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
9077 else
9079 for (i = 0; i < manager->count; ++i)
9081 if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
9083 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
9084 *hdevice = ULongToHandle(i + 1);
9085 break;
9089 if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
9090 sizeof(*manager->handles)))
9092 *hdevice = ULongToHandle(manager->count + 1);
9093 manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
9095 else
9096 hr = E_OUTOFMEMORY;
9099 LeaveCriticalSection(&manager->cs);
9101 return hr;
9104 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
9106 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9107 IUnknown *d3d_device;
9108 size_t i;
9110 TRACE("%p, %p, %u.\n", iface, device, token);
9112 if (!device || token != manager->token)
9113 return E_INVALIDARG;
9115 if (FAILED(IUnknown_QueryInterface(device, &IID_ID3D11Device, (void **)&d3d_device)))
9117 if (FAILED(IUnknown_QueryInterface(device, &IID_ID3D12Device, (void **)&d3d_device)))
9119 WARN("Unsupported device interface.\n");
9120 return E_INVALIDARG;
9124 EnterCriticalSection(&manager->cs);
9126 if (manager->device)
9128 for (i = 0; i < manager->count; ++i)
9130 manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
9131 manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
9133 manager->locking_tid = 0;
9134 manager->locks = 0;
9135 IUnknown_Release(manager->device);
9137 manager->device = d3d_device;
9139 LeaveCriticalSection(&manager->cs);
9141 WakeAllConditionVariable(&manager->lock);
9143 return S_OK;
9146 static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
9148 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9149 HRESULT hr;
9150 size_t idx;
9152 TRACE("%p, %p.\n", iface, hdevice);
9154 EnterCriticalSection(&manager->cs);
9156 if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9158 if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
9159 hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
9160 else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
9161 hr = E_HANDLE;
9164 LeaveCriticalSection(&manager->cs);
9166 return hr;
9169 static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
9170 BOOL savestate)
9172 struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
9173 HRESULT hr = E_FAIL;
9174 size_t idx;
9176 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
9178 EnterCriticalSection(&manager->cs);
9180 if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
9182 hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
9183 if (SUCCEEDED(hr))
9184 dxgi_device_manager_unlock_handle(manager, idx);
9187 LeaveCriticalSection(&manager->cs);
9189 WakeAllConditionVariable(&manager->lock);
9191 return hr;
9194 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
9196 dxgi_device_manager_QueryInterface,
9197 dxgi_device_manager_AddRef,
9198 dxgi_device_manager_Release,
9199 dxgi_device_manager_CloseDeviceHandle,
9200 dxgi_device_manager_GetVideoService,
9201 dxgi_device_manager_LockDevice,
9202 dxgi_device_manager_OpenDeviceHandle,
9203 dxgi_device_manager_ResetDevice,
9204 dxgi_device_manager_TestDevice,
9205 dxgi_device_manager_UnlockDevice,
9208 /***********************************************************************
9209 * MFCreateDXGIDeviceManager (mfplat.@)
9211 HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
9213 struct dxgi_device_manager *object;
9215 TRACE("%p, %p.\n", token, manager);
9217 if (!token || !manager)
9218 return E_POINTER;
9220 if (!(object = calloc(1, sizeof(*object))))
9221 return E_OUTOFMEMORY;
9223 object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
9224 object->refcount = 1;
9225 object->token = GetTickCount();
9226 InitializeCriticalSection(&object->cs);
9227 InitializeConditionVariable(&object->lock);
9229 TRACE("Created device manager: %p, token: %u.\n", object, object->token);
9231 *token = object->token;
9232 *manager = &object->IMFDXGIDeviceManager_iface;
9234 return S_OK;
9237 /***********************************************************************
9238 * MFLockDXGIDeviceManager (mfplat.@)
9240 HRESULT WINAPI MFLockDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
9242 HRESULT hr = S_OK;
9244 TRACE("%p, %p.\n", token, manager);
9246 EnterCriticalSection(&shared_dm_cs);
9248 if (!shared_dm.manager)
9249 hr = MFCreateDXGIDeviceManager(&shared_dm.token, &shared_dm.manager);
9251 if (SUCCEEDED(hr))
9253 *manager = shared_dm.manager;
9254 IMFDXGIDeviceManager_AddRef(*manager);
9255 shared_dm.locks++;
9257 if (token) *token = shared_dm.token;
9260 LeaveCriticalSection(&shared_dm_cs);
9262 return hr;
9265 /***********************************************************************
9266 * MFUnlockDXGIDeviceManager (mfplat.@)
9268 HRESULT WINAPI MFUnlockDXGIDeviceManager(void)
9270 TRACE("\n");
9272 EnterCriticalSection(&shared_dm_cs);
9274 if (shared_dm.manager)
9276 IMFDXGIDeviceManager_Release(shared_dm.manager);
9277 if (!--shared_dm.locks)
9279 shared_dm.manager = NULL;
9280 shared_dm.token = 0;
9284 LeaveCriticalSection(&shared_dm_cs);
9286 return S_OK;
9291 * MFllMulDiv implementation is derived from gstreamer utility functions code (gstutils.c),
9292 * released under LGPL2. Full authors list follows.
9293 * ===================================================================================
9294 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
9295 * 2000 Wim Taymans <wtay@chello.be>
9296 * 2002 Thomas Vander Stichele <thomas@apestaart.org>
9297 * 2004 Wim Taymans <wim@fluendo.com>
9298 * 2015 Jan Schmidt <jan@centricular.com>
9299 * ===================================================================================
9302 static void llmult128(ULARGE_INTEGER *c1, ULARGE_INTEGER *c0, LONGLONG val, LONGLONG num)
9304 ULARGE_INTEGER a1, b0, v, n;
9306 v.QuadPart = llabs(val);
9307 n.QuadPart = llabs(num);
9309 /* do 128 bits multiply
9310 * nh nl
9311 * * vh vl
9312 * ----------
9313 * a0 = vl * nl
9314 * a1 = vl * nh
9315 * b0 = vh * nl
9316 * b1 = + vh * nh
9317 * -------------------
9318 * c1h c1l c0h c0l
9320 * "a0" is optimized away, result is stored directly in c0. "b1" is
9321 * optimized away, result is stored directly in c1.
9323 c0->QuadPart = (ULONGLONG)v.LowPart * n.LowPart;
9324 a1.QuadPart = (ULONGLONG)v.LowPart * n.HighPart;
9325 b0.QuadPart = (ULONGLONG)v.HighPart * n.LowPart;
9327 /* add the high word of a0 to the low words of a1 and b0 using c1 as
9328 * scratch space to capture the carry. the low word of the result becomes
9329 * the final high word of c0 */
9330 c1->QuadPart = (ULONGLONG)c0->HighPart + a1.LowPart + b0.LowPart;
9331 c0->HighPart = c1->LowPart;
9333 /* add the carry from the result above (found in the high word of c1) and
9334 * the high words of a1 and b0 to b1, the result is c1. */
9335 c1->QuadPart = (ULONGLONG)v.HighPart * n.HighPart + c1->HighPart + a1.HighPart + b0.HighPart;
9338 static ULONGLONG lldiv128(ULARGE_INTEGER c1, ULARGE_INTEGER c0, LONGLONG denom)
9340 ULARGE_INTEGER q1, q0, rhat;
9341 ULARGE_INTEGER v, cmp1, cmp2;
9342 DWORD s = 0;
9344 v.QuadPart = llabs(denom);
9346 /* 64bit numerator */
9347 if (c1.QuadPart == 0)
9348 return c0.QuadPart / v.QuadPart;
9350 /* 96bit numerator, 32bit denominator */
9351 if (v.HighPart == 0 && c1.HighPart == 0)
9353 ULONGLONG low = c0.LowPart, high = c0.HighPart + ((ULONGLONG)c1.LowPart << 32);
9354 low += (high % v.LowPart) << 32;
9355 return ((high / v.LowPart) << 32) + (low / v.LowPart);
9358 /* 128bit numerator, 32bit denominator */
9359 if (v.HighPart == 0)
9360 return UI64_MAX;
9362 /* count number of leading zeroes */
9363 BitScanReverse(&s, v.HighPart);
9364 s = 31 - s;
9366 if (s)
9368 /* normalize divisor and dividend */
9369 v.QuadPart <<= s;
9370 c1.QuadPart = (c1.QuadPart << s) | (c0.HighPart >> (32 - s));
9371 c0.QuadPart <<= s;
9374 q1.QuadPart = c1.QuadPart / v.HighPart;
9375 rhat.QuadPart = c1.QuadPart - q1.QuadPart * v.HighPart;
9377 cmp1.HighPart = rhat.LowPart;
9378 cmp1.LowPart = c0.HighPart;
9379 cmp2.QuadPart = q1.QuadPart * v.LowPart;
9381 while (q1.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9383 q1.QuadPart--;
9384 rhat.QuadPart += v.HighPart;
9385 if (rhat.HighPart)
9386 break;
9387 cmp1.HighPart = rhat.LowPart;
9388 cmp2.QuadPart -= v.LowPart;
9390 c1.HighPart = c1.LowPart;
9391 c1.LowPart = c0.HighPart;
9392 c1.QuadPart -= q1.QuadPart * v.QuadPart;
9393 q0.QuadPart = c1.QuadPart / v.HighPart;
9394 rhat.QuadPart = c1.QuadPart - q0.QuadPart * v.HighPart;
9396 cmp1.HighPart = rhat.LowPart;
9397 cmp1.LowPart = c0.LowPart;
9398 cmp2.QuadPart = q0.QuadPart * v.LowPart;
9400 while (q0.HighPart || cmp2.QuadPart > cmp1.QuadPart)
9402 q0.QuadPart--;
9403 rhat.QuadPart += v.HighPart;
9404 if (rhat.HighPart)
9405 break;
9406 cmp1.HighPart = rhat.LowPart;
9407 cmp2.QuadPart -= v.LowPart;
9409 q0.HighPart += q1.LowPart;
9411 return q0.QuadPart;
9414 /***********************************************************************
9415 * MFllMulDiv (mfplat.@)
9417 LONGLONG WINAPI MFllMulDiv(LONGLONG val, LONGLONG num, LONGLONG denom, LONGLONG factor)
9419 #define LLOVERFLOW (sign ? I64_MIN : I64_MAX)
9420 unsigned int sign, factor_sign, denom_sign;
9421 ULARGE_INTEGER c1, c0;
9422 ULONGLONG ret;
9424 TRACE("%s, %s, %s, %s.\n", wine_dbgstr_longlong(val), wine_dbgstr_longlong(num),
9425 wine_dbgstr_longlong(denom), wine_dbgstr_longlong(factor));
9427 /* compute 128-bit numerator product */
9428 llmult128(&c1, &c0, val, num);
9430 sign = (val < 0) ^ (num < 0);
9431 factor_sign = factor < 0;
9432 denom_sign = denom < 0;
9434 factor = llabs(factor);
9435 if (sign == factor_sign)
9437 if (UI64_MAX - c0.QuadPart < factor)
9439 if (c1.QuadPart == UI64_MAX) return LLOVERFLOW;
9440 c1.QuadPart++;
9442 c0.QuadPart += factor;
9444 else
9446 if (c0.QuadPart >= factor)
9447 c0.QuadPart -= factor;
9448 else
9450 if (c1.QuadPart)
9451 c1.QuadPart--;
9452 else
9453 sign = !sign;
9455 c0.QuadPart = factor - c0.QuadPart;
9459 if (c1.QuadPart >= denom) return LLOVERFLOW;
9461 /* compute quotient, fits in 64 bits */
9462 ret = lldiv128(c1, c0, denom);
9463 sign ^= denom_sign;
9464 if (ret >= I64_MAX) return LLOVERFLOW;
9465 return sign ? -(LONGLONG)ret : ret;
9466 #undef LLOVERFLOW
9469 /***********************************************************************
9470 * MFCreatePathFromURL (mfplat.@)
9472 HRESULT WINAPI MFCreatePathFromURL(const WCHAR *url, WCHAR **ret_path)
9474 WCHAR path[MAX_PATH];
9475 DWORD length;
9476 HRESULT hr;
9478 TRACE("%s, %p.\n", debugstr_w(url), ret_path);
9480 if (!url || !ret_path)
9481 return E_POINTER;
9483 length = ARRAY_SIZE(path);
9484 if (FAILED(hr = PathCreateFromUrlW(url, path, &length, 0)))
9485 return hr;
9487 if (!(*ret_path = CoTaskMemAlloc((length + 1) * sizeof(*path))))
9488 return E_OUTOFMEMORY;
9490 memcpy(*ret_path, path, (length + 1) * sizeof(*path));
9491 return S_OK;